Skip to content

Commit 130029f

Browse files
committed
Refactor
1 parent 149f300 commit 130029f

1 file changed

Lines changed: 85 additions & 55 deletions

File tree

test/unit/test_fuzz_preserve.py

Lines changed: 85 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -8,84 +8,108 @@
88
from . import utils
99

1010

11-
class PreserveFuzzTest(utils.BinaryenTestCase):
12-
def test_against_js(self):
13-
# When --fuzz-against-js is used, the wasm is only going to be fuzzed
14-
# against JS, so the fuzzer mutates the boundary in valid ways, even if
15-
# --fuzz-preserve-imports-exports is set.
16-
#
17-
# Testing this deterministically is too hard (as the fuzzer evolves, it
18-
# will handle random data differently, and the test would constantly get
19-
# out of date). Instead, test randomly, but in a way that the chance of
20-
# a flake is unrealistic.
21-
max_size = 1024
11+
# Runs the fuzzer many times and allows checking for specific variety in the
12+
# output. Calls hooks:
13+
#
14+
# self.found_variety() - checks if we found what we are looking for
15+
# self.process_wat(wat) - receives the current fuzz wat
16+
#
17+
class FuzzerVarietyTester:
18+
# Run until we find what we want. Stop only if we reached a max number
19+
# of iterations and a timeout.
20+
max_time = 60
21+
min_iters = 200
22+
23+
# The maximum size of the wasm-generating input
24+
max_size = 1024
25+
26+
def __init__(self, initial):
27+
self.initial = initial
28+
29+
def test(self):
2230
temp_dat = tempfile.NamedTemporaryFile(suffix='.dat')
23-
initial = self.input_path('fuzz.wat')
24-
25-
# The set of all params we see, for the import that is refinable. Ditto
26-
# for export results.
27-
import_params = set()
28-
export_results = set()
2931

30-
# Run until we find what we want. Stop only if we reached a max number
31-
# of iterations and a timeout.
32-
min_iters = 200
3332
start_time = time.time()
34-
# Locally this succeeds in less than 1 second. Give it a very wide
35-
# margin of error to avoid flakes.
36-
max_time = start_time + 60
33+
stop_time = start_time + self.max_time
3734

3835
i = 0
3936
while True:
4037
i += 1
4138

42-
if self.found_expected(import_params) and self.found_expected(export_results):
39+
# Stop early if we found what we are looking for.
40+
if self.found_variety():
4341
print(f"{i} iterations {round(time.time() - start_time, 2)} seconds)")
44-
print(f'proper import_params : {import_params}')
45-
print(f'proper export_results: {export_results}')
42+
print(f'proper import_params : {self.import_params}')
43+
print(f'proper export_results: {self.export_results}')
4644
return
4745

48-
if i > min_iters and time.time() > max_time:
46+
if i > self.min_iters and time.time() > stop_time:
4947
raise Exception('looked too long and still failed')
5048

5149
# Generate raw random data
52-
size = random.randint(1, max_size)
50+
size = random.randint(1, self.max_size)
5351
with open(temp_dat.name, 'wb') as f:
5452
f.write(bytes([random.randint(0, 255) for x in range(size)]))
5553

5654
# Generate the fuzz testcase from the random data + the initial
5755
# contents.
58-
args = ['-ttf', temp_dat.name, '--initial-fuzz=' + initial, '-all']
59-
args += ['--fuzz-preserve-imports-exports', '--fuzz-against-js']
56+
args = ['-ttf', temp_dat.name, '--initial-fuzz=' + self.initial, '-all']
57+
args += self.ttf_args
6058
args += ['--print']
6159
wat = shared.run_process(shared.WASM_OPT + args,
6260
stdout=subprocess.PIPE).stdout
6361

64-
# The things that begin reffed might end up not reffed, if mutation
65-
# removes the refs. Check for that.
66-
import_reffed_is_reffed = '(ref.func $import-reffed)' in wat
67-
export_reffed_is_reffed = '(ref.func $export-reffed)' in wat
68-
69-
# Find the params/results that might be refined.
70-
for line in wat.splitlines():
71-
if line.startswith(' (import "module" "base" (func $import '):
72-
params, results = self.parse_params_results(line)
73-
import_params.add(params)
74-
assert results == '(result eqref)', 'cannot refine import result'
75-
elif line.startswith(' (import "module" "base" (func $import-reffed '):
76-
params, results = self.parse_params_results(line)
77-
if import_reffed_is_reffed:
78-
assert params == '(param i32 anyref)', 'cannot refine reffed stuff'
79-
assert results == '(result eqref)', 'cannot refine import result'
80-
if line.startswith(' (func $export '):
81-
params, results = self.parse_params_results(line)
82-
assert params == '(param $0 i32) (param $1 anyref)', 'cannot refine export params'
83-
export_results.add(results)
84-
if line.startswith(' (func $export-reffed '):
85-
params, results = self.parse_params_results(line)
86-
assert params == '(param $0 i32) (param $1 anyref)', 'cannot refine export params'
87-
if export_reffed_is_reffed:
88-
assert results == '(result eqref)', 'cannot refine reffed stuff'
62+
self.process_wat(wat)
63+
64+
65+
class FuzzAgainstJSVarietyTester(FuzzerVarietyTester):
66+
# When --fuzz-against-js is used, the wasm is only going to be fuzzed
67+
# against JS, so the fuzzer mutates the boundary in valid ways, even if
68+
# --fuzz-preserve-imports-exports is set.
69+
#
70+
# Testing this deterministically is too hard (as the fuzzer evolves, it
71+
# will handle random data differently, and the test would constantly get
72+
# out of date). Instead, test randomly, but in a way that the chance of
73+
# a flake is unrealistic.
74+
ttf_args = ['--fuzz-preserve-imports-exports', '--fuzz-against-js']
75+
76+
def __init__(self, initial):
77+
super().__init__(initial)
78+
79+
# The set of all params we see, for the import that is refinable. Ditto
80+
# for export results.
81+
self.import_params = set()
82+
self.export_results = set()
83+
84+
def found_variety(self):
85+
return self.found_expected(self.import_params) and self.found_expected(self.export_results)
86+
87+
def process_wat(self, wat):
88+
# The things that begin reffed might end up not reffed, if mutation
89+
# removes the refs. Check for that.
90+
import_reffed_is_reffed = '(ref.func $import-reffed)' in wat
91+
export_reffed_is_reffed = '(ref.func $export-reffed)' in wat
92+
93+
# Find the params/results that might be refined.
94+
for line in wat.splitlines():
95+
if line.startswith(' (import "module" "base" (func $import '):
96+
params, results = self.parse_params_results(line)
97+
self.import_params.add(params)
98+
assert results == '(result eqref)', 'cannot refine import result'
99+
elif line.startswith(' (import "module" "base" (func $import-reffed '):
100+
params, results = self.parse_params_results(line)
101+
if import_reffed_is_reffed:
102+
assert params == '(param i32 anyref)', 'cannot refine reffed stuff'
103+
assert results == '(result eqref)', 'cannot refine import result'
104+
if line.startswith(' (func $export '):
105+
params, results = self.parse_params_results(line)
106+
assert params == '(param $0 i32) (param $1 anyref)', 'cannot refine export params'
107+
self.export_results.add(results)
108+
if line.startswith(' (func $export-reffed '):
109+
params, results = self.parse_params_results(line)
110+
assert params == '(param $0 i32) (param $1 anyref)', 'cannot refine export params'
111+
if export_reffed_is_reffed:
112+
assert results == '(result eqref)', 'cannot refine reffed stuff'
89113

90114
# Given the types we saw for params or results, look in detail for the
91115
# things we expect to see.
@@ -161,3 +185,9 @@ def get(what, line):
161185
return ret
162186

163187
return get('(param', line), get('(result', line)
188+
189+
190+
class PreserveFuzzTest(utils.BinaryenTestCase):
191+
def test_against_js(self):
192+
FuzzAgainstJSVarietyTester(self.input_path('fuzz.wat')).test()
193+

0 commit comments

Comments
 (0)