Commit 236de01f authored by Antoine Pitrou's avatar Antoine Pitrou

Issue #15320: Make iterating the list of tests thread-safe when running tests in multiprocess mode.

Patch by Chris Jerdonek.
parent 3fd0b42a
...@@ -550,16 +550,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -550,16 +550,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
debug_output_pat = re.compile(r"\[\d+ refs\]$") debug_output_pat = re.compile(r"\[\d+ refs\]$")
output = Queue() output = Queue()
def tests_and_args(): pending = MultiprocessTests(tests)
for test in tests:
args_tuple = (
(test, verbose, quiet),
dict(huntrleaks=huntrleaks, use_resources=use_resources,
debug=debug, output_on_failure=verbose3,
failfast=failfast, match_tests=match_tests)
)
yield (test, args_tuple)
pending = tests_and_args()
opt_args = support.args_from_interpreter_flags() opt_args = support.args_from_interpreter_flags()
base_cmd = [sys.executable] + opt_args + ['-m', 'test.regrtest'] base_cmd = [sys.executable] + opt_args + ['-m', 'test.regrtest']
def work(): def work():
...@@ -567,10 +558,16 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -567,10 +558,16 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
try: try:
while True: while True:
try: try:
test, args_tuple = next(pending) test = next(pending)
except StopIteration: except StopIteration:
output.put((None, None, None, None)) output.put((None, None, None, None))
return return
args_tuple = (
(test, verbose, quiet),
dict(huntrleaks=huntrleaks, use_resources=use_resources,
debug=debug, output_on_failure=verbose3,
failfast=failfast, match_tests=match_tests)
)
# -E is needed by some tests, e.g. test_import # -E is needed by some tests, e.g. test_import
# Running the child from the same working directory ensures # Running the child from the same working directory ensures
# that TEMPDIR for the child is the same when # that TEMPDIR for the child is the same when
...@@ -622,7 +619,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -622,7 +619,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
test_index += 1 test_index += 1
except KeyboardInterrupt: except KeyboardInterrupt:
interrupted = True interrupted = True
pending.close() pending.interrupted = True
for worker in workers: for worker in workers:
worker.join() worker.join()
else: else:
...@@ -766,6 +763,25 @@ def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS): ...@@ -766,6 +763,25 @@ def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS):
tests.append(modname) tests.append(modname)
return stdtests + sorted(tests) return stdtests + sorted(tests)
# We do not use a generator so multiple threads can call next().
class MultiprocessTests(object):
"""A thread-safe iterator over tests for multiprocess mode."""
def __init__(self, tests):
self.interrupted = False
self.lock = threading.Lock()
self.tests = tests
def __iter__(self):
return self
def __next__(self):
with self.lock:
if self.interrupted:
raise StopIteration('tests interrupted')
return next(self.tests)
def replace_stdout(): def replace_stdout():
"""Set stdout encoder error handler to backslashreplace (as stderr error """Set stdout encoder error handler to backslashreplace (as stderr error
handler) to avoid UnicodeEncodeError when printing a traceback""" handler) to avoid UnicodeEncodeError when printing a traceback"""
......
...@@ -378,6 +378,9 @@ Extension Modules ...@@ -378,6 +378,9 @@ Extension Modules
Tests Tests
----- -----
- Issue #15320: Make iterating the list of tests thread-safe when running
tests in multiprocess mode. Patch by Chris Jerdonek.
- Issue #15230: Adopted a more systematic approach in the runpy tests - Issue #15230: Adopted a more systematic approach in the runpy tests
- Issue #15300: Ensure the temporary test working directories are in the same - Issue #15300: Ensure the temporary test working directories are in the same
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment