summaryrefslogtreecommitdiff
path: root/deps/v8/tools/clusterfuzz
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/tools/clusterfuzz')
-rw-r--r--deps/v8/tools/clusterfuzz/testdata/baseline/d8.py5
-rw-r--r--deps/v8/tools/clusterfuzz/testdata/build3/d8.py7
-rw-r--r--deps/v8/tools/clusterfuzz/testdata/failure_output_arch.txt50
-rw-r--r--deps/v8/tools/clusterfuzz/testdata/failure_output_second.txt50
-rwxr-xr-xdeps/v8/tools/clusterfuzz/v8_foozzie.py87
-rwxr-xr-xdeps/v8/tools/clusterfuzz/v8_foozzie_test.py32
-rw-r--r--deps/v8/tools/clusterfuzz/v8_mock.js12
7 files changed, 218 insertions, 25 deletions
diff --git a/deps/v8/tools/clusterfuzz/testdata/baseline/d8.py b/deps/v8/tools/clusterfuzz/testdata/baseline/d8.py
index 4a3d008077..cd729b9cf7 100644
--- a/deps/v8/tools/clusterfuzz/testdata/baseline/d8.py
+++ b/deps/v8/tools/clusterfuzz/testdata/baseline/d8.py
@@ -5,6 +5,8 @@
# for py2/py3 compatibility
from __future__ import print_function
+import sys
+
print("""
1
v8-foozzie source: name/to/a/file.js
@@ -15,3 +17,6 @@ v8-foozzie source: name/to/file.js
3
unknown
""")
+
+if '--bad-flag' in sys.argv:
+ print('bad behavior')
diff --git a/deps/v8/tools/clusterfuzz/testdata/build3/d8.py b/deps/v8/tools/clusterfuzz/testdata/build3/d8.py
index 824b222485..a48a591d1e 100644
--- a/deps/v8/tools/clusterfuzz/testdata/build3/d8.py
+++ b/deps/v8/tools/clusterfuzz/testdata/build3/d8.py
@@ -5,6 +5,8 @@
# for py2/py3 compatibility
from __future__ import print_function
+import sys
+
print("""
1
v8-foozzie source: name/to/a/file.js
@@ -15,3 +17,8 @@ v8-foozzie source: name/to/file.js
3
unknown
""")
+
+if '--bad-flag' in sys.argv:
+ print('bad behavior')
+if '--very-bad-flag' in sys.argv:
+ print('very bad behavior')
diff --git a/deps/v8/tools/clusterfuzz/testdata/failure_output_arch.txt b/deps/v8/tools/clusterfuzz/testdata/failure_output_arch.txt
new file mode 100644
index 0000000000..bf72649c3e
--- /dev/null
+++ b/deps/v8/tools/clusterfuzz/testdata/failure_output_arch.txt
@@ -0,0 +1,50 @@
+#
+# V8 correctness failure
+# V8 correctness configs: x64,ignition:x64,ignition_turbo
+# V8 correctness sources: f60
+# V8 correctness suppression:
+#
+# CHECK
+#
+# Compared x64,ignition with x64,ignition_turbo
+#
+# Flags of x64,ignition:
+--correctness-fuzzer-suppressions --expose-gc --fuzzing --allow-natives-for-differential-fuzzing --invoke-weak-callbacks --omit-quit --es-staging --wasm-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345 --turbo-filter=~ --noopt --liftoff --no-wasm-tier-up
+# Flags of x64,ignition_turbo:
+--correctness-fuzzer-suppressions --expose-gc --fuzzing --allow-natives-for-differential-fuzzing --invoke-weak-callbacks --omit-quit --es-staging --wasm-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345 --bad-flag
+#
+# Difference:
++ bad behavior
+#
+# Source file:
+name/to/file.js
+#
+### Start of configuration x64,ignition:
+
+1
+v8-foozzie source: name/to/a/file.js
+2
+v8-foozzie source: name/to/file.js
+ weird error
+ ^
+3
+unknown
+
+
+### End of configuration x64,ignition
+#
+### Start of configuration x64,ignition_turbo:
+
+1
+v8-foozzie source: name/to/a/file.js
+2
+v8-foozzie source: name/to/file.js
+ weird error
+ ^
+3
+unknown
+
+bad behavior
+
+### End of configuration x64,ignition_turbo
+
diff --git a/deps/v8/tools/clusterfuzz/testdata/failure_output_second.txt b/deps/v8/tools/clusterfuzz/testdata/failure_output_second.txt
new file mode 100644
index 0000000000..030168884f
--- /dev/null
+++ b/deps/v8/tools/clusterfuzz/testdata/failure_output_second.txt
@@ -0,0 +1,50 @@
+#
+# V8 correctness failure
+# V8 correctness configs: x64,ignition:ia32,ignition_turbo
+# V8 correctness sources: f60
+# V8 correctness suppression:
+#
+# CHECK
+#
+# Compared x64,ignition with ia32,ignition_turbo
+#
+# Flags of x64,ignition:
+--correctness-fuzzer-suppressions --expose-gc --fuzzing --allow-natives-for-differential-fuzzing --invoke-weak-callbacks --omit-quit --es-staging --wasm-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345 --turbo-filter=~ --noopt --liftoff --no-wasm-tier-up
+# Flags of ia32,ignition_turbo:
+--correctness-fuzzer-suppressions --expose-gc --fuzzing --allow-natives-for-differential-fuzzing --invoke-weak-callbacks --omit-quit --es-staging --wasm-staging --no-wasm-async-compilation --suppress-asm-messages --random-seed 12345 --very-bad-flag
+#
+# Difference:
++ very bad behavior
+#
+# Source file:
+name/to/file.js
+#
+### Start of configuration x64,ignition:
+
+1
+v8-foozzie source: name/to/a/file.js
+2
+v8-foozzie source: name/to/file.js
+ weird error
+ ^
+3
+unknown
+
+
+### End of configuration x64,ignition
+#
+### Start of configuration ia32,ignition_turbo:
+
+1
+v8-foozzie source: name/to/a/file.js
+2
+v8-foozzie source: name/to/file.js
+ weird other error
+^
+3
+unknown
+
+very bad behavior
+
+### End of configuration ia32,ignition_turbo
+
diff --git a/deps/v8/tools/clusterfuzz/v8_foozzie.py b/deps/v8/tools/clusterfuzz/v8_foozzie.py
index 9f3810c9f5..52b7954093 100755
--- a/deps/v8/tools/clusterfuzz/v8_foozzie.py
+++ b/deps/v8/tools/clusterfuzz/v8_foozzie.py
@@ -211,14 +211,14 @@ class ExecutionArgumentsConfig(object):
'default: bundled in the directory of this script',
default=DEFAULT_D8)
- def make_options(self, options, default_config=None):
+ def make_options(self, options, default_config=None, default_d8=None):
def get(name):
return getattr(options, '%s_%s' % (self.label, name))
config = default_config or get('config')
assert config in CONFIGS
- d8 = get('d8')
+ d8 = default_d8 or get('d8')
if not os.path.isabs(d8):
d8 = os.path.join(BASE_PATH, d8)
assert os.path.exists(d8)
@@ -239,6 +239,13 @@ class ExecutionConfig(object):
flags = getattr(options, label).flags
self.command = Command(options, label, d8, flags)
+ # Options for a fallback configuration only exist when comparing
+ # different architectures.
+ fallback_label = label + '_fallback'
+ self.fallback = None
+ if getattr(options, fallback_label, None):
+ self.fallback = ExecutionConfig(options, fallback_label)
+
@property
def flags(self):
return self.command.flags
@@ -278,7 +285,15 @@ def parse_args():
options.first = first_config_arguments.make_options(options)
options.second = second_config_arguments.make_options(options)
options.default = second_config_arguments.make_options(
- options, DEFAULT_CONFIG)
+ options, default_config=DEFAULT_CONFIG)
+
+ # Use fallback configurations only on diffrent architectures. In this
+ # case we are going to re-test against the first architecture.
+ if options.first.arch != options.second.arch:
+ options.second_fallback = second_config_arguments.make_options(
+ options, default_d8=options.first.d8)
+ options.default_fallback = second_config_arguments.make_options(
+ options, default_config=DEFAULT_CONFIG, default_d8=options.first.d8)
# Ensure we make a valid comparison.
if (options.first.d8 == options.second.d8 and
@@ -315,10 +330,12 @@ def fail_bailout(output, ignore_by_output_fun):
def format_difference(
- source_key, first_config, second_config,
- first_config_output, second_config_output, difference, source=None):
+ first_config, second_config,
+ first_config_output, second_config_output,
+ difference, source_key=None, source=None):
# The first three entries will be parsed by clusterfuzz. Format changes
# will require changes on the clusterfuzz side.
+ source_key = source_key or cluster_failures(source)
first_config_label = '%s,%s' % (first_config.arch, first_config.config)
second_config_label = '%s,%s' % (second_config.arch, second_config.config)
source_file_text = SOURCE_FILE_TEMPLATE % source if source else ''
@@ -376,6 +393,29 @@ def cluster_failures(source, known_failures=None):
return long_key[:ORIGINAL_SOURCE_HASH_LENGTH]
+class RepeatedRuns(object):
+ """Helper class for storing statistical data from repeated runs."""
+ def __init__(self, test_case, timeout, verbose):
+ self.test_case = test_case
+ self.timeout = timeout
+ self.verbose = verbose
+
+ # Stores if any run has crashed or was simulated.
+ self.has_crashed = False
+ self.simulated = False
+
+ def run(self, config):
+ comparison_output = config.command.run(
+ self.test_case, timeout=self.timeout, verbose=self.verbose)
+ self.has_crashed = self.has_crashed or comparison_output.HasCrashed()
+ self.simulated = self.simulated or config.is_error_simulation
+ return comparison_output
+
+ @property
+ def crash_state(self):
+ return '_simulated_crash_' if self.simulated else '_unexpected_crash_'
+
+
def run_comparisons(suppress, execution_configs, test_case, timeout,
verbose=True, ignore_crashes=True, source_key=None):
"""Runs different configurations and bails out on output difference.
@@ -393,20 +433,15 @@ def run_comparisons(suppress, execution_configs, test_case, timeout,
source_key: A fixed source key. If not given, it will be inferred from the
output.
"""
- run_test_case = lambda config: config.command.run(
- test_case, timeout=timeout, verbose=verbose)
+ runner = RepeatedRuns(test_case, timeout, verbose)
# Run the baseline configuration.
baseline_config = execution_configs[0]
- baseline_output = run_test_case(baseline_config)
- has_crashed = baseline_output.HasCrashed()
- simulated = baseline_config.is_error_simulation
+ baseline_output = runner.run(baseline_config)
# Iterate over the remaining configurations, run and compare.
for comparison_config in execution_configs[1:]:
- comparison_output = run_test_case(comparison_config)
- has_crashed = has_crashed or comparison_output.HasCrashed()
- simulated = simulated or comparison_config.is_error_simulation
+ comparison_output = runner.run(comparison_config)
difference, source = suppress.diff(baseline_output, comparison_output)
if difference:
@@ -416,12 +451,25 @@ def run_comparisons(suppress, execution_configs, test_case, timeout,
fail_bailout(baseline_output, suppress.ignore_by_output)
fail_bailout(comparison_output, suppress.ignore_by_output)
- source_key = source_key or cluster_failures(source)
+ # Check if a difference also occurs with the fallback configuration and
+ # give it precedence. E.g. we always prefer x64 differences.
+ if comparison_config.fallback:
+ fallback_output = runner.run(comparison_config.fallback)
+ fallback_difference, fallback_source = suppress.diff(
+ baseline_output, fallback_output)
+ if fallback_difference:
+ fail_bailout(fallback_output, suppress.ignore_by_output)
+ source = fallback_source
+ comparison_config = comparison_config.fallback
+ comparison_output = fallback_output
+ difference = fallback_difference
+
raise FailException(format_difference(
- source_key, baseline_config, comparison_config,
- baseline_output, comparison_output, difference, source))
+ baseline_config, comparison_config,
+ baseline_output, comparison_output,
+ difference, source_key, source))
- if has_crashed:
+ if runner.has_crashed:
if ignore_crashes:
# Show if a crash has happened in one of the runs and no difference was
# detected. This is only for the statistics during experiments.
@@ -429,9 +477,8 @@ def run_comparisons(suppress, execution_configs, test_case, timeout,
else:
# Subsume simulated and unexpected crashes (e.g. during smoke tests)
# with one failure state.
- crash_state = '_simulated_crash_' if simulated else '_unexpected_crash_'
raise FailException(FAILURE_HEADER_TEMPLATE % dict(
- configs='', source_key='', suppression=crash_state))
+ configs='', source_key='', suppression=runner.crash_state))
def main():
@@ -448,7 +495,7 @@ def main():
content_bailout(content, suppress.ignore_by_content)
# Prepare the baseline, default and a secondary configuration to compare to.
- # The baseline (turbofan) takes precedence as many of the secondary configs
+ # The default (turbofan) takes precedence as many of the secondary configs
# are based on the turbofan config with additional parameters.
execution_configs = [
ExecutionConfig(options, 'first'),
diff --git a/deps/v8/tools/clusterfuzz/v8_foozzie_test.py b/deps/v8/tools/clusterfuzz/v8_foozzie_test.py
index eb8322ce62..a8ba74364b 100755
--- a/deps/v8/tools/clusterfuzz/v8_foozzie_test.py
+++ b/deps/v8/tools/clusterfuzz/v8_foozzie_test.py
@@ -263,7 +263,7 @@ class SystemTest(unittest.TestCase):
Overview of fakes:
baseline: Example foozzie output including a syntax error.
- build1: Difference to baseline is a stack trace differece expected to
+ build1: Difference to baseline is a stack trace difference expected to
be suppressed.
build2: Difference to baseline is a non-suppressed output difference
causing the script to fail.
@@ -312,6 +312,36 @@ class SystemTest(unittest.TestCase):
self.assertIn('v8_mock_archs.js', lines[1])
self.assertIn('v8_mock_archs.js', lines[3])
+ def testDifferentArchFailFirst(self):
+ """Test that we re-test against x64. This tests the path that also fails
+ on x64 and then reports the error as x64.
+ """
+ with open(os.path.join(TEST_DATA, 'failure_output_arch.txt')) as f:
+ expected_output = f.read()
+ # Build 3 simulates x86 and produces a difference on --bad-flag, but
+ # the baseline build shows the same difference when --bad-flag is passed.
+ with self.assertRaises(subprocess.CalledProcessError) as ctx:
+ run_foozzie('build3', '--skip-smoke-tests',
+ '--second-config-extra-flags=--bad-flag')
+ e = ctx.exception
+ self.assertEqual(v8_foozzie.RETURN_FAIL, e.returncode)
+ self.assertEqual(expected_output, cut_verbose_output(e.output, 3))
+
+ def testDifferentArchFailSecond(self):
+ """As above, but we test the path that only fails in the second (ia32)
+ run and not with x64 and then reports the error as ia32.
+ """
+ with open(os.path.join(TEST_DATA, 'failure_output_second.txt')) as f:
+ expected_output = f.read()
+ # Build 3 simulates x86 and produces a difference on --very-bad-flag,
+ # which the baseline build doesn't.
+ with self.assertRaises(subprocess.CalledProcessError) as ctx:
+ run_foozzie('build3', '--skip-smoke-tests',
+ '--second-config-extra-flags=--very-bad-flag')
+ e = ctx.exception
+ self.assertEqual(v8_foozzie.RETURN_FAIL, e.returncode)
+ self.assertEqual(expected_output, cut_verbose_output(e.output, 3))
+
def testJitless(self):
"""Test that webassembly is mocked out when comparing with jitless."""
stdout = run_foozzie(
diff --git a/deps/v8/tools/clusterfuzz/v8_mock.js b/deps/v8/tools/clusterfuzz/v8_mock.js
index be7a40b70f..41f1901d5d 100644
--- a/deps/v8/tools/clusterfuzz/v8_mock.js
+++ b/deps/v8/tools/clusterfuzz/v8_mock.js
@@ -99,7 +99,11 @@ Object.defineProperty(
// Mock buffer access in float typed arrays because of varying NaN patterns.
(function() {
+ const origArrayFrom = Array.from;
+ const origArrayIsArray = Array.isArray;
+ const origFunctionPrototype = Function.prototype;
const origIsNaN = isNaN;
+ const origIterator = Symbol.iterator;
const deNaNify = function(value) { return origIsNaN(value) ? 1 : value; };
const mock = function(type) {
@@ -117,17 +121,17 @@ Object.defineProperty(
construct: function(target, args) {
for (let i = 0; i < args.length; i++) {
if (args[i] != null &&
- typeof args[i][Symbol.iterator] === 'function') {
+ typeof args[i][origIterator] === 'function') {
// Consume iterators.
- args[i] = Array.from(args[i]);
+ args[i] = origArrayFrom(args[i]);
}
- if (Array.isArray(args[i])) {
+ if (origArrayIsArray(args[i])) {
args[i] = args[i].map(deNaNify);
}
}
const obj = new (
- Function.prototype.bind.call(type, null, ...args));
+ origFunctionPrototype.bind.call(type, null, ...args));
return new Proxy(obj, {
get: function(x, prop) {
if (typeof x[prop] == "function")