summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/fuzz_opt.py62
1 files changed, 43 insertions, 19 deletions
diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py
index 595ee933e..49a2c3f73 100644
--- a/scripts/fuzz_opt.py
+++ b/scripts/fuzz_opt.py
@@ -14,19 +14,29 @@ script covers different options being passed)
'''
import os
-import sys
import difflib
import subprocess
import random
import shutil
import time
+from test.shared import options
+
+
# parameters
+
LOG_LIMIT = 125
INPUT_SIZE_LIMIT = 250 * 1024
+# utilities
+
+
+def in_bin(tool):
+ return os.path.join(options.binaryen_root, 'bin', tool)
+
+
def random_size():
return random.randint(1, INPUT_SIZE_LIMIT)
@@ -50,9 +60,13 @@ def randomize_pass_debug():
del os.environ['BINARYEN_PASS_DEBUG']
+# Test outputs we want to ignore are marked this way.
+IGNORE = '[binaryen-fuzzer-ignore]'
+
+
def test_one(infile, opts):
def compare(x, y, comment):
- if x != y:
+ if x != y and x != IGNORE and y != IGNORE:
message = ''.join([a.rstrip() + '\n' for a in difflib.unified_diff(x.split('\n'), y.split('\n'), fromfile='expected', tofile='actual')])
raise Exception(str(comment) + ": Expected to have '%s' == '%s', diff:\n\n%s" % (
x, y,
@@ -88,9 +102,27 @@ def test_one(infile, opts):
out = '\n'.join(map(lambda x: x if 'f32' not in x and 'f64' not in x else '', out.split('\n')))
return out
+ def run_vm(cmd):
+ # ignore some vm assertions, if bugs have already been filed
+ known_issues = [
+ 'local count too large', # ignore this; can be caused by flatten, ssa, etc. passes
+ 'liftoff-assembler.cc, line 239\n', # https://bugs.chromium.org/p/v8/issues/detail?id=8631
+ 'liftoff-register.h, line 86\n', # https://bugs.chromium.org/p/v8/issues/detail?id=8632
+ ]
+ try:
+ return run(cmd)
+ except:
+ output = run_unchecked(cmd)
+ for issue in known_issues:
+ if issue in output:
+ return IGNORE
+ raise
+
results = []
# append to this list to add results from VMs
- # results += [fix_output(run([os.path.expanduser('d8'), '--', prefix + 'js', prefix + 'wasm']))]
+ results += [fix_output(run_vm([os.path.expanduser('d8'), prefix + 'js', '--', prefix + 'wasm']))]
+ results += [fix_output(run_vm([os.path.expanduser('d8-debug'), '--wasm-tier-up', prefix + 'js', '--', prefix + 'wasm']))]
+ results += [fix_output(run_vm([os.path.expanduser('d8-debug'), '--no-wasm-tier-up', prefix + 'js', '--', prefix + 'wasm']))]
# spec has no mechanism to not halt on a trap. so we just check until the first trap, basically
# run(['../spec/interpreter/wasm', prefix + 'wasm'])
# results += [fix_spec_output(run_unchecked(['../spec/interpreter/wasm', prefix + 'wasm', '-e', open(prefix + 'wat').read()]))]
@@ -110,14 +142,14 @@ def test_one(infile, opts):
# fuzz vms
# gather VM outputs on input file
- run(['bin/wasm-opt', infile, '-ttf', '--emit-js-wrapper=a.js', '--emit-spec-wrapper=a.wat', '-o', 'a.wasm'])
+ run([in_bin('wasm-opt'), infile, '-ttf', '--emit-js-wrapper=a.js', '--emit-spec-wrapper=a.wat', '-o', 'a.wasm', '--mvp-features'])
wasm_size = os.stat('a.wasm').st_size
bytes += wasm_size
print('pre js size :', os.stat('a.js').st_size, ' wasm size:', wasm_size)
before = run_vms('a.')
print('----------------')
# gather VM outputs on processed file
- run(['bin/wasm-opt', 'a.wasm', '-o', 'b.wasm'] + opts)
+ run([in_bin('wasm-opt'), 'a.wasm', '-o', 'b.wasm'] + opts)
wasm_size = os.stat('b.wasm').st_size
bytes += wasm_size
print('post js size:', os.stat('a.js').st_size, ' wasm size:', wasm_size)
@@ -126,11 +158,11 @@ def test_one(infile, opts):
for i in range(len(before)):
compare(before[i], after[i], 'comparing between builds at ' + str(i))
# fuzz binaryen interpreter itself. separate invocation so result is easily fuzzable
- run(['bin/wasm-opt', 'a.wasm', '--fuzz-exec', '--fuzz-binary'] + opts)
+ run([in_bin('wasm-opt'), 'a.wasm', '--fuzz-exec', '--fuzz-binary'] + opts)
# check for determinism
- run(['bin/wasm-opt', 'a.wasm', '-o', 'b.wasm'] + opts)
- run(['bin/wasm-opt', 'a.wasm', '-o', 'c.wasm'] + opts)
- assert open('b.wasm').read() == open('c.wasm').read()
+ run([in_bin('wasm-opt'), 'a.wasm', '-o', 'b.wasm'] + opts)
+ run([in_bin('wasm-opt'), 'a.wasm', '-o', 'c.wasm'] + opts)
+ assert open('b.wasm').read() == open('c.wasm').read(), 'output must be deterministic'
return bytes
@@ -202,17 +234,9 @@ def get_multiple_opt_choices():
# main
-if len(sys.argv) >= 2:
- print('checking given input')
- if len(sys.argv) >= 3:
- test_one(sys.argv[1], sys.argv[2:])
- else:
- for opts in opt_choices:
- print(opts)
- test_one(sys.argv[1], opts)
-else:
+if __name__ == '__main__':
print('checking infinite random inputs')
- random.seed(time.time())
+ random.seed(time.time() * os.getpid())
temp = 'input.dat'
counter = 0
bytes = 0 # wasm bytes tested