Skip to content

Commit 350313e

Browse files
mhsmithvstinner
andauthored
[3.13] gh-119727: Add --single-process option to regrtest (#119728) (#123010)
gh-119727: Add --single-process option to regrtest (#119728) (cherry picked from commit 4e8aa32) Co-authored-by: Victor Stinner <[email protected]>
1 parent 3822d7c commit 350313e

File tree

4 files changed

+43
-9
lines changed

4 files changed

+43
-9
lines changed

Lib/test/libregrtest/cmdline.py

+11
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ def __init__(self, **kwargs) -> None:
174174
self.tempdir = None
175175
self._add_python_opts = True
176176
self.xmlpath = None
177+
self.single_process = False
177178

178179
super().__init__(**kwargs)
179180

@@ -307,6 +308,12 @@ def _create_parser():
307308
group.add_argument('-j', '--multiprocess', metavar='PROCESSES',
308309
dest='use_mp', type=int,
309310
help='run PROCESSES processes at once')
311+
group.add_argument('--single-process', action='store_true',
312+
dest='single_process',
313+
help='always run all tests sequentially in '
314+
'a single process, ignore -jN option, '
315+
'and failed tests are also rerun sequentially '
316+
'in the same process')
310317
group.add_argument('-T', '--coverage', action='store_true',
311318
dest='trace',
312319
help='turn on code coverage tracing using the trace '
@@ -433,6 +440,10 @@ def _parse_args(args, **kwargs):
433440
else:
434441
ns._add_python_opts = False
435442

443+
# --singleprocess overrides -jN option
444+
if ns.single_process:
445+
ns.use_mp = None
446+
436447
# When both --slow-ci and --fast-ci options are present,
437448
# --slow-ci has the priority
438449
if ns.slow_ci:

Lib/test/libregrtest/main.py

+17-9
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,13 @@ def __init__(self, ns: Namespace, _add_python_opts: bool = False):
8989
self.cmdline_args: TestList = ns.args
9090

9191
# Workers
92-
if ns.use_mp is None:
93-
num_workers = 0 # run sequentially
92+
self.single_process: bool = ns.single_process
93+
if self.single_process or ns.use_mp is None:
94+
num_workers = 0 # run sequentially in a single process
9495
elif ns.use_mp <= 0:
95-
num_workers = -1 # use the number of CPUs
96+
num_workers = -1 # run in parallel, use the number of CPUs
9697
else:
97-
num_workers = ns.use_mp
98+
num_workers = ns.use_mp # run in parallel
9899
self.num_workers: int = num_workers
99100
self.worker_json: StrJSON | None = ns.worker_json
100101

@@ -236,7 +237,7 @@ def list_tests(tests: TestTuple):
236237

237238
def _rerun_failed_tests(self, runtests: RunTests):
238239
# Configure the runner to re-run tests
239-
if self.num_workers == 0:
240+
if self.num_workers == 0 and not self.single_process:
240241
# Always run tests in fresh processes to have more deterministic
241242
# initial state. Don't re-run tests in parallel but limit to a
242243
# single worker process to have side effects (on the system load
@@ -246,7 +247,6 @@ def _rerun_failed_tests(self, runtests: RunTests):
246247
tests, match_tests_dict = self.results.prepare_rerun()
247248

248249
# Re-run failed tests
249-
self.log(f"Re-running {len(tests)} failed tests in verbose mode in subprocesses")
250250
runtests = runtests.copy(
251251
tests=tests,
252252
rerun=True,
@@ -256,7 +256,15 @@ def _rerun_failed_tests(self, runtests: RunTests):
256256
match_tests_dict=match_tests_dict,
257257
output_on_failure=False)
258258
self.logger.set_tests(runtests)
259-
self._run_tests_mp(runtests, self.num_workers)
259+
260+
msg = f"Re-running {len(tests)} failed tests in verbose mode"
261+
if not self.single_process:
262+
msg = f"{msg} in subprocesses"
263+
self.log(msg)
264+
self._run_tests_mp(runtests, self.num_workers)
265+
else:
266+
self.log(msg)
267+
self.run_tests_sequentially(runtests)
260268
return runtests
261269

262270
def rerun_failed_tests(self, runtests: RunTests):
@@ -371,7 +379,7 @@ def run_tests_sequentially(self, runtests) -> None:
371379
tests = count(jobs, 'test')
372380
else:
373381
tests = 'tests'
374-
msg = f"Run {tests} sequentially"
382+
msg = f"Run {tests} sequentially in a single process"
375383
if runtests.timeout:
376384
msg += " (timeout: %s)" % format_duration(runtests.timeout)
377385
self.log(msg)
@@ -599,7 +607,7 @@ def _add_cross_compile_opts(self, regrtest_opts):
599607
keep_environ = True
600608

601609
if cross_compile and hostrunner:
602-
if self.num_workers == 0:
610+
if self.num_workers == 0 and not self.single_process:
603611
# For now use only two cores for cross-compiled builds;
604612
# hostrunner can be expensive.
605613
regrtest_opts.extend(['-j', '2'])

Lib/test/test_regrtest.py

+13
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,19 @@ def test_verbose3_huntrleaks(self):
475475
self.assertEqual(regrtest.hunt_refleak.runs, 10)
476476
self.assertFalse(regrtest.output_on_failure)
477477

478+
def test_single_process(self):
479+
args = ['-j2', '--single-process']
480+
with support.captured_stderr():
481+
regrtest = self.create_regrtest(args)
482+
self.assertEqual(regrtest.num_workers, 0)
483+
self.assertTrue(regrtest.single_process)
484+
485+
args = ['--fast-ci', '--single-process']
486+
with support.captured_stderr():
487+
regrtest = self.create_regrtest(args)
488+
self.assertEqual(regrtest.num_workers, 0)
489+
self.assertTrue(regrtest.single_process)
490+
478491

479492
@dataclasses.dataclass(slots=True)
480493
class Rerun:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add ``--single-process`` command line option to Python test runner (regrtest).
2+
Patch by Victor Stinner.

0 commit comments

Comments
 (0)