Reland "[foozzie] Refactor command abstraction"
This is a reland of 1d493d31ce
Original change's description:
> [foozzie] Refactor command abstraction
>
> This moves code for running d8 into its own class. No functional
> changes intended.
>
> No-Try: true
> Bug: chromium:1023091
> Change-Id: I7cbfeebd2911dc758322f89cf93666550f2956d9
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1906378
> Commit-Queue: Michael Achenbach <machenbach@chromium.org>
> Reviewed-by: Tamer Tas <tmrts@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#64928}
Bug: chromium:1023091
Change-Id: I7df6e12084e20510a400ce209827c2bba8325f86
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1914209
Reviewed-by: Tamer Tas <tmrts@chromium.org>
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64966}
This commit is contained in:
parent
72d440d97d
commit
2475c91bb3
@ -4,11 +4,82 @@
|
|||||||
|
|
||||||
# Fork from commands.py and output.py in v8 test driver.
|
# Fork from commands.py and output.py in v8 test driver.
|
||||||
|
|
||||||
|
import os
|
||||||
import signal
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from threading import Event, Timer
|
from threading import Event, Timer
|
||||||
|
|
||||||
|
import v8_fuzz_config
|
||||||
|
|
||||||
|
# List of default flags passed to each d8 run.
|
||||||
|
DEFAULT_FLAGS = [
|
||||||
|
'--correctness-fuzzer-suppressions',
|
||||||
|
'--expose-gc',
|
||||||
|
'--allow-natives-syntax',
|
||||||
|
'--invoke-weak-callbacks',
|
||||||
|
'--omit-quit',
|
||||||
|
'--es-staging',
|
||||||
|
'--wasm-staging',
|
||||||
|
'--no-wasm-async-compilation',
|
||||||
|
'--suppress-asm-messages',
|
||||||
|
]
|
||||||
|
|
||||||
|
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
# List of files passed to each d8 run before the testcase.
|
||||||
|
DEFAULT_FILES = [
|
||||||
|
os.path.join(BASE_PATH, 'v8_mock.js'),
|
||||||
|
os.path.join(BASE_PATH, 'v8_suppressions.js'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Architecture-specific mock file
|
||||||
|
ARCH_MOCKS = os.path.join(BASE_PATH, 'v8_mock_archs.js')
|
||||||
|
|
||||||
|
# Timeout in seconds for one d8 run.
|
||||||
|
TIMEOUT = 3
|
||||||
|
|
||||||
|
|
||||||
|
def _startup_files(options):
|
||||||
|
"""Default files and optional architecture-specific mock file."""
|
||||||
|
files = DEFAULT_FILES[:]
|
||||||
|
if options.first_arch != options.second_arch:
|
||||||
|
files.append(ARCH_MOCKS)
|
||||||
|
return files
|
||||||
|
|
||||||
|
|
||||||
|
class Command(object):
|
||||||
|
"""Represents a configuration for running V8 multiple times with certain
|
||||||
|
flags and files.
|
||||||
|
"""
|
||||||
|
def __init__(self, options, label, executable, config_flags):
|
||||||
|
self.label = label
|
||||||
|
self.executable = executable
|
||||||
|
self.config_flags = config_flags
|
||||||
|
self.common_flags = DEFAULT_FLAGS[:]
|
||||||
|
self.common_flags.extend(['--random-seed', str(options.random_seed)])
|
||||||
|
|
||||||
|
self.files = _startup_files(options)
|
||||||
|
|
||||||
|
def run(self, testcase, verbose=False):
|
||||||
|
"""Run the executable with a specific testcase."""
|
||||||
|
args = [self.executable] + self.flags + self.files + [testcase]
|
||||||
|
if verbose:
|
||||||
|
print('# Command line for %s comparison:' % self.label)
|
||||||
|
print(' '.join(args))
|
||||||
|
if self.executable.endswith('.py'):
|
||||||
|
# Wrap with python in tests.
|
||||||
|
args = [sys.executable] + args
|
||||||
|
return Execute(
|
||||||
|
args,
|
||||||
|
cwd=os.path.dirname(os.path.abspath(testcase)),
|
||||||
|
timeout=TIMEOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def flags(self):
|
||||||
|
return self.common_flags + self.config_flags
|
||||||
|
|
||||||
|
|
||||||
class Output(object):
|
class Output(object):
|
||||||
def __init__(self, exit_code, timed_out, stdout, pid):
|
def __init__(self, exit_code, timed_out, stdout, pid):
|
||||||
@ -50,7 +121,6 @@ def Execute(args, cwd, timeout=None):
|
|||||||
except OSError:
|
except OSError:
|
||||||
sys.stderr.write('Error: Process %s already ended.\n' % process.pid)
|
sys.stderr.write('Error: Process %s already ended.\n' % process.pid)
|
||||||
|
|
||||||
|
|
||||||
timer = Timer(timeout, kill_process)
|
timer = Timer(timeout, kill_process)
|
||||||
timer.start()
|
timer.start()
|
||||||
stdout, _ = process.communicate()
|
stdout, _ = process.communicate()
|
||||||
|
@ -88,26 +88,13 @@ CONFIGS = dict(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Timeout in seconds for one d8 run.
|
|
||||||
TIMEOUT = 3
|
|
||||||
|
|
||||||
# Return codes.
|
# Return codes.
|
||||||
RETURN_PASS = 0
|
RETURN_PASS = 0
|
||||||
RETURN_FAIL = 2
|
RETURN_FAIL = 2
|
||||||
|
|
||||||
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
|
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||||
PREAMBLE = [
|
|
||||||
os.path.join(BASE_PATH, 'v8_mock.js'),
|
|
||||||
os.path.join(BASE_PATH, 'v8_suppressions.js'),
|
|
||||||
]
|
|
||||||
ARCH_MOCKS = os.path.join(BASE_PATH, 'v8_mock_archs.js')
|
|
||||||
SANITY_CHECKS = os.path.join(BASE_PATH, 'v8_sanity_checks.js')
|
SANITY_CHECKS = os.path.join(BASE_PATH, 'v8_sanity_checks.js')
|
||||||
|
|
||||||
FLAGS = ['--correctness-fuzzer-suppressions', '--expose-gc',
|
|
||||||
'--allow-natives-syntax', '--invoke-weak-callbacks', '--omit-quit',
|
|
||||||
'--es-staging', '--wasm-staging', '--no-wasm-async-compilation',
|
|
||||||
'--suppress-asm-messages']
|
|
||||||
|
|
||||||
SUPPORTED_ARCHS = ['ia32', 'x64', 'arm', 'arm64']
|
SUPPORTED_ARCHS = ['ia32', 'x64', 'arm', 'arm64']
|
||||||
|
|
||||||
# Output for suppressed failure case.
|
# Output for suppressed failure case.
|
||||||
@ -274,7 +261,7 @@ def fail_bailout(output, ignore_by_output_fun):
|
|||||||
|
|
||||||
|
|
||||||
def print_difference(
|
def print_difference(
|
||||||
options, source_key, first_config_flags, second_config_flags,
|
options, source_key, first_command, second_command,
|
||||||
first_config_output, second_config_output, difference, source=None):
|
first_config_output, second_config_output, difference, source=None):
|
||||||
# The first three entries will be parsed by clusterfuzz. Format changes
|
# The first three entries will be parsed by clusterfuzz. Format changes
|
||||||
# will require changes on the clusterfuzz side.
|
# will require changes on the clusterfuzz side.
|
||||||
@ -288,8 +275,8 @@ def print_difference(
|
|||||||
suppression='', # We can't tie bugs to differences.
|
suppression='', # We can't tie bugs to differences.
|
||||||
first_config_label=first_config_label,
|
first_config_label=first_config_label,
|
||||||
second_config_label=second_config_label,
|
second_config_label=second_config_label,
|
||||||
first_config_flags=' '.join(first_config_flags),
|
first_config_flags=' '.join(first_command.flags),
|
||||||
second_config_flags=' '.join(second_config_flags),
|
second_config_flags=' '.join(second_command.flags),
|
||||||
first_config_output=
|
first_config_output=
|
||||||
first_config_output.stdout.decode('utf-8', 'replace'),
|
first_config_output.stdout.decode('utf-8', 'replace'),
|
||||||
second_config_output=
|
second_config_output=
|
||||||
@ -317,36 +304,21 @@ def main():
|
|||||||
return RETURN_FAIL
|
return RETURN_FAIL
|
||||||
|
|
||||||
# Set up runtime arguments.
|
# Set up runtime arguments.
|
||||||
common_flags = FLAGS + ['--random-seed', str(options.random_seed)]
|
first_config_flags = (CONFIGS[options.first_config] +
|
||||||
first_config_flags = (common_flags + CONFIGS[options.first_config] +
|
|
||||||
options.first_config_extra_flags)
|
options.first_config_extra_flags)
|
||||||
second_config_flags = (common_flags + CONFIGS[options.second_config] +
|
second_config_flags = (CONFIGS[options.second_config] +
|
||||||
options.second_config_extra_flags)
|
options.second_config_extra_flags)
|
||||||
|
|
||||||
def run_d8(d8, config_flags, config_label=None, testcase=options.testcase):
|
first_cmd = v8_commands.Command(
|
||||||
preamble = PREAMBLE[:]
|
options,'first', options.first_d8, first_config_flags)
|
||||||
if options.first_arch != options.second_arch:
|
second_cmd = v8_commands.Command(
|
||||||
preamble.append(ARCH_MOCKS)
|
options, 'second', options.second_d8, second_config_flags)
|
||||||
args = [d8] + config_flags + preamble + [testcase]
|
|
||||||
if config_label:
|
|
||||||
print('# Command line for %s comparison:' % config_label)
|
|
||||||
print(' '.join(args))
|
|
||||||
if d8.endswith('.py'):
|
|
||||||
# Wrap with python in tests.
|
|
||||||
args = [sys.executable] + args
|
|
||||||
return v8_commands.Execute(
|
|
||||||
args,
|
|
||||||
cwd=os.path.dirname(os.path.abspath(testcase)),
|
|
||||||
timeout=TIMEOUT,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Sanity checks. Run both configurations with the sanity-checks file only and
|
# Sanity checks. Run both configurations with the sanity-checks file only and
|
||||||
# bail out early if different.
|
# bail out early if different.
|
||||||
if not options.skip_sanity_checks:
|
if not options.skip_sanity_checks:
|
||||||
first_config_output = run_d8(
|
first_config_output = first_cmd.run(SANITY_CHECKS)
|
||||||
options.first_d8, first_config_flags, testcase=SANITY_CHECKS)
|
second_config_output = second_cmd.run(SANITY_CHECKS)
|
||||||
second_config_output = run_d8(
|
|
||||||
options.second_d8, second_config_flags, testcase=SANITY_CHECKS)
|
|
||||||
difference, _ = suppress.diff(
|
difference, _ = suppress.diff(
|
||||||
first_config_output.stdout, second_config_output.stdout)
|
first_config_output.stdout, second_config_output.stdout)
|
||||||
if difference:
|
if difference:
|
||||||
@ -354,18 +326,17 @@ def main():
|
|||||||
# cases on this in case it's hit.
|
# cases on this in case it's hit.
|
||||||
source_key = 'sanity check failed'
|
source_key = 'sanity check failed'
|
||||||
print_difference(
|
print_difference(
|
||||||
options, source_key, first_config_flags, second_config_flags,
|
options, source_key, first_cmd, second_cmd,
|
||||||
first_config_output, second_config_output, difference)
|
first_config_output, second_config_output, difference)
|
||||||
return RETURN_FAIL
|
return RETURN_FAIL
|
||||||
|
|
||||||
first_config_output = run_d8(options.first_d8, first_config_flags, 'first')
|
first_config_output = first_cmd.run(options.testcase, verbose=True)
|
||||||
|
|
||||||
# Early bailout based on first run's output.
|
# Early bailout based on first run's output.
|
||||||
if pass_bailout(first_config_output, 1):
|
if pass_bailout(first_config_output, 1):
|
||||||
return RETURN_PASS
|
return RETURN_PASS
|
||||||
|
|
||||||
second_config_output = run_d8(
|
second_config_output = second_cmd.run(options.testcase, verbose=True)
|
||||||
options.second_d8, second_config_flags, 'second')
|
|
||||||
|
|
||||||
# Bailout based on second run's output.
|
# Bailout based on second run's output.
|
||||||
if pass_bailout(second_config_output, 2):
|
if pass_bailout(second_config_output, 2):
|
||||||
@ -389,7 +360,7 @@ def main():
|
|||||||
return RETURN_FAIL
|
return RETURN_FAIL
|
||||||
|
|
||||||
print_difference(
|
print_difference(
|
||||||
options, source_key, first_config_flags, second_config_flags,
|
options, source_key, first_cmd, second_cmd,
|
||||||
first_config_output, second_config_output, difference, source)
|
first_config_output, second_config_output, difference, source)
|
||||||
return RETURN_FAIL
|
return RETURN_FAIL
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user