diff --git a/check.py b/check.py index 3d1ca8aef46..2275687bb6d 100755 --- a/check.py +++ b/check.py @@ -16,13 +16,10 @@ import functools import glob -import io import os import subprocess import sys import unittest -from contextlib import contextmanager -from multiprocessing.pool import ThreadPool from pathlib import Path from scripts.test import binaryenjs, finalize, shared, support, wasm2js, wasm_opt @@ -232,7 +229,6 @@ def run_one_spec_test(wast: Path, stdout=None): shared.verbose_log('<< test failed as expected >>', file=stdout) return # don't try all the binary format stuff TODO else: - shared.fail_with_error(str(e)) raise check_expected(actual, expected, stdout=stdout) @@ -265,67 +261,10 @@ def run_one_spec_test(wast: Path, stdout=None): check_expected(actual, os.path.join(shared.get_test_dir('spec'), 'expected-output', test_name + '.log'), stdout=stdout) -def run_spec_test_with_wrapped_stdout(wast: Path): - """Run a single spec test while capturing stdout. - - Return (bool, str) where the first element is whether the test was - successful and the second is the combined stdout and stderr of the test. - """ - out = io.StringIO() - try: - run_one_spec_test(wast, stdout=out) - except Exception as e: - shared.num_failures += 1 - # Serialize exceptions into the output string buffer - # so they can be reported on the main thread. - print(e, file=out) - return False, out.getvalue() - return True, out.getvalue() - - -@contextmanager -def red_output(file=sys.stdout): - print("\033[31m", end="", file=file) - try: - yield - finally: - print("\033[0m", end="", file=file) - - -def red_stderr(): - return red_output(file=sys.stderr) - - def run_spec_tests(): print_heading('checking wasm-shell spec testcases...') - - worker_count = os.cpu_count() - print("Running with", worker_count, "workers") test_paths = (Path(x) for x in shared.options.spec_tests) - - failed_stdouts = [] - with ThreadPool(processes=worker_count) as pool: - try: - for success, stdout in pool.imap_unordered(run_spec_test_with_wrapped_stdout, test_paths): - if success: - print(stdout, end="") - continue - - failed_stdouts.append(stdout) - if shared.options.abort_on_first_failure: - with red_stderr(): - print("Aborted spec test suite execution after first failure. Set --no-fail-fast to disable this.", file=sys.stderr) - break - except KeyboardInterrupt: - # Hard exit to avoid threads continuing to run after Ctrl-C. - # There's no concern of deadlocking during shutdown here. - os._exit(1) - - if failed_stdouts: - with red_stderr(): - print("Failed tests:", file=sys.stderr) - for failed in failed_stdouts: - print(failed, end="", file=sys.stderr) + shared.run_parallel_tests(run_one_spec_test, test_paths) def run_validator_tests(): diff --git a/scripts/test/shared.py b/scripts/test/shared.py index bd5bd9dc43b..4f9fbcf3110 100644 --- a/scripts/test/shared.py +++ b/scripts/test/shared.py @@ -17,12 +17,14 @@ import difflib import fnmatch import glob +import io import os import shutil import stat import subprocess import sys from contextlib import contextmanager +from multiprocessing.pool import ThreadPool from pathlib import Path # The C++ standard whose features are required to build Binaryen. @@ -126,6 +128,63 @@ def verbose_log(*args, **kwargs): print(*args, **kwargs) +@contextmanager +def red_output(file=sys.stderr): + print("\033[31m", end="", file=file) + try: + yield + finally: + print("\033[0m", end="", file=file) + + +def red_stderr(): + return red_output(file=sys.stderr) + + +def run_parallel_tests(run_one_test_func, tests, show_worker_count=True): + global num_failures + tests = list(tests) + if not tests: + return + worker_count = min(os.cpu_count() or 1, len(tests)) + if show_worker_count: + print(f"Running with {worker_count} workers") + + def run_test_with_wrapped_stdout(test): + out = io.StringIO() + try: + run_one_test_func(test, stdout=out) + except Exception as e: + print(e, file=out) + return False, out.getvalue() + return True, out.getvalue() + + failed_stdouts = [] + with ThreadPool(processes=worker_count) as pool: + try: + for success, stdout in pool.imap_unordered(run_test_with_wrapped_stdout, tests): + if success: + print(stdout, end="") + continue + + num_failures += 1 + failed_stdouts.append(stdout) + if options.abort_on_first_failure: + with red_stderr(): + print("Aborted test execution after first failure. Set --no-fail-fast to disable this.", file=sys.stderr) + break + except KeyboardInterrupt: + # Hard exit to avoid threads continuing to run after Ctrl-C. + # There's no concern of deadlocking during shutdown here. + os._exit(1) + + if failed_stdouts: + with red_stderr(): + print("Failed tests:", file=sys.stderr) + for failed in failed_stdouts: + print(failed, end="", file=sys.stderr) + + # setup # Locate Binaryen source directory if not specified.