mirror of
https://github.com/django/django.git
synced 2025-11-07 07:15:35 +00:00
Fixed #36678 -- Limited retries in ParallelTestRunner.
Thanks Natalia Bidart for the review.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import ctypes
|
import ctypes
|
||||||
import faulthandler
|
import faulthandler
|
||||||
|
import functools
|
||||||
import hashlib
|
import hashlib
|
||||||
import io
|
import io
|
||||||
import itertools
|
import itertools
|
||||||
@@ -485,6 +486,16 @@ def _init_worker(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _safe_init_worker(init_worker, counter, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
init_worker(counter, *args, **kwargs)
|
||||||
|
except Exception:
|
||||||
|
with counter.get_lock():
|
||||||
|
# Set a value that will not increment above zero any time soon.
|
||||||
|
counter.value = -1000
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def _run_subsuite(args):
|
def _run_subsuite(args):
|
||||||
"""
|
"""
|
||||||
Run a suite of tests with a RemoteTestRunner and return a RemoteTestResult.
|
Run a suite of tests with a RemoteTestRunner and return a RemoteTestResult.
|
||||||
@@ -558,7 +569,7 @@ class ParallelTestSuite(unittest.TestSuite):
|
|||||||
counter = multiprocessing.Value(ctypes.c_int, 0)
|
counter = multiprocessing.Value(ctypes.c_int, 0)
|
||||||
pool = multiprocessing.Pool(
|
pool = multiprocessing.Pool(
|
||||||
processes=self.processes,
|
processes=self.processes,
|
||||||
initializer=self.init_worker.__func__,
|
initializer=functools.partial(_safe_init_worker, self.init_worker.__func__),
|
||||||
initargs=[
|
initargs=[
|
||||||
counter,
|
counter,
|
||||||
self.initial_settings,
|
self.initial_settings,
|
||||||
@@ -585,7 +596,11 @@ class ParallelTestSuite(unittest.TestSuite):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
subsuite_index, events = test_results.next(timeout=0.1)
|
subsuite_index, events = test_results.next(timeout=0.1)
|
||||||
except multiprocessing.TimeoutError:
|
except multiprocessing.TimeoutError as err:
|
||||||
|
if counter.value < 0:
|
||||||
|
err.add_note("ERROR: _init_worker failed, see prior traceback")
|
||||||
|
pool.close()
|
||||||
|
raise
|
||||||
continue
|
continue
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
pool.close()
|
pool.close()
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ Tests for django test runner
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import collections.abc
|
import collections.abc
|
||||||
|
import functools
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@@ -738,8 +739,10 @@ class TestRunnerInitializerTests(SimpleTestCase):
|
|||||||
"test_runner_apps.simple.tests",
|
"test_runner_apps.simple.tests",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
# Initializer must be a function.
|
# Initializer must be a partial function binding _init_worker.
|
||||||
self.assertIs(mocked_pool.call_args.kwargs["initializer"], _init_worker)
|
initializer = mocked_pool.call_args.kwargs["initializer"]
|
||||||
|
self.assertIsInstance(initializer, functools.partial)
|
||||||
|
self.assertIs(initializer.args[0], _init_worker)
|
||||||
initargs = mocked_pool.call_args.kwargs["initargs"]
|
initargs = mocked_pool.call_args.kwargs["initargs"]
|
||||||
self.assertEqual(len(initargs), 7)
|
self.assertEqual(len(initargs), 7)
|
||||||
self.assertEqual(initargs[5], True) # debug_mode
|
self.assertEqual(initargs[5], True) # debug_mode
|
||||||
|
|||||||
Reference in New Issue
Block a user