From 1b154e367502946cae598b9872f2f03dc64aa089 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 6 Feb 2017 12:42:00 +0100 Subject: regrtest: don't fail immediately if a child does crash Issue #29362: Catch a crash of a worker process as a normal failure and continue to run next tests. It allows to get the usual test summary: single line result (OK/FAIL), total duration, etc. --- Lib/test/libregrtest/main.py | 2 +- Lib/test/libregrtest/runtest_mp.py | 7 +++---- Lib/test/test_regrtest.py | 13 ++++++++++++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 61a9876370..de1f4f9505 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -107,7 +107,7 @@ class Regrtest: self.test_times.append((test_time, test)) if ok == PASSED: self.good.append(test) - elif ok == FAILED: + elif ok in (FAILED, CHILD_ERROR): self.bad.append(test) elif ok == ENV_CHANGED: self.environment_changed.append(test) diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index 74ac4fa895..34b3ae6a97 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -129,7 +129,7 @@ class MultiprocessThread(threading.Thread): result = (CHILD_ERROR, "Exit code %s" % retcode) self.output.put((test, stdout.rstrip(), stderr.rstrip(), result)) - return True + return False if not result: self.output.put((None, None, None, None)) @@ -203,6 +203,8 @@ def run_tests_multiprocess(regrtest): and test_time >= PROGRESS_MIN_TIME and not regrtest.ns.pgo): text += ' (%.0f sec)' % test_time + elif ok == CHILD_ERROR: + text = '%s (%s)' % (text, test_time) running = get_running(workers) if running and not regrtest.ns.pgo: text += ' -- running: %s' % ', '.join(running) @@ -216,9 +218,6 @@ def run_tests_multiprocess(regrtest): if result[0] == INTERRUPTED: raise KeyboardInterrupt - if result[0] == CHILD_ERROR: - msg = "Child error on {}: {}".format(test, result[1]) - raise Exception(msg) test_index += 1 except KeyboardInterrupt: regrtest.interrupted = True diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 6d70e4d8f0..0bd62985d9 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -354,7 +354,7 @@ class BaseTestCase(unittest.TestCase): self.assertRegex(output, regex) def parse_executed_tests(self, output): - regex = (r'^[0-9]+:[0-9]+:[0-9]+ \[ *[0-9]+(?:/ *[0-9]+)?\] (%s)' + regex = (r'^[0-9]+:[0-9]+:[0-9]+ \[ *[0-9]+(?:/ *[0-9]+)*\] (%s)' % self.TESTNAME_REGEX) parser = re.finditer(regex, output, re.MULTILINE) return list(match.group(1) for match in parser) @@ -809,6 +809,17 @@ class ArgsTestCase(BaseTestCase): self.assertEqual(output.rstrip().splitlines(), tests) + def test_crashed(self): + # Any code which causes a crash + code = 'import faulthandler; faulthandler._sigsegv()' + crash_test = self.create_test(name="crash", code=code) + ok_test = self.create_test(name="ok") + + tests = [crash_test, ok_test] + output = self.run_tests("-j2", *tests, exitcode=1) + self.check_executed_tests(output, tests, failed=crash_test, + randomize=True) + if __name__ == '__main__': unittest.main() -- cgit v1.2.1