11cb0ef41Sopenharmony_ci# Copyright 2016 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci# found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci# Fork from commands.py and output.py in v8 test driver. 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ciimport os 81cb0ef41Sopenharmony_ciimport signal 91cb0ef41Sopenharmony_ciimport subprocess 101cb0ef41Sopenharmony_ciimport sys 111cb0ef41Sopenharmony_cifrom threading import Event, Timer 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ciimport v8_fuzz_config 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ciPYTHON3 = sys.version_info >= (3, 0) 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ci# List of default flags passed to each d8 run. 181cb0ef41Sopenharmony_ciDEFAULT_FLAGS = [ 191cb0ef41Sopenharmony_ci '--correctness-fuzzer-suppressions', 201cb0ef41Sopenharmony_ci '--expose-gc', 211cb0ef41Sopenharmony_ci '--fuzzing', 221cb0ef41Sopenharmony_ci '--allow-natives-for-differential-fuzzing', 231cb0ef41Sopenharmony_ci '--invoke-weak-callbacks', 241cb0ef41Sopenharmony_ci '--omit-quit', 251cb0ef41Sopenharmony_ci '--harmony', 261cb0ef41Sopenharmony_ci '--wasm-staging', 271cb0ef41Sopenharmony_ci '--no-wasm-async-compilation', 281cb0ef41Sopenharmony_ci '--suppress-asm-messages', 291cb0ef41Sopenharmony_ci] 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ciBASE_PATH = os.path.dirname(os.path.abspath(__file__)) 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci# List of files passed to each d8 run before the testcase. 341cb0ef41Sopenharmony_ciDEFAULT_MOCK = os.path.join(BASE_PATH, 'v8_mock.js') 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci# Suppressions on JavaScript level for known issues. 371cb0ef41Sopenharmony_ciJS_SUPPRESSIONS = os.path.join(BASE_PATH, 'v8_suppressions.js') 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci# Config-specific mock files. 401cb0ef41Sopenharmony_ciARCH_MOCKS = os.path.join(BASE_PATH, 'v8_mock_archs.js') 411cb0ef41Sopenharmony_ciWEBASSEMBLY_MOCKS = os.path.join(BASE_PATH, 'v8_mock_webassembly.js') 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_cidef _startup_files(options): 451cb0ef41Sopenharmony_ci """Default files and optional config-specific mock files.""" 461cb0ef41Sopenharmony_ci files = [DEFAULT_MOCK] 471cb0ef41Sopenharmony_ci if not options.skip_suppressions: 481cb0ef41Sopenharmony_ci files.append(JS_SUPPRESSIONS) 491cb0ef41Sopenharmony_ci if options.first.arch != options.second.arch: 501cb0ef41Sopenharmony_ci files.append(ARCH_MOCKS) 511cb0ef41Sopenharmony_ci # Mock out WebAssembly when comparing with jitless mode. 521cb0ef41Sopenharmony_ci if '--jitless' in options.first.flags + options.second.flags: 531cb0ef41Sopenharmony_ci files.append(WEBASSEMBLY_MOCKS) 541cb0ef41Sopenharmony_ci return files 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ciclass BaseException(Exception): 581cb0ef41Sopenharmony_ci """Used to abort the comparison workflow and print the given message.""" 591cb0ef41Sopenharmony_ci def __init__(self, message): 601cb0ef41Sopenharmony_ci self.message = message 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ciclass PassException(BaseException): 641cb0ef41Sopenharmony_ci """Represents an early abort making the overall run pass.""" 651cb0ef41Sopenharmony_ci pass 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ciclass FailException(BaseException): 691cb0ef41Sopenharmony_ci """Represents an early abort making the overall run fail.""" 701cb0ef41Sopenharmony_ci pass 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ciclass Command(object): 741cb0ef41Sopenharmony_ci """Represents a configuration for running V8 multiple times with certain 751cb0ef41Sopenharmony_ci flags and files. 761cb0ef41Sopenharmony_ci """ 771cb0ef41Sopenharmony_ci def __init__(self, options, label, executable, config_flags): 781cb0ef41Sopenharmony_ci self.label = label 791cb0ef41Sopenharmony_ci self.executable = executable 801cb0ef41Sopenharmony_ci self.config_flags = config_flags 811cb0ef41Sopenharmony_ci self.common_flags = DEFAULT_FLAGS[:] 821cb0ef41Sopenharmony_ci self.common_flags.extend(['--random-seed', str(options.random_seed)]) 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci self.files = _startup_files(options) 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci def run(self, testcase, timeout, verbose=False): 871cb0ef41Sopenharmony_ci """Run the executable with a specific testcase.""" 881cb0ef41Sopenharmony_ci args = [self.executable] + self.flags + self.files + [testcase] 891cb0ef41Sopenharmony_ci if verbose: 901cb0ef41Sopenharmony_ci print('# Command line for %s comparison:' % self.label) 911cb0ef41Sopenharmony_ci print(' '.join(args)) 921cb0ef41Sopenharmony_ci if self.executable.endswith('.py'): 931cb0ef41Sopenharmony_ci # Wrap with python in tests. 941cb0ef41Sopenharmony_ci args = [sys.executable] + args 951cb0ef41Sopenharmony_ci return Execute( 961cb0ef41Sopenharmony_ci args, 971cb0ef41Sopenharmony_ci cwd=os.path.dirname(os.path.abspath(testcase)), 981cb0ef41Sopenharmony_ci timeout=timeout, 991cb0ef41Sopenharmony_ci ) 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci @property 1021cb0ef41Sopenharmony_ci def flags(self): 1031cb0ef41Sopenharmony_ci return self.common_flags + self.config_flags 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ciclass Output(object): 1071cb0ef41Sopenharmony_ci def __init__(self, exit_code, stdout, pid): 1081cb0ef41Sopenharmony_ci self.exit_code = exit_code 1091cb0ef41Sopenharmony_ci self.stdout = stdout 1101cb0ef41Sopenharmony_ci self.pid = pid 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci def HasCrashed(self): 1131cb0ef41Sopenharmony_ci return self.exit_code < 0 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_cidef Execute(args, cwd, timeout=None): 1171cb0ef41Sopenharmony_ci popen_args = [c for c in args if c != ""] 1181cb0ef41Sopenharmony_ci kwargs = {} 1191cb0ef41Sopenharmony_ci if PYTHON3: 1201cb0ef41Sopenharmony_ci kwargs['encoding'] = 'utf-8' 1211cb0ef41Sopenharmony_ci try: 1221cb0ef41Sopenharmony_ci process = subprocess.Popen( 1231cb0ef41Sopenharmony_ci args=popen_args, 1241cb0ef41Sopenharmony_ci stdout=subprocess.PIPE, 1251cb0ef41Sopenharmony_ci stderr=subprocess.PIPE, 1261cb0ef41Sopenharmony_ci cwd=cwd, 1271cb0ef41Sopenharmony_ci **kwargs 1281cb0ef41Sopenharmony_ci ) 1291cb0ef41Sopenharmony_ci except Exception as e: 1301cb0ef41Sopenharmony_ci sys.stderr.write("Error executing: %s\n" % popen_args) 1311cb0ef41Sopenharmony_ci raise e 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci timeout_event = Event() 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci def kill_process(): 1361cb0ef41Sopenharmony_ci timeout_event.set() 1371cb0ef41Sopenharmony_ci try: 1381cb0ef41Sopenharmony_ci process.kill() 1391cb0ef41Sopenharmony_ci except OSError: 1401cb0ef41Sopenharmony_ci sys.stderr.write('Error: Process %s already ended.\n' % process.pid) 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci timer = Timer(timeout, kill_process) 1431cb0ef41Sopenharmony_ci timer.start() 1441cb0ef41Sopenharmony_ci stdout, _ = process.communicate() 1451cb0ef41Sopenharmony_ci timer.cancel() 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci if timeout_event.is_set(): 1481cb0ef41Sopenharmony_ci raise PassException('# V8 correctness - T-I-M-E-O-U-T') 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci return Output( 1511cb0ef41Sopenharmony_ci process.returncode, 1521cb0ef41Sopenharmony_ci stdout, 1531cb0ef41Sopenharmony_ci process.pid, 1541cb0ef41Sopenharmony_ci ) 155