xref: /aosp_15_r20/art/tools/jfuzz/run_jfuzz_test.py (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*795d594fSAndroid Build Coastguard Worker#
3*795d594fSAndroid Build Coastguard Worker# Copyright (C) 2016 The Android Open Source Project
4*795d594fSAndroid Build Coastguard Worker#
5*795d594fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*795d594fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*795d594fSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*795d594fSAndroid Build Coastguard Worker#
9*795d594fSAndroid Build Coastguard Worker#   http://www.apache.org/licenses/LICENSE-2.0
10*795d594fSAndroid Build Coastguard Worker#
11*795d594fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*795d594fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*795d594fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*795d594fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*795d594fSAndroid Build Coastguard Worker# limitations under the License.
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Workerimport abc
18*795d594fSAndroid Build Coastguard Workerimport argparse
19*795d594fSAndroid Build Coastguard Workerimport filecmp
20*795d594fSAndroid Build Coastguard Workerimport os
21*795d594fSAndroid Build Coastguard Workerimport shlex
22*795d594fSAndroid Build Coastguard Workerimport shutil
23*795d594fSAndroid Build Coastguard Workerimport subprocess
24*795d594fSAndroid Build Coastguard Workerimport sys
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Workerfrom glob import glob
27*795d594fSAndroid Build Coastguard Workerfrom subprocess import DEVNULL
28*795d594fSAndroid Build Coastguard Workerfrom tempfile import mkdtemp
29*795d594fSAndroid Build Coastguard Worker
30*795d594fSAndroid Build Coastguard Workersys.path.append(os.path.dirname(os.path.dirname(
31*795d594fSAndroid Build Coastguard Worker    os.path.realpath(__file__))))
32*795d594fSAndroid Build Coastguard Worker
33*795d594fSAndroid Build Coastguard Workerfrom common.common import RetCode
34*795d594fSAndroid Build Coastguard Workerfrom common.common import CommandListToCommandString
35*795d594fSAndroid Build Coastguard Workerfrom common.common import FatalError
36*795d594fSAndroid Build Coastguard Workerfrom common.common import GetEnvVariableOrError
37*795d594fSAndroid Build Coastguard Workerfrom common.common import RunCommand
38*795d594fSAndroid Build Coastguard Workerfrom common.common import RunCommandForOutput
39*795d594fSAndroid Build Coastguard Workerfrom common.common import DeviceTestEnv
40*795d594fSAndroid Build Coastguard Worker
41*795d594fSAndroid Build Coastguard Worker# Return codes supported by bisection bug search.
42*795d594fSAndroid Build Coastguard WorkerBISECTABLE_RET_CODES = (RetCode.SUCCESS, RetCode.ERROR, RetCode.TIMEOUT)
43*795d594fSAndroid Build Coastguard Worker
44*795d594fSAndroid Build Coastguard Worker
45*795d594fSAndroid Build Coastguard Workerdef GetExecutionModeRunner(dexer, debug_info, device, mode):
46*795d594fSAndroid Build Coastguard Worker  """Returns a runner for the given execution mode.
47*795d594fSAndroid Build Coastguard Worker
48*795d594fSAndroid Build Coastguard Worker  Args:
49*795d594fSAndroid Build Coastguard Worker    dexer: string, defines dexer
50*795d594fSAndroid Build Coastguard Worker    debug_info: boolean, if True include debugging info
51*795d594fSAndroid Build Coastguard Worker    device: string, target device serial number (or None)
52*795d594fSAndroid Build Coastguard Worker    mode: string, execution mode
53*795d594fSAndroid Build Coastguard Worker  Returns:
54*795d594fSAndroid Build Coastguard Worker    TestRunner with given execution mode
55*795d594fSAndroid Build Coastguard Worker  Raises:
56*795d594fSAndroid Build Coastguard Worker    FatalError: error for unknown execution mode
57*795d594fSAndroid Build Coastguard Worker  """
58*795d594fSAndroid Build Coastguard Worker  if mode == 'ri':
59*795d594fSAndroid Build Coastguard Worker    return TestRunnerRIOnHost(debug_info)
60*795d594fSAndroid Build Coastguard Worker  if mode == 'hint':
61*795d594fSAndroid Build Coastguard Worker    return TestRunnerArtIntOnHost(dexer, debug_info)
62*795d594fSAndroid Build Coastguard Worker  if mode == 'hopt':
63*795d594fSAndroid Build Coastguard Worker    return TestRunnerArtOptOnHost(dexer, debug_info)
64*795d594fSAndroid Build Coastguard Worker  if mode == 'tint':
65*795d594fSAndroid Build Coastguard Worker    return TestRunnerArtIntOnTarget(dexer, debug_info, device)
66*795d594fSAndroid Build Coastguard Worker  if mode == 'topt':
67*795d594fSAndroid Build Coastguard Worker    return TestRunnerArtOptOnTarget(dexer, debug_info, device)
68*795d594fSAndroid Build Coastguard Worker  raise FatalError('Unknown execution mode')
69*795d594fSAndroid Build Coastguard Worker
70*795d594fSAndroid Build Coastguard Worker
71*795d594fSAndroid Build Coastguard Worker#
72*795d594fSAndroid Build Coastguard Worker# Execution mode classes.
73*795d594fSAndroid Build Coastguard Worker#
74*795d594fSAndroid Build Coastguard Worker
75*795d594fSAndroid Build Coastguard Worker
76*795d594fSAndroid Build Coastguard Workerclass TestRunner(object):
77*795d594fSAndroid Build Coastguard Worker  """Abstraction for running a test in a particular execution mode."""
78*795d594fSAndroid Build Coastguard Worker  __meta_class__ = abc.ABCMeta
79*795d594fSAndroid Build Coastguard Worker
80*795d594fSAndroid Build Coastguard Worker  @abc.abstractproperty
81*795d594fSAndroid Build Coastguard Worker  def description(self):
82*795d594fSAndroid Build Coastguard Worker    """Returns a description string of the execution mode."""
83*795d594fSAndroid Build Coastguard Worker
84*795d594fSAndroid Build Coastguard Worker  @abc.abstractproperty
85*795d594fSAndroid Build Coastguard Worker  def id(self):
86*795d594fSAndroid Build Coastguard Worker    """Returns a short string that uniquely identifies the execution mode."""
87*795d594fSAndroid Build Coastguard Worker
88*795d594fSAndroid Build Coastguard Worker  @property
89*795d594fSAndroid Build Coastguard Worker  def output_file(self):
90*795d594fSAndroid Build Coastguard Worker    return self.id + '_out.txt'
91*795d594fSAndroid Build Coastguard Worker
92*795d594fSAndroid Build Coastguard Worker  @abc.abstractmethod
93*795d594fSAndroid Build Coastguard Worker  def GetBisectionSearchArgs(self):
94*795d594fSAndroid Build Coastguard Worker    """Get arguments to pass to bisection search tool.
95*795d594fSAndroid Build Coastguard Worker
96*795d594fSAndroid Build Coastguard Worker    Returns:
97*795d594fSAndroid Build Coastguard Worker      list of strings - arguments for bisection search tool, or None if
98*795d594fSAndroid Build Coastguard Worker      runner is not bisectable
99*795d594fSAndroid Build Coastguard Worker    """
100*795d594fSAndroid Build Coastguard Worker
101*795d594fSAndroid Build Coastguard Worker  @abc.abstractmethod
102*795d594fSAndroid Build Coastguard Worker  def CompileAndRunTest(self):
103*795d594fSAndroid Build Coastguard Worker    """Compile and run the generated test.
104*795d594fSAndroid Build Coastguard Worker
105*795d594fSAndroid Build Coastguard Worker    Ensures that the current Test.java in the temporary directory is compiled
106*795d594fSAndroid Build Coastguard Worker    and executed under the current execution mode. On success, transfers the
107*795d594fSAndroid Build Coastguard Worker    generated output to the file self.output_file in the temporary directory.
108*795d594fSAndroid Build Coastguard Worker
109*795d594fSAndroid Build Coastguard Worker    Most nonzero return codes are assumed non-divergent, since systems may
110*795d594fSAndroid Build Coastguard Worker    exit in different ways. This is enforced by normalizing return codes.
111*795d594fSAndroid Build Coastguard Worker
112*795d594fSAndroid Build Coastguard Worker    Returns:
113*795d594fSAndroid Build Coastguard Worker      normalized return code
114*795d594fSAndroid Build Coastguard Worker    """
115*795d594fSAndroid Build Coastguard Worker
116*795d594fSAndroid Build Coastguard Worker
117*795d594fSAndroid Build Coastguard Workerclass TestRunnerWithHostCompilation(TestRunner):
118*795d594fSAndroid Build Coastguard Worker  """Abstract test runner that supports compilation on host."""
119*795d594fSAndroid Build Coastguard Worker
120*795d594fSAndroid Build Coastguard Worker  def  __init__(self, dexer, debug_info):
121*795d594fSAndroid Build Coastguard Worker    """Constructor for the runner with host compilation.
122*795d594fSAndroid Build Coastguard Worker
123*795d594fSAndroid Build Coastguard Worker    Args:
124*795d594fSAndroid Build Coastguard Worker      dexer: string, defines dexer
125*795d594fSAndroid Build Coastguard Worker      debug_info: boolean, if True include debugging info
126*795d594fSAndroid Build Coastguard Worker    """
127*795d594fSAndroid Build Coastguard Worker    self._dexer = dexer
128*795d594fSAndroid Build Coastguard Worker    self._debug_info = debug_info
129*795d594fSAndroid Build Coastguard Worker
130*795d594fSAndroid Build Coastguard Worker  def CompileOnHost(self):
131*795d594fSAndroid Build Coastguard Worker    if self._dexer == 'dx' or self._dexer == 'd8':
132*795d594fSAndroid Build Coastguard Worker      dbg = '-g' if self._debug_info else '-g:none'
133*795d594fSAndroid Build Coastguard Worker      if RunCommand(['javac', '--release=8', dbg, 'Test.java'],
134*795d594fSAndroid Build Coastguard Worker                    out=None, err=None, timeout=30) == RetCode.SUCCESS:
135*795d594fSAndroid Build Coastguard Worker        dx = 'dx' if self._dexer == 'dx' else 'd8-compat-dx'
136*795d594fSAndroid Build Coastguard Worker        retc = RunCommand([dx, '--dex', '--output=classes.dex'] + glob('*.class'),
137*795d594fSAndroid Build Coastguard Worker                          out=None, err='dxerr.txt', timeout=30)
138*795d594fSAndroid Build Coastguard Worker      else:
139*795d594fSAndroid Build Coastguard Worker        retc = RetCode.NOTCOMPILED
140*795d594fSAndroid Build Coastguard Worker    else:
141*795d594fSAndroid Build Coastguard Worker      raise FatalError('Unknown dexer: ' + self._dexer)
142*795d594fSAndroid Build Coastguard Worker    return retc
143*795d594fSAndroid Build Coastguard Worker
144*795d594fSAndroid Build Coastguard Worker
145*795d594fSAndroid Build Coastguard Workerclass TestRunnerRIOnHost(TestRunner):
146*795d594fSAndroid Build Coastguard Worker  """Concrete test runner of the reference implementation on host."""
147*795d594fSAndroid Build Coastguard Worker
148*795d594fSAndroid Build Coastguard Worker  def  __init__(self, debug_info):
149*795d594fSAndroid Build Coastguard Worker    """Constructor for the runner with host compilation.
150*795d594fSAndroid Build Coastguard Worker
151*795d594fSAndroid Build Coastguard Worker    Args:
152*795d594fSAndroid Build Coastguard Worker      debug_info: boolean, if True include debugging info
153*795d594fSAndroid Build Coastguard Worker    """
154*795d594fSAndroid Build Coastguard Worker    self._debug_info = debug_info
155*795d594fSAndroid Build Coastguard Worker
156*795d594fSAndroid Build Coastguard Worker  @property
157*795d594fSAndroid Build Coastguard Worker  def description(self):
158*795d594fSAndroid Build Coastguard Worker    return 'RI on host'
159*795d594fSAndroid Build Coastguard Worker
160*795d594fSAndroid Build Coastguard Worker  @property
161*795d594fSAndroid Build Coastguard Worker  def id(self):
162*795d594fSAndroid Build Coastguard Worker    return 'RI'
163*795d594fSAndroid Build Coastguard Worker
164*795d594fSAndroid Build Coastguard Worker  def CompileAndRunTest(self):
165*795d594fSAndroid Build Coastguard Worker    dbg = '-g' if self._debug_info else '-g:none'
166*795d594fSAndroid Build Coastguard Worker    if RunCommand(['javac', '--release=8', dbg, 'Test.java'],
167*795d594fSAndroid Build Coastguard Worker                  out=None, err=None, timeout=30) == RetCode.SUCCESS:
168*795d594fSAndroid Build Coastguard Worker      retc = RunCommand(['java', 'Test'], self.output_file, err=None)
169*795d594fSAndroid Build Coastguard Worker    else:
170*795d594fSAndroid Build Coastguard Worker      retc = RetCode.NOTCOMPILED
171*795d594fSAndroid Build Coastguard Worker    return retc
172*795d594fSAndroid Build Coastguard Worker
173*795d594fSAndroid Build Coastguard Worker  def GetBisectionSearchArgs(self):
174*795d594fSAndroid Build Coastguard Worker    return None
175*795d594fSAndroid Build Coastguard Worker
176*795d594fSAndroid Build Coastguard Worker
177*795d594fSAndroid Build Coastguard Workerclass TestRunnerArtOnHost(TestRunnerWithHostCompilation):
178*795d594fSAndroid Build Coastguard Worker  """Abstract test runner of Art on host."""
179*795d594fSAndroid Build Coastguard Worker
180*795d594fSAndroid Build Coastguard Worker  def  __init__(self, dexer, debug_info, extra_args=None):
181*795d594fSAndroid Build Coastguard Worker    """Constructor for the Art on host tester.
182*795d594fSAndroid Build Coastguard Worker
183*795d594fSAndroid Build Coastguard Worker    Args:
184*795d594fSAndroid Build Coastguard Worker      dexer: string, defines dexer
185*795d594fSAndroid Build Coastguard Worker      debug_info: boolean, if True include debugging info
186*795d594fSAndroid Build Coastguard Worker      extra_args: list of strings, extra arguments for dalvikvm
187*795d594fSAndroid Build Coastguard Worker    """
188*795d594fSAndroid Build Coastguard Worker    super().__init__(dexer, debug_info)
189*795d594fSAndroid Build Coastguard Worker    self._art_cmd = ['/bin/bash', 'art', '-cp', 'classes.dex']
190*795d594fSAndroid Build Coastguard Worker    if extra_args is not None:
191*795d594fSAndroid Build Coastguard Worker      self._art_cmd += extra_args
192*795d594fSAndroid Build Coastguard Worker    self._art_cmd.append('Test')
193*795d594fSAndroid Build Coastguard Worker
194*795d594fSAndroid Build Coastguard Worker  def CompileAndRunTest(self):
195*795d594fSAndroid Build Coastguard Worker    if self.CompileOnHost() == RetCode.SUCCESS:
196*795d594fSAndroid Build Coastguard Worker      retc = RunCommand(self._art_cmd, self.output_file, 'arterr.txt')
197*795d594fSAndroid Build Coastguard Worker    else:
198*795d594fSAndroid Build Coastguard Worker      retc = RetCode.NOTCOMPILED
199*795d594fSAndroid Build Coastguard Worker    return retc
200*795d594fSAndroid Build Coastguard Worker
201*795d594fSAndroid Build Coastguard Worker
202*795d594fSAndroid Build Coastguard Workerclass TestRunnerArtIntOnHost(TestRunnerArtOnHost):
203*795d594fSAndroid Build Coastguard Worker  """Concrete test runner of interpreter mode Art on host."""
204*795d594fSAndroid Build Coastguard Worker
205*795d594fSAndroid Build Coastguard Worker  def  __init__(self, dexer, debug_info):
206*795d594fSAndroid Build Coastguard Worker    """Constructor for the Art on host tester (interpreter).
207*795d594fSAndroid Build Coastguard Worker
208*795d594fSAndroid Build Coastguard Worker    Args:
209*795d594fSAndroid Build Coastguard Worker      dexer: string, defines dexer
210*795d594fSAndroid Build Coastguard Worker      debug_info: boolean, if True include debugging info
211*795d594fSAndroid Build Coastguard Worker   """
212*795d594fSAndroid Build Coastguard Worker    super().__init__(dexer, debug_info, ['-Xint'])
213*795d594fSAndroid Build Coastguard Worker
214*795d594fSAndroid Build Coastguard Worker  @property
215*795d594fSAndroid Build Coastguard Worker  def description(self):
216*795d594fSAndroid Build Coastguard Worker    return 'Art interpreter on host'
217*795d594fSAndroid Build Coastguard Worker
218*795d594fSAndroid Build Coastguard Worker  @property
219*795d594fSAndroid Build Coastguard Worker  def id(self):
220*795d594fSAndroid Build Coastguard Worker    return 'HInt'
221*795d594fSAndroid Build Coastguard Worker
222*795d594fSAndroid Build Coastguard Worker  def GetBisectionSearchArgs(self):
223*795d594fSAndroid Build Coastguard Worker    return None
224*795d594fSAndroid Build Coastguard Worker
225*795d594fSAndroid Build Coastguard Worker
226*795d594fSAndroid Build Coastguard Workerclass TestRunnerArtOptOnHost(TestRunnerArtOnHost):
227*795d594fSAndroid Build Coastguard Worker  """Concrete test runner of optimizing compiler mode Art on host."""
228*795d594fSAndroid Build Coastguard Worker
229*795d594fSAndroid Build Coastguard Worker  def  __init__(self, dexer, debug_info):
230*795d594fSAndroid Build Coastguard Worker    """Constructor for the Art on host tester (optimizing).
231*795d594fSAndroid Build Coastguard Worker
232*795d594fSAndroid Build Coastguard Worker    Args:
233*795d594fSAndroid Build Coastguard Worker      dexer: string, defines dexer
234*795d594fSAndroid Build Coastguard Worker      debug_info: boolean, if True include debugging info
235*795d594fSAndroid Build Coastguard Worker   """
236*795d594fSAndroid Build Coastguard Worker    super().__init__(dexer, debug_info, None)
237*795d594fSAndroid Build Coastguard Worker
238*795d594fSAndroid Build Coastguard Worker  @property
239*795d594fSAndroid Build Coastguard Worker  def description(self):
240*795d594fSAndroid Build Coastguard Worker    return 'Art optimizing on host'
241*795d594fSAndroid Build Coastguard Worker
242*795d594fSAndroid Build Coastguard Worker  @property
243*795d594fSAndroid Build Coastguard Worker  def id(self):
244*795d594fSAndroid Build Coastguard Worker    return 'HOpt'
245*795d594fSAndroid Build Coastguard Worker
246*795d594fSAndroid Build Coastguard Worker  def GetBisectionSearchArgs(self):
247*795d594fSAndroid Build Coastguard Worker    cmd_str = CommandListToCommandString(
248*795d594fSAndroid Build Coastguard Worker        self._art_cmd[0:2] + ['{ARGS}'] + self._art_cmd[2:])
249*795d594fSAndroid Build Coastguard Worker    return ['--raw-cmd={0}'.format(cmd_str), '--timeout', str(30)]
250*795d594fSAndroid Build Coastguard Worker
251*795d594fSAndroid Build Coastguard Worker
252*795d594fSAndroid Build Coastguard Workerclass TestRunnerArtOnTarget(TestRunnerWithHostCompilation):
253*795d594fSAndroid Build Coastguard Worker  """Abstract test runner of Art on target."""
254*795d594fSAndroid Build Coastguard Worker
255*795d594fSAndroid Build Coastguard Worker  def  __init__(self, dexer, debug_info, device, extra_args=None):
256*795d594fSAndroid Build Coastguard Worker    """Constructor for the Art on target tester.
257*795d594fSAndroid Build Coastguard Worker
258*795d594fSAndroid Build Coastguard Worker    Args:
259*795d594fSAndroid Build Coastguard Worker      dexer: string, defines dexer
260*795d594fSAndroid Build Coastguard Worker      debug_info: boolean, if True include debugging info
261*795d594fSAndroid Build Coastguard Worker      device: string, target device serial number (or None)
262*795d594fSAndroid Build Coastguard Worker      extra_args: list of strings, extra arguments for dalvikvm
263*795d594fSAndroid Build Coastguard Worker    """
264*795d594fSAndroid Build Coastguard Worker    super().__init__(dexer, debug_info)
265*795d594fSAndroid Build Coastguard Worker    self._test_env = DeviceTestEnv('jfuzz_', specific_device=device)
266*795d594fSAndroid Build Coastguard Worker    self._dalvik_cmd = ['dalvikvm']
267*795d594fSAndroid Build Coastguard Worker    if extra_args is not None:
268*795d594fSAndroid Build Coastguard Worker      self._dalvik_cmd += extra_args
269*795d594fSAndroid Build Coastguard Worker    self._device = device
270*795d594fSAndroid Build Coastguard Worker    self._device_classpath = None
271*795d594fSAndroid Build Coastguard Worker
272*795d594fSAndroid Build Coastguard Worker  def CompileAndRunTest(self):
273*795d594fSAndroid Build Coastguard Worker    if self.CompileOnHost() == RetCode.SUCCESS:
274*795d594fSAndroid Build Coastguard Worker      self._device_classpath = self._test_env.PushClasspath('classes.dex')
275*795d594fSAndroid Build Coastguard Worker      cmd = self._dalvik_cmd + ['-cp', self._device_classpath, 'Test']
276*795d594fSAndroid Build Coastguard Worker      (output, retc) = self._test_env.RunCommand(
277*795d594fSAndroid Build Coastguard Worker          cmd, {'ANDROID_LOG_TAGS': '*:s'})
278*795d594fSAndroid Build Coastguard Worker      with open(self.output_file, 'w') as run_out:
279*795d594fSAndroid Build Coastguard Worker        run_out.write(output)
280*795d594fSAndroid Build Coastguard Worker    else:
281*795d594fSAndroid Build Coastguard Worker      retc = RetCode.NOTCOMPILED
282*795d594fSAndroid Build Coastguard Worker    return retc
283*795d594fSAndroid Build Coastguard Worker
284*795d594fSAndroid Build Coastguard Worker  def GetBisectionSearchArgs(self):
285*795d594fSAndroid Build Coastguard Worker    cmd_str = CommandListToCommandString(
286*795d594fSAndroid Build Coastguard Worker        self._dalvik_cmd + ['-cp',self._device_classpath, 'Test'])
287*795d594fSAndroid Build Coastguard Worker    cmd = ['--raw-cmd={0}'.format(cmd_str), '--timeout', str(30)]
288*795d594fSAndroid Build Coastguard Worker    if self._device:
289*795d594fSAndroid Build Coastguard Worker      cmd += ['--device-serial', self._device]
290*795d594fSAndroid Build Coastguard Worker    else:
291*795d594fSAndroid Build Coastguard Worker      cmd.append('--device')
292*795d594fSAndroid Build Coastguard Worker    return cmd
293*795d594fSAndroid Build Coastguard Worker
294*795d594fSAndroid Build Coastguard Worker
295*795d594fSAndroid Build Coastguard Workerclass TestRunnerArtIntOnTarget(TestRunnerArtOnTarget):
296*795d594fSAndroid Build Coastguard Worker  """Concrete test runner of interpreter mode Art on target."""
297*795d594fSAndroid Build Coastguard Worker
298*795d594fSAndroid Build Coastguard Worker  def  __init__(self, dexer, debug_info, device):
299*795d594fSAndroid Build Coastguard Worker    """Constructor for the Art on target tester (interpreter).
300*795d594fSAndroid Build Coastguard Worker
301*795d594fSAndroid Build Coastguard Worker    Args:
302*795d594fSAndroid Build Coastguard Worker      dexer: string, defines dexer
303*795d594fSAndroid Build Coastguard Worker      debug_info: boolean, if True include debugging info
304*795d594fSAndroid Build Coastguard Worker      device: string, target device serial number (or None)
305*795d594fSAndroid Build Coastguard Worker    """
306*795d594fSAndroid Build Coastguard Worker    super().__init__(dexer, debug_info, device, ['-Xint'])
307*795d594fSAndroid Build Coastguard Worker
308*795d594fSAndroid Build Coastguard Worker  @property
309*795d594fSAndroid Build Coastguard Worker  def description(self):
310*795d594fSAndroid Build Coastguard Worker    return 'Art interpreter on target'
311*795d594fSAndroid Build Coastguard Worker
312*795d594fSAndroid Build Coastguard Worker  @property
313*795d594fSAndroid Build Coastguard Worker  def id(self):
314*795d594fSAndroid Build Coastguard Worker    return 'TInt'
315*795d594fSAndroid Build Coastguard Worker
316*795d594fSAndroid Build Coastguard Worker  def GetBisectionSearchArgs(self):
317*795d594fSAndroid Build Coastguard Worker    return None
318*795d594fSAndroid Build Coastguard Worker
319*795d594fSAndroid Build Coastguard Worker
320*795d594fSAndroid Build Coastguard Workerclass TestRunnerArtOptOnTarget(TestRunnerArtOnTarget):
321*795d594fSAndroid Build Coastguard Worker  """Concrete test runner of optimizing compiler mode Art on target."""
322*795d594fSAndroid Build Coastguard Worker
323*795d594fSAndroid Build Coastguard Worker  def  __init__(self, dexer, debug_info, device):
324*795d594fSAndroid Build Coastguard Worker    """Constructor for the Art on target tester (optimizing).
325*795d594fSAndroid Build Coastguard Worker
326*795d594fSAndroid Build Coastguard Worker    Args:
327*795d594fSAndroid Build Coastguard Worker      dexer: string, defines dexer
328*795d594fSAndroid Build Coastguard Worker      debug_info: boolean, if True include debugging info
329*795d594fSAndroid Build Coastguard Worker      device: string, target device serial number (or None)
330*795d594fSAndroid Build Coastguard Worker    """
331*795d594fSAndroid Build Coastguard Worker    super().__init__(dexer, debug_info, device, None)
332*795d594fSAndroid Build Coastguard Worker
333*795d594fSAndroid Build Coastguard Worker  @property
334*795d594fSAndroid Build Coastguard Worker  def description(self):
335*795d594fSAndroid Build Coastguard Worker    return 'Art optimizing on target'
336*795d594fSAndroid Build Coastguard Worker
337*795d594fSAndroid Build Coastguard Worker  @property
338*795d594fSAndroid Build Coastguard Worker  def id(self):
339*795d594fSAndroid Build Coastguard Worker    return 'TOpt'
340*795d594fSAndroid Build Coastguard Worker
341*795d594fSAndroid Build Coastguard Worker  def GetBisectionSearchArgs(self):
342*795d594fSAndroid Build Coastguard Worker    cmd_str = CommandListToCommandString(
343*795d594fSAndroid Build Coastguard Worker        self._dalvik_cmd + ['-cp', self._device_classpath, 'Test'])
344*795d594fSAndroid Build Coastguard Worker    cmd = ['--raw-cmd={0}'.format(cmd_str), '--timeout', str(30)]
345*795d594fSAndroid Build Coastguard Worker    if self._device:
346*795d594fSAndroid Build Coastguard Worker      cmd += ['--device-serial', self._device]
347*795d594fSAndroid Build Coastguard Worker    else:
348*795d594fSAndroid Build Coastguard Worker      cmd.append('--device')
349*795d594fSAndroid Build Coastguard Worker    return cmd
350*795d594fSAndroid Build Coastguard Worker
351*795d594fSAndroid Build Coastguard Worker
352*795d594fSAndroid Build Coastguard Worker#
353*795d594fSAndroid Build Coastguard Worker# Tester class.
354*795d594fSAndroid Build Coastguard Worker#
355*795d594fSAndroid Build Coastguard Worker
356*795d594fSAndroid Build Coastguard Worker
357*795d594fSAndroid Build Coastguard Workerclass JFuzzTester(object):
358*795d594fSAndroid Build Coastguard Worker  """Tester that runs JFuzz many times and report divergences."""
359*795d594fSAndroid Build Coastguard Worker
360*795d594fSAndroid Build Coastguard Worker  def  __init__(self, num_tests, device, mode1, mode2, jfuzz_args,
361*795d594fSAndroid Build Coastguard Worker                report_script, true_divergence_only, dexer, debug_info):
362*795d594fSAndroid Build Coastguard Worker    """Constructor for the tester.
363*795d594fSAndroid Build Coastguard Worker
364*795d594fSAndroid Build Coastguard Worker    Args:
365*795d594fSAndroid Build Coastguard Worker      num_tests: int, number of tests to run
366*795d594fSAndroid Build Coastguard Worker      device: string, target device serial number (or None)
367*795d594fSAndroid Build Coastguard Worker      mode1: string, execution mode for first runner
368*795d594fSAndroid Build Coastguard Worker      mode2: string, execution mode for second runner
369*795d594fSAndroid Build Coastguard Worker      jfuzz_args: list of strings, additional arguments for jfuzz
370*795d594fSAndroid Build Coastguard Worker      report_script: string, path to script called for each divergence
371*795d594fSAndroid Build Coastguard Worker      true_divergence_only: boolean, if True don't bisect timeout divergences
372*795d594fSAndroid Build Coastguard Worker      dexer: string, defines dexer
373*795d594fSAndroid Build Coastguard Worker      debug_info: boolean, if True include debugging info
374*795d594fSAndroid Build Coastguard Worker    """
375*795d594fSAndroid Build Coastguard Worker    self._num_tests = num_tests
376*795d594fSAndroid Build Coastguard Worker    self._device = device
377*795d594fSAndroid Build Coastguard Worker    self._runner1 = GetExecutionModeRunner(dexer, debug_info, device, mode1)
378*795d594fSAndroid Build Coastguard Worker    self._runner2 = GetExecutionModeRunner(dexer, debug_info, device, mode2)
379*795d594fSAndroid Build Coastguard Worker    self._jfuzz_args = jfuzz_args
380*795d594fSAndroid Build Coastguard Worker    self._report_script = report_script
381*795d594fSAndroid Build Coastguard Worker    self._true_divergence_only = true_divergence_only
382*795d594fSAndroid Build Coastguard Worker    self._dexer = dexer
383*795d594fSAndroid Build Coastguard Worker    self._debug_info = debug_info
384*795d594fSAndroid Build Coastguard Worker    self._save_dir = None
385*795d594fSAndroid Build Coastguard Worker    self._results_dir = None
386*795d594fSAndroid Build Coastguard Worker    self._jfuzz_dir = None
387*795d594fSAndroid Build Coastguard Worker    # Statistics.
388*795d594fSAndroid Build Coastguard Worker    self._test = 0
389*795d594fSAndroid Build Coastguard Worker    self._num_success = 0
390*795d594fSAndroid Build Coastguard Worker    self._num_not_compiled = 0
391*795d594fSAndroid Build Coastguard Worker    self._num_not_run = 0
392*795d594fSAndroid Build Coastguard Worker    self._num_timed_out = 0
393*795d594fSAndroid Build Coastguard Worker    self._num_divergences = 0
394*795d594fSAndroid Build Coastguard Worker
395*795d594fSAndroid Build Coastguard Worker  def __enter__(self):
396*795d594fSAndroid Build Coastguard Worker    """On entry, enters new temp directory after saving current directory.
397*795d594fSAndroid Build Coastguard Worker
398*795d594fSAndroid Build Coastguard Worker    Raises:
399*795d594fSAndroid Build Coastguard Worker      FatalError: error when temp directory cannot be constructed
400*795d594fSAndroid Build Coastguard Worker    """
401*795d594fSAndroid Build Coastguard Worker    self._save_dir = os.getcwd()
402*795d594fSAndroid Build Coastguard Worker    self._results_dir = mkdtemp(dir='/tmp/')
403*795d594fSAndroid Build Coastguard Worker    self._jfuzz_dir = mkdtemp(dir=self._results_dir)
404*795d594fSAndroid Build Coastguard Worker    if self._results_dir is None or self._jfuzz_dir is None:
405*795d594fSAndroid Build Coastguard Worker      raise FatalError('Cannot obtain temp directory')
406*795d594fSAndroid Build Coastguard Worker    os.chdir(self._jfuzz_dir)
407*795d594fSAndroid Build Coastguard Worker    return self
408*795d594fSAndroid Build Coastguard Worker
409*795d594fSAndroid Build Coastguard Worker  def __exit__(self, etype, evalue, etraceback):
410*795d594fSAndroid Build Coastguard Worker    """On exit, re-enters previously saved current directory and cleans up."""
411*795d594fSAndroid Build Coastguard Worker    os.chdir(self._save_dir)
412*795d594fSAndroid Build Coastguard Worker    shutil.rmtree(self._jfuzz_dir)
413*795d594fSAndroid Build Coastguard Worker    if self._num_divergences == 0:
414*795d594fSAndroid Build Coastguard Worker      shutil.rmtree(self._results_dir)
415*795d594fSAndroid Build Coastguard Worker
416*795d594fSAndroid Build Coastguard Worker  def Run(self):
417*795d594fSAndroid Build Coastguard Worker    """Runs JFuzz many times and report divergences."""
418*795d594fSAndroid Build Coastguard Worker    print()
419*795d594fSAndroid Build Coastguard Worker    print('**\n**** JFuzz Testing\n**')
420*795d594fSAndroid Build Coastguard Worker    print()
421*795d594fSAndroid Build Coastguard Worker    print('#Tests    :', self._num_tests)
422*795d594fSAndroid Build Coastguard Worker    print('Device    :', self._device)
423*795d594fSAndroid Build Coastguard Worker    print('Directory :', self._results_dir)
424*795d594fSAndroid Build Coastguard Worker    print('Exec-mode1:', self._runner1.description)
425*795d594fSAndroid Build Coastguard Worker    print('Exec-mode2:', self._runner2.description)
426*795d594fSAndroid Build Coastguard Worker    print('Dexer     :', self._dexer)
427*795d594fSAndroid Build Coastguard Worker    print('Debug-info:', self._debug_info)
428*795d594fSAndroid Build Coastguard Worker    print()
429*795d594fSAndroid Build Coastguard Worker    self.ShowStats()
430*795d594fSAndroid Build Coastguard Worker    for self._test in range(1, self._num_tests + 1):
431*795d594fSAndroid Build Coastguard Worker      self.RunJFuzzTest()
432*795d594fSAndroid Build Coastguard Worker      self.ShowStats()
433*795d594fSAndroid Build Coastguard Worker    if self._num_divergences == 0:
434*795d594fSAndroid Build Coastguard Worker      print('\n\nsuccess (no divergences)\n')
435*795d594fSAndroid Build Coastguard Worker    else:
436*795d594fSAndroid Build Coastguard Worker      print('\n\nfailure (divergences)\n')
437*795d594fSAndroid Build Coastguard Worker
438*795d594fSAndroid Build Coastguard Worker  def ShowStats(self):
439*795d594fSAndroid Build Coastguard Worker    """Shows current statistics (on same line) while tester is running."""
440*795d594fSAndroid Build Coastguard Worker    print('\rTests:', self._test,
441*795d594fSAndroid Build Coastguard Worker          'Success:', self._num_success,
442*795d594fSAndroid Build Coastguard Worker          'Not-compiled:', self._num_not_compiled,
443*795d594fSAndroid Build Coastguard Worker          'Not-run:', self._num_not_run,
444*795d594fSAndroid Build Coastguard Worker          'Timed-out:', self._num_timed_out,
445*795d594fSAndroid Build Coastguard Worker          'Divergences:', self._num_divergences,
446*795d594fSAndroid Build Coastguard Worker          end='')
447*795d594fSAndroid Build Coastguard Worker    sys.stdout.flush()
448*795d594fSAndroid Build Coastguard Worker
449*795d594fSAndroid Build Coastguard Worker  def RunJFuzzTest(self):
450*795d594fSAndroid Build Coastguard Worker    """Runs a single JFuzz test, comparing two execution modes."""
451*795d594fSAndroid Build Coastguard Worker    self.ConstructTest()
452*795d594fSAndroid Build Coastguard Worker    retc1 = self._runner1.CompileAndRunTest()
453*795d594fSAndroid Build Coastguard Worker    retc2 = self._runner2.CompileAndRunTest()
454*795d594fSAndroid Build Coastguard Worker    self.CheckForDivergence(retc1, retc2)
455*795d594fSAndroid Build Coastguard Worker    self.CleanupTest()
456*795d594fSAndroid Build Coastguard Worker
457*795d594fSAndroid Build Coastguard Worker  def ConstructTest(self):
458*795d594fSAndroid Build Coastguard Worker    """Use JFuzz to generate next Test.java test.
459*795d594fSAndroid Build Coastguard Worker
460*795d594fSAndroid Build Coastguard Worker    Raises:
461*795d594fSAndroid Build Coastguard Worker      FatalError: error when jfuzz fails
462*795d594fSAndroid Build Coastguard Worker    """
463*795d594fSAndroid Build Coastguard Worker    if (RunCommand(['jfuzz'] + self._jfuzz_args, out='Test.java', err=None)
464*795d594fSAndroid Build Coastguard Worker          != RetCode.SUCCESS):
465*795d594fSAndroid Build Coastguard Worker      raise FatalError('Unexpected error while running JFuzz')
466*795d594fSAndroid Build Coastguard Worker
467*795d594fSAndroid Build Coastguard Worker  def CheckForDivergence(self, retc1, retc2):
468*795d594fSAndroid Build Coastguard Worker    """Checks for divergences and updates statistics.
469*795d594fSAndroid Build Coastguard Worker
470*795d594fSAndroid Build Coastguard Worker    Args:
471*795d594fSAndroid Build Coastguard Worker      retc1: int, normalized return code of first runner
472*795d594fSAndroid Build Coastguard Worker      retc2: int, normalized return code of second runner
473*795d594fSAndroid Build Coastguard Worker    """
474*795d594fSAndroid Build Coastguard Worker    if retc1 == retc2:
475*795d594fSAndroid Build Coastguard Worker      # No divergence in return code.
476*795d594fSAndroid Build Coastguard Worker      if retc1 == RetCode.SUCCESS:
477*795d594fSAndroid Build Coastguard Worker        # Both compilations and runs were successful, inspect generated output.
478*795d594fSAndroid Build Coastguard Worker        runner1_out = self._runner1.output_file
479*795d594fSAndroid Build Coastguard Worker        runner2_out = self._runner2.output_file
480*795d594fSAndroid Build Coastguard Worker        if not filecmp.cmp(runner1_out, runner2_out, shallow=False):
481*795d594fSAndroid Build Coastguard Worker          # Divergence in output.
482*795d594fSAndroid Build Coastguard Worker          self.ReportDivergence(retc1, retc2, is_output_divergence=True)
483*795d594fSAndroid Build Coastguard Worker        else:
484*795d594fSAndroid Build Coastguard Worker          # No divergence in output.
485*795d594fSAndroid Build Coastguard Worker          self._num_success += 1
486*795d594fSAndroid Build Coastguard Worker      elif retc1 == RetCode.TIMEOUT:
487*795d594fSAndroid Build Coastguard Worker        self._num_timed_out += 1
488*795d594fSAndroid Build Coastguard Worker      elif retc1 == RetCode.NOTCOMPILED:
489*795d594fSAndroid Build Coastguard Worker        self._num_not_compiled += 1
490*795d594fSAndroid Build Coastguard Worker      else:
491*795d594fSAndroid Build Coastguard Worker        self._num_not_run += 1
492*795d594fSAndroid Build Coastguard Worker    else:
493*795d594fSAndroid Build Coastguard Worker      # Divergence in return code.
494*795d594fSAndroid Build Coastguard Worker      if self._true_divergence_only:
495*795d594fSAndroid Build Coastguard Worker        # When only true divergences are requested, any divergence in return
496*795d594fSAndroid Build Coastguard Worker        # code where one is a time out is treated as a regular time out.
497*795d594fSAndroid Build Coastguard Worker        if RetCode.TIMEOUT in (retc1, retc2):
498*795d594fSAndroid Build Coastguard Worker          self._num_timed_out += 1
499*795d594fSAndroid Build Coastguard Worker          return
500*795d594fSAndroid Build Coastguard Worker        # When only true divergences are requested, a runtime crash in just
501*795d594fSAndroid Build Coastguard Worker        # the RI is treated as if not run at all.
502*795d594fSAndroid Build Coastguard Worker        if retc1 == RetCode.ERROR and retc2 == RetCode.SUCCESS:
503*795d594fSAndroid Build Coastguard Worker          if self._runner1.GetBisectionSearchArgs() is None:
504*795d594fSAndroid Build Coastguard Worker            self._num_not_run += 1
505*795d594fSAndroid Build Coastguard Worker            return
506*795d594fSAndroid Build Coastguard Worker      self.ReportDivergence(retc1, retc2, is_output_divergence=False)
507*795d594fSAndroid Build Coastguard Worker
508*795d594fSAndroid Build Coastguard Worker  def GetCurrentDivergenceDir(self):
509*795d594fSAndroid Build Coastguard Worker    return self._results_dir + '/divergence' + str(self._num_divergences)
510*795d594fSAndroid Build Coastguard Worker
511*795d594fSAndroid Build Coastguard Worker  def ReportDivergence(self, retc1, retc2, is_output_divergence):
512*795d594fSAndroid Build Coastguard Worker    """Reports and saves a divergence."""
513*795d594fSAndroid Build Coastguard Worker    self._num_divergences += 1
514*795d594fSAndroid Build Coastguard Worker    print('\n' + str(self._num_divergences), end='')
515*795d594fSAndroid Build Coastguard Worker    if is_output_divergence:
516*795d594fSAndroid Build Coastguard Worker      print(' divergence in output')
517*795d594fSAndroid Build Coastguard Worker    else:
518*795d594fSAndroid Build Coastguard Worker      print(' divergence in return code: ' + retc1.name + ' vs. ' +
519*795d594fSAndroid Build Coastguard Worker            retc2.name)
520*795d594fSAndroid Build Coastguard Worker    # Save.
521*795d594fSAndroid Build Coastguard Worker    ddir = self.GetCurrentDivergenceDir()
522*795d594fSAndroid Build Coastguard Worker    os.mkdir(ddir)
523*795d594fSAndroid Build Coastguard Worker    for f in glob('*.txt') + ['Test.java']:
524*795d594fSAndroid Build Coastguard Worker      shutil.copy(f, ddir)
525*795d594fSAndroid Build Coastguard Worker    # Maybe run bisection bug search.
526*795d594fSAndroid Build Coastguard Worker    if retc1 in BISECTABLE_RET_CODES and retc2 in BISECTABLE_RET_CODES:
527*795d594fSAndroid Build Coastguard Worker      self.MaybeBisectDivergence(retc1, retc2, is_output_divergence)
528*795d594fSAndroid Build Coastguard Worker    # Call reporting script.
529*795d594fSAndroid Build Coastguard Worker    if self._report_script:
530*795d594fSAndroid Build Coastguard Worker      self.RunReportScript(retc1, retc2, is_output_divergence)
531*795d594fSAndroid Build Coastguard Worker
532*795d594fSAndroid Build Coastguard Worker  def RunReportScript(self, retc1, retc2, is_output_divergence):
533*795d594fSAndroid Build Coastguard Worker    """Runs report script."""
534*795d594fSAndroid Build Coastguard Worker    try:
535*795d594fSAndroid Build Coastguard Worker      title = "Divergence between {0} and {1} (found with fuzz testing)".format(
536*795d594fSAndroid Build Coastguard Worker          self._runner1.description, self._runner2.description)
537*795d594fSAndroid Build Coastguard Worker      # Prepare divergence comment.
538*795d594fSAndroid Build Coastguard Worker      jfuzz_cmd_and_version = subprocess.check_output(
539*795d594fSAndroid Build Coastguard Worker          ['grep', '-o', 'jfuzz.*', 'Test.java'], universal_newlines=True)
540*795d594fSAndroid Build Coastguard Worker      (jfuzz_cmd_str, jfuzz_ver) = jfuzz_cmd_and_version.split('(')
541*795d594fSAndroid Build Coastguard Worker      # Strip right parenthesis and new line.
542*795d594fSAndroid Build Coastguard Worker      jfuzz_ver = jfuzz_ver[:-2]
543*795d594fSAndroid Build Coastguard Worker      jfuzz_args = ['\'-{0}\''.format(arg)
544*795d594fSAndroid Build Coastguard Worker                    for arg in jfuzz_cmd_str.strip().split(' -')][1:]
545*795d594fSAndroid Build Coastguard Worker      wrapped_args = ['--jfuzz_arg={0}'.format(opt) for opt in jfuzz_args]
546*795d594fSAndroid Build Coastguard Worker      repro_cmd_str = (os.path.basename(__file__) +
547*795d594fSAndroid Build Coastguard Worker                       ' --num_tests=1 --dexer=' + self._dexer +
548*795d594fSAndroid Build Coastguard Worker                       (' --debug_info ' if self._debug_info else ' ') +
549*795d594fSAndroid Build Coastguard Worker                       ' '.join(wrapped_args))
550*795d594fSAndroid Build Coastguard Worker      comment = 'jfuzz {0}\nReproduce test:\n{1}\nReproduce divergence:\n{2}\n'.format(
551*795d594fSAndroid Build Coastguard Worker          jfuzz_ver, jfuzz_cmd_str, repro_cmd_str)
552*795d594fSAndroid Build Coastguard Worker      if is_output_divergence:
553*795d594fSAndroid Build Coastguard Worker        (output, _, _) = RunCommandForOutput(
554*795d594fSAndroid Build Coastguard Worker            ['diff', self._runner1.output_file, self._runner2.output_file],
555*795d594fSAndroid Build Coastguard Worker            None, subprocess.PIPE, subprocess.STDOUT)
556*795d594fSAndroid Build Coastguard Worker        comment += 'Diff:\n' + output
557*795d594fSAndroid Build Coastguard Worker      else:
558*795d594fSAndroid Build Coastguard Worker        comment += '{0} vs {1}\n'.format(retc1, retc2)
559*795d594fSAndroid Build Coastguard Worker      # Prepare report script command.
560*795d594fSAndroid Build Coastguard Worker      script_cmd = [self._report_script, title, comment]
561*795d594fSAndroid Build Coastguard Worker      ddir = self.GetCurrentDivergenceDir()
562*795d594fSAndroid Build Coastguard Worker      bisection_out_files = glob(ddir + '/*_bisection_out.txt')
563*795d594fSAndroid Build Coastguard Worker      if bisection_out_files:
564*795d594fSAndroid Build Coastguard Worker        script_cmd += ['--bisection_out', bisection_out_files[0]]
565*795d594fSAndroid Build Coastguard Worker      subprocess.check_call(script_cmd, stdout=DEVNULL, stderr=DEVNULL)
566*795d594fSAndroid Build Coastguard Worker    except subprocess.CalledProcessError as err:
567*795d594fSAndroid Build Coastguard Worker      print('Failed to run report script.\n', err)
568*795d594fSAndroid Build Coastguard Worker
569*795d594fSAndroid Build Coastguard Worker  def RunBisectionSearch(self, args, expected_retcode, expected_output,
570*795d594fSAndroid Build Coastguard Worker                         runner_id):
571*795d594fSAndroid Build Coastguard Worker    ddir = self.GetCurrentDivergenceDir()
572*795d594fSAndroid Build Coastguard Worker    outfile_path = ddir + '/' + runner_id + '_bisection_out.txt'
573*795d594fSAndroid Build Coastguard Worker    logfile_path = ddir + '/' + runner_id + '_bisection_log.txt'
574*795d594fSAndroid Build Coastguard Worker    errfile_path = ddir + '/' + runner_id + '_bisection_err.txt'
575*795d594fSAndroid Build Coastguard Worker    args = list(args) + ['--logfile', logfile_path, '--cleanup']
576*795d594fSAndroid Build Coastguard Worker    args += ['--expected-retcode', expected_retcode.name]
577*795d594fSAndroid Build Coastguard Worker    if expected_output:
578*795d594fSAndroid Build Coastguard Worker      args += ['--expected-output', expected_output]
579*795d594fSAndroid Build Coastguard Worker    bisection_search_path = os.path.join(
580*795d594fSAndroid Build Coastguard Worker        GetEnvVariableOrError('ANDROID_BUILD_TOP'),
581*795d594fSAndroid Build Coastguard Worker        'art/tools/bisection_search/bisection_search.py')
582*795d594fSAndroid Build Coastguard Worker    if RunCommand([bisection_search_path] + args, out=outfile_path,
583*795d594fSAndroid Build Coastguard Worker                  err=errfile_path, timeout=300) == RetCode.TIMEOUT:
584*795d594fSAndroid Build Coastguard Worker      print('Bisection search TIMEOUT')
585*795d594fSAndroid Build Coastguard Worker
586*795d594fSAndroid Build Coastguard Worker  def MaybeBisectDivergence(self, retc1, retc2, is_output_divergence):
587*795d594fSAndroid Build Coastguard Worker    bisection_args1 = self._runner1.GetBisectionSearchArgs()
588*795d594fSAndroid Build Coastguard Worker    bisection_args2 = self._runner2.GetBisectionSearchArgs()
589*795d594fSAndroid Build Coastguard Worker    if is_output_divergence:
590*795d594fSAndroid Build Coastguard Worker      maybe_output1 = self._runner1.output_file
591*795d594fSAndroid Build Coastguard Worker      maybe_output2 = self._runner2.output_file
592*795d594fSAndroid Build Coastguard Worker    else:
593*795d594fSAndroid Build Coastguard Worker      maybe_output1 = maybe_output2 = None
594*795d594fSAndroid Build Coastguard Worker    if bisection_args1 is not None:
595*795d594fSAndroid Build Coastguard Worker      self.RunBisectionSearch(bisection_args1, retc2, maybe_output2,
596*795d594fSAndroid Build Coastguard Worker                              self._runner1.id)
597*795d594fSAndroid Build Coastguard Worker    if bisection_args2 is not None:
598*795d594fSAndroid Build Coastguard Worker      self.RunBisectionSearch(bisection_args2, retc1, maybe_output1,
599*795d594fSAndroid Build Coastguard Worker                              self._runner2.id)
600*795d594fSAndroid Build Coastguard Worker
601*795d594fSAndroid Build Coastguard Worker  def CleanupTest(self):
602*795d594fSAndroid Build Coastguard Worker    """Cleans up after a single test run."""
603*795d594fSAndroid Build Coastguard Worker    for file_name in os.listdir(self._jfuzz_dir):
604*795d594fSAndroid Build Coastguard Worker      file_path = os.path.join(self._jfuzz_dir, file_name)
605*795d594fSAndroid Build Coastguard Worker      if os.path.isfile(file_path):
606*795d594fSAndroid Build Coastguard Worker        os.unlink(file_path)
607*795d594fSAndroid Build Coastguard Worker      elif os.path.isdir(file_path):
608*795d594fSAndroid Build Coastguard Worker        shutil.rmtree(file_path)
609*795d594fSAndroid Build Coastguard Worker
610*795d594fSAndroid Build Coastguard Worker
611*795d594fSAndroid Build Coastguard Workerdef main():
612*795d594fSAndroid Build Coastguard Worker  # Handle arguments.
613*795d594fSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
614*795d594fSAndroid Build Coastguard Worker  parser.add_argument('--num_tests', default=10000, type=int,
615*795d594fSAndroid Build Coastguard Worker                      help='number of tests to run')
616*795d594fSAndroid Build Coastguard Worker  parser.add_argument('--device', help='target device serial number')
617*795d594fSAndroid Build Coastguard Worker  parser.add_argument('--mode1', default='ri',
618*795d594fSAndroid Build Coastguard Worker                      help='execution mode 1 (default: ri)')
619*795d594fSAndroid Build Coastguard Worker  parser.add_argument('--mode2', default='hopt',
620*795d594fSAndroid Build Coastguard Worker                      help='execution mode 2 (default: hopt)')
621*795d594fSAndroid Build Coastguard Worker  parser.add_argument('--report_script',
622*795d594fSAndroid Build Coastguard Worker                      help='script called for each divergence')
623*795d594fSAndroid Build Coastguard Worker  parser.add_argument('--jfuzz_arg', default=[], dest='jfuzz_args',
624*795d594fSAndroid Build Coastguard Worker                      action='append',
625*795d594fSAndroid Build Coastguard Worker                      help='argument for jfuzz')
626*795d594fSAndroid Build Coastguard Worker  parser.add_argument('--true_divergence', default=False, action='store_true',
627*795d594fSAndroid Build Coastguard Worker                      help='do not bisect timeout divergences')
628*795d594fSAndroid Build Coastguard Worker  parser.add_argument('--dexer', default='dx', type=str,
629*795d594fSAndroid Build Coastguard Worker                      help='defines dexer as dx or d8 (default: dx)')
630*795d594fSAndroid Build Coastguard Worker  parser.add_argument('--debug_info', default=False, action='store_true',
631*795d594fSAndroid Build Coastguard Worker                      help='include debugging info')
632*795d594fSAndroid Build Coastguard Worker  args = parser.parse_args()
633*795d594fSAndroid Build Coastguard Worker  if args.mode1 == args.mode2:
634*795d594fSAndroid Build Coastguard Worker    raise FatalError('Identical execution modes given')
635*795d594fSAndroid Build Coastguard Worker  # Run the JFuzz tester.
636*795d594fSAndroid Build Coastguard Worker  with JFuzzTester(args.num_tests,
637*795d594fSAndroid Build Coastguard Worker                   args.device,
638*795d594fSAndroid Build Coastguard Worker                   args.mode1, args.mode2,
639*795d594fSAndroid Build Coastguard Worker                   args.jfuzz_args,
640*795d594fSAndroid Build Coastguard Worker                   args.report_script,
641*795d594fSAndroid Build Coastguard Worker                   args.true_divergence,
642*795d594fSAndroid Build Coastguard Worker                   args.dexer,
643*795d594fSAndroid Build Coastguard Worker                   args.debug_info) as fuzzer:
644*795d594fSAndroid Build Coastguard Worker    fuzzer.Run()
645*795d594fSAndroid Build Coastguard Worker
646*795d594fSAndroid Build Coastguard Workerif __name__ == '__main__':
647*795d594fSAndroid Build Coastguard Worker  main()
648