Skip to content

Commit 0e2eb12

Browse files
Print failed test results at the end for the spec test suite (#8154)
* Print all failed test stdouts/stderrs at the end so that the output isn't lost among the successful tests * Make `shared.options.abort_on_first_failure` work with the spec test suite and add aliases for --fail-fast and --no-fail-fast * Re-raise in run_one_spec_test since fail_with_error may no longer throw an exception when abort_on_first_failure is false (the remaining code shouldn't execute because then `actual` isn't defined).
1 parent 9452643 commit 0e2eb12

File tree

2 files changed

+41
-12
lines changed

2 files changed

+41
-12
lines changed

check.py

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import sys
2222
import unittest
2323
from collections import OrderedDict
24+
from contextlib import contextmanager
2425
from multiprocessing.pool import ThreadPool
2526
from pathlib import Path
2627

@@ -219,6 +220,7 @@ def run_one_spec_test(wast: Path, stdout=None):
219220
return # don't try all the binary format stuff TODO
220221
else:
221222
shared.fail_with_error(str(e))
223+
raise
222224

223225
check_expected(actual, expected, stdout=stdout)
224226

@@ -248,32 +250,64 @@ def run_one_spec_test(wast: Path, stdout=None):
248250

249251

250252
def run_spec_test_with_wrapped_stdout(wast: Path):
253+
"""Return (bool, str) where the first element is whether the test was
254+
successful and the second is the combined stdout and stderr of the test.
255+
"""
251256
out = io.StringIO()
252257
try:
253258
run_one_spec_test(wast, stdout=out)
254259
except Exception as e:
255260
# Serialize exceptions into the output string buffer
256261
# so they can be reported on the main thread.
257262
print(e, file=out)
258-
raise
259-
return out.getvalue()
263+
return False, out.getvalue()
264+
return True, out.getvalue()
265+
266+
267+
@contextmanager
268+
def red_output(file=sys.stdout):
269+
print("\033[31m", end="", file=file)
270+
try:
271+
yield
272+
finally:
273+
print("\033[0m", end="", file=file)
274+
275+
276+
def red_stderr():
277+
return red_output(file=sys.stderr)
260278

261279

262280
def run_spec_tests():
263281
print('\n[ checking wasm-shell spec testcases... ]\n')
264282

265283
worker_count = os.cpu_count()
266284
print("Running with", worker_count, "workers")
267-
test_paths = [Path(x) for x in shared.options.spec_tests]
285+
test_paths = (Path(x) for x in shared.options.spec_tests)
286+
287+
failed_stdouts = []
268288
with ThreadPool(processes=worker_count) as pool:
269289
try:
270-
for result in pool.imap_unordered(run_spec_test_with_wrapped_stdout, test_paths):
271-
print(result, end="")
290+
for success, stdout in pool.imap_unordered(run_spec_test_with_wrapped_stdout, test_paths):
291+
if success:
292+
print(stdout, end="")
293+
continue
294+
295+
failed_stdouts.append(stdout)
296+
if shared.options.abort_on_first_failure:
297+
with red_stderr():
298+
print("Aborted spec test suite execution after first failure. Set --no-fail-fast to disable this.", file=sys.stderr)
299+
break
272300
except KeyboardInterrupt:
273301
# Hard exit to avoid threads continuing to run after Ctrl-C.
274302
# There's no concern of deadlocking during shutdown here.
275303
os._exit(1)
276304

305+
if failed_stdouts:
306+
with red_stderr():
307+
print("Failed tests:", file=sys.stderr)
308+
for failed in failed_stdouts:
309+
print(failed, end="", file=sys.stderr)
310+
277311

278312
def run_validator_tests():
279313
print('\n[ running validation tests... ]\n')

scripts/test/shared.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,10 @@ def parse_args(args):
4040
'--no-torture', dest='torture', action='store_false',
4141
help='Disables running the torture testcases.')
4242
parser.add_argument(
43-
'--abort-on-first-failure', dest='abort_on_first_failure',
44-
action='store_true', default=True,
43+
'--abort-on-first-failure', '--fail-fast', dest='abort_on_first_failure',
44+
action=argparse.BooleanOptionalAction, default=True,
4545
help=('Specifies whether to halt test suite execution on first test error.'
4646
' Default: true.'))
47-
parser.add_argument(
48-
'--no-abort-on-first-failure', dest='abort_on_first_failure',
49-
action='store_false',
50-
help=('If set, the whole test suite will run to completion independent of'
51-
' earlier errors.'))
5247
parser.add_argument(
5348
'--binaryen-bin', dest='binaryen_bin', default='',
5449
help=('Specifies the path to the Binaryen executables in the CMake build'

0 commit comments

Comments
 (0)