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