mirror of https://github.com/python/cpython.git
gh-119727: Add --single-process option to regrtest (#119728)
(cherry picked from commit 4e8aa32245
)
Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
parent
3822d7cd28
commit
350313e731
|
@ -174,6 +174,7 @@ def __init__(self, **kwargs) -> None:
|
||||||
self.tempdir = None
|
self.tempdir = None
|
||||||
self._add_python_opts = True
|
self._add_python_opts = True
|
||||||
self.xmlpath = None
|
self.xmlpath = None
|
||||||
|
self.single_process = False
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
@ -307,6 +308,12 @@ def _create_parser():
|
||||||
group.add_argument('-j', '--multiprocess', metavar='PROCESSES',
|
group.add_argument('-j', '--multiprocess', metavar='PROCESSES',
|
||||||
dest='use_mp', type=int,
|
dest='use_mp', type=int,
|
||||||
help='run PROCESSES processes at once')
|
help='run PROCESSES processes at once')
|
||||||
|
group.add_argument('--single-process', action='store_true',
|
||||||
|
dest='single_process',
|
||||||
|
help='always run all tests sequentially in '
|
||||||
|
'a single process, ignore -jN option, '
|
||||||
|
'and failed tests are also rerun sequentially '
|
||||||
|
'in the same process')
|
||||||
group.add_argument('-T', '--coverage', action='store_true',
|
group.add_argument('-T', '--coverage', action='store_true',
|
||||||
dest='trace',
|
dest='trace',
|
||||||
help='turn on code coverage tracing using the trace '
|
help='turn on code coverage tracing using the trace '
|
||||||
|
@ -433,6 +440,10 @@ def _parse_args(args, **kwargs):
|
||||||
else:
|
else:
|
||||||
ns._add_python_opts = False
|
ns._add_python_opts = False
|
||||||
|
|
||||||
|
# --singleprocess overrides -jN option
|
||||||
|
if ns.single_process:
|
||||||
|
ns.use_mp = None
|
||||||
|
|
||||||
# When both --slow-ci and --fast-ci options are present,
|
# When both --slow-ci and --fast-ci options are present,
|
||||||
# --slow-ci has the priority
|
# --slow-ci has the priority
|
||||||
if ns.slow_ci:
|
if ns.slow_ci:
|
||||||
|
|
|
@ -89,12 +89,13 @@ def __init__(self, ns: Namespace, _add_python_opts: bool = False):
|
||||||
self.cmdline_args: TestList = ns.args
|
self.cmdline_args: TestList = ns.args
|
||||||
|
|
||||||
# Workers
|
# Workers
|
||||||
if ns.use_mp is None:
|
self.single_process: bool = ns.single_process
|
||||||
num_workers = 0 # run sequentially
|
if self.single_process or ns.use_mp is None:
|
||||||
|
num_workers = 0 # run sequentially in a single process
|
||||||
elif ns.use_mp <= 0:
|
elif ns.use_mp <= 0:
|
||||||
num_workers = -1 # use the number of CPUs
|
num_workers = -1 # run in parallel, use the number of CPUs
|
||||||
else:
|
else:
|
||||||
num_workers = ns.use_mp
|
num_workers = ns.use_mp # run in parallel
|
||||||
self.num_workers: int = num_workers
|
self.num_workers: int = num_workers
|
||||||
self.worker_json: StrJSON | None = ns.worker_json
|
self.worker_json: StrJSON | None = ns.worker_json
|
||||||
|
|
||||||
|
@ -236,7 +237,7 @@ def list_tests(tests: TestTuple):
|
||||||
|
|
||||||
def _rerun_failed_tests(self, runtests: RunTests):
|
def _rerun_failed_tests(self, runtests: RunTests):
|
||||||
# Configure the runner to re-run tests
|
# Configure the runner to re-run tests
|
||||||
if self.num_workers == 0:
|
if self.num_workers == 0 and not self.single_process:
|
||||||
# Always run tests in fresh processes to have more deterministic
|
# Always run tests in fresh processes to have more deterministic
|
||||||
# initial state. Don't re-run tests in parallel but limit to a
|
# initial state. Don't re-run tests in parallel but limit to a
|
||||||
# single worker process to have side effects (on the system load
|
# single worker process to have side effects (on the system load
|
||||||
|
@ -246,7 +247,6 @@ def _rerun_failed_tests(self, runtests: RunTests):
|
||||||
tests, match_tests_dict = self.results.prepare_rerun()
|
tests, match_tests_dict = self.results.prepare_rerun()
|
||||||
|
|
||||||
# Re-run failed tests
|
# Re-run failed tests
|
||||||
self.log(f"Re-running {len(tests)} failed tests in verbose mode in subprocesses")
|
|
||||||
runtests = runtests.copy(
|
runtests = runtests.copy(
|
||||||
tests=tests,
|
tests=tests,
|
||||||
rerun=True,
|
rerun=True,
|
||||||
|
@ -256,7 +256,15 @@ def _rerun_failed_tests(self, runtests: RunTests):
|
||||||
match_tests_dict=match_tests_dict,
|
match_tests_dict=match_tests_dict,
|
||||||
output_on_failure=False)
|
output_on_failure=False)
|
||||||
self.logger.set_tests(runtests)
|
self.logger.set_tests(runtests)
|
||||||
self._run_tests_mp(runtests, self.num_workers)
|
|
||||||
|
msg = f"Re-running {len(tests)} failed tests in verbose mode"
|
||||||
|
if not self.single_process:
|
||||||
|
msg = f"{msg} in subprocesses"
|
||||||
|
self.log(msg)
|
||||||
|
self._run_tests_mp(runtests, self.num_workers)
|
||||||
|
else:
|
||||||
|
self.log(msg)
|
||||||
|
self.run_tests_sequentially(runtests)
|
||||||
return runtests
|
return runtests
|
||||||
|
|
||||||
def rerun_failed_tests(self, runtests: RunTests):
|
def rerun_failed_tests(self, runtests: RunTests):
|
||||||
|
@ -371,7 +379,7 @@ def run_tests_sequentially(self, runtests) -> None:
|
||||||
tests = count(jobs, 'test')
|
tests = count(jobs, 'test')
|
||||||
else:
|
else:
|
||||||
tests = 'tests'
|
tests = 'tests'
|
||||||
msg = f"Run {tests} sequentially"
|
msg = f"Run {tests} sequentially in a single process"
|
||||||
if runtests.timeout:
|
if runtests.timeout:
|
||||||
msg += " (timeout: %s)" % format_duration(runtests.timeout)
|
msg += " (timeout: %s)" % format_duration(runtests.timeout)
|
||||||
self.log(msg)
|
self.log(msg)
|
||||||
|
@ -599,7 +607,7 @@ def _add_cross_compile_opts(self, regrtest_opts):
|
||||||
keep_environ = True
|
keep_environ = True
|
||||||
|
|
||||||
if cross_compile and hostrunner:
|
if cross_compile and hostrunner:
|
||||||
if self.num_workers == 0:
|
if self.num_workers == 0 and not self.single_process:
|
||||||
# For now use only two cores for cross-compiled builds;
|
# For now use only two cores for cross-compiled builds;
|
||||||
# hostrunner can be expensive.
|
# hostrunner can be expensive.
|
||||||
regrtest_opts.extend(['-j', '2'])
|
regrtest_opts.extend(['-j', '2'])
|
||||||
|
|
|
@ -475,6 +475,19 @@ def test_verbose3_huntrleaks(self):
|
||||||
self.assertEqual(regrtest.hunt_refleak.runs, 10)
|
self.assertEqual(regrtest.hunt_refleak.runs, 10)
|
||||||
self.assertFalse(regrtest.output_on_failure)
|
self.assertFalse(regrtest.output_on_failure)
|
||||||
|
|
||||||
|
def test_single_process(self):
|
||||||
|
args = ['-j2', '--single-process']
|
||||||
|
with support.captured_stderr():
|
||||||
|
regrtest = self.create_regrtest(args)
|
||||||
|
self.assertEqual(regrtest.num_workers, 0)
|
||||||
|
self.assertTrue(regrtest.single_process)
|
||||||
|
|
||||||
|
args = ['--fast-ci', '--single-process']
|
||||||
|
with support.captured_stderr():
|
||||||
|
regrtest = self.create_regrtest(args)
|
||||||
|
self.assertEqual(regrtest.num_workers, 0)
|
||||||
|
self.assertTrue(regrtest.single_process)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(slots=True)
|
@dataclasses.dataclass(slots=True)
|
||||||
class Rerun:
|
class Rerun:
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Add ``--single-process`` command line option to Python test runner (regrtest).
|
||||||
|
Patch by Victor Stinner.
|
Loading…
Reference in New Issue