bpo-36725: Refactor regrtest multiprocessing code (GH-12961)
Rewrite run_tests_multiprocess() function as a new MultiprocessRunner
class with multiple methods to better report errors and stop
immediately when needed.
Changes:
* Worker processes are now killed immediately if tests are
interrupted or if a test does crash (CHILD_ERROR): worker
processes are killed.
* Rewrite how errors in a worker thread are reported to
the main thread. No longer ignore BaseException or parsing errors
silently.
* Remove 'finished' variable: use worker.is_alive() instead
* Always compute omitted tests. Add Regrtest.get_executed() method.
diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py
index ef1336a..606dc26 100644
--- a/Lib/test/libregrtest/main.py
+++ b/Lib/test/libregrtest/main.py
@@ -79,8 +79,8 @@
self.skipped = []
self.resource_denieds = []
self.environment_changed = []
- self.rerun = []
self.run_no_tests = []
+ self.rerun = []
self.first_result = None
self.interrupted = False
@@ -105,6 +105,11 @@
# used by --junit-xml
self.testsuite_xml = None
+ def get_executed(self):
+ return (set(self.good) | set(self.bad) | set(self.skipped)
+ | set(self.resource_denieds) | set(self.environment_changed)
+ | set(self.run_no_tests))
+
def accumulate_result(self, result):
test_name = result.test_name
ok = result.result
@@ -311,8 +316,6 @@
self.bad.remove(test_name)
if ok.result == INTERRUPTED:
- # print a newline separate from the ^C
- print()
self.interrupted = True
break
else:
@@ -331,11 +334,11 @@
print("== Tests result: %s ==" % self.get_tests_result())
if self.interrupted:
- print()
- # print a newline after ^C
print("Test suite interrupted by signal SIGINT.")
- executed = set(self.good) | set(self.bad) | set(self.skipped)
- omitted = set(self.selected) - executed
+
+ omitted = set(self.selected) - self.get_executed()
+ if omitted:
+ print()
print(count(len(omitted), "test"), "omitted:")
printlist(omitted)