diff options
author | Alon Zakai <azakai@google.com> | 2024-11-21 11:11:48 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-21 11:11:48 -0800 |
commit | af5f74aeb3c53081ffaedbde18a77bdede0a697e (patch) | |
tree | 2dd7e09ad82e4d918f9d579c964fb8f25833f906 /test/unit/test_cluster_fuzz.py | |
parent | 45d8f24ad36562939bed14b2157fd5bb51c396bc (diff) | |
download | binaryen-af5f74aeb3c53081ffaedbde18a77bdede0a697e.tar.gz binaryen-af5f74aeb3c53081ffaedbde18a77bdede0a697e.tar.bz2 binaryen-af5f74aeb3c53081ffaedbde18a77bdede0a697e.zip |
Fuzzing: Append more JS operations in run.py (#7098)
The main fuzz_shell.js code builds and runs the given wasm. After the refactoring
in #7096, it is simple to append to that file and add more build and run operations,
adding more variety to the code, including cross-module interactions. Add logic
to run.py to do that for ClusterFuzz.
To test this, add a node test that builds a module with internal state that can
actually show which module is being executed. The test appends a build+run
operation, whose output prove that we are calling from the first module to the
second and vice versa.
Also add a ClusterFuzz test for run.py that verifies that we add a variety of
build/run operations.
Diffstat (limited to 'test/unit/test_cluster_fuzz.py')
-rw-r--r-- | test/unit/test_cluster_fuzz.py | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/test/unit/test_cluster_fuzz.py b/test/unit/test_cluster_fuzz.py index 1d275c712..8ec1d8928 100644 --- a/test/unit/test_cluster_fuzz.py +++ b/test/unit/test_cluster_fuzz.py @@ -247,6 +247,43 @@ class ClusterFuzz(utils.BinaryenTestCase): print() + # To check for interesting JS file contents, we'll note how many times + # we build and run the wasm. + seen_builds = [] + seen_calls = [] + + for i in range(1, N + 1): + fuzz_file = os.path.join(temp_dir.name, f'fuzz-binaryen-{i}.js') + with open(fuzz_file) as f: + js = f.read() + seen_builds.append(js.count('build(binary);')) + seen_calls.append(js.count('callExports();')) + + # There is always one build and one call (those are in the default + # fuzz_shell.js), and we add a couple of operations, each with equal + # probability to be a build or a call, so over the 100 testcases here we + # have an overwhelming probability to see at least one extra build and + # one extra call. + # + # builds and calls are distributed as mean 4, stddev 5, median 2. + print(f'mean JS builds: {statistics.mean(seen_builds)}') + print(f'stdev JS builds: {statistics.stdev(seen_builds)}') + print(f'median JS builds: {statistics.median(seen_builds)}') + # Assert on at least 2, which means we added at least one to the default + # one that always exists, as mentioned before. + self.assertGreaterEqual(max(seen_builds), 2) + self.assertGreater(statistics.stdev(seen_builds), 0) + + print() + + print(f'mean JS calls: {statistics.mean(seen_calls)}') + print(f'stdev JS calls: {statistics.stdev(seen_calls)}') + print(f'median JS calls: {statistics.median(seen_calls)}') + self.assertGreaterEqual(max(seen_calls), 2) + self.assertGreater(statistics.stdev(seen_calls), 0) + + print() + # "zzz" in test name so that this runs last. If it runs first, it can be # confusing as it appears next to the logging of which bundle we use (see # setUpClass). |