]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-119727: Add --single-process option to regrtest (GH-119728) (#130359)
authorHugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Thu, 20 Feb 2025 15:47:10 +0000 (17:47 +0200)
committerGitHub <noreply@github.com>
Thu, 20 Feb 2025 15:47:10 +0000 (15:47 +0000)
Co-authored-by: Victor Stinner <vstinner@python.org>
Lib/test/libregrtest/cmdline.py
Lib/test/libregrtest/main.py
Lib/test/test_regrtest.py
Misc/NEWS.d/next/Tests/2024-05-29-15-28-08.gh-issue-119727.dVkaZM.rst [new file with mode: 0644]

index 3211d04bee0c349857023dd83a0eabb5e87cb05a..05b2e9fefc1f324b1052ff280ee5f5a0c83d25be 100644 (file)
@@ -174,6 +174,7 @@ class Namespace(argparse.Namespace):
         self.tempdir = None
         self._add_python_opts = True
         self.xmlpath = None
+        self.single_process = False
 
         super().__init__(**kwargs)
 
@@ -307,6 +308,12 @@ def _create_parser():
     group.add_argument('-j', '--multiprocess', metavar='PROCESSES',
                        dest='use_mp', type=int,
                        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',
                        dest='trace',
                        help='turn on code coverage tracing using the trace '
@@ -436,6 +443,10 @@ def _parse_args(args, **kwargs):
     else:
         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,
     # --slow-ci has the priority
     if ns.slow_ci:
index 04404cbcd524e162efe540a9d339d20e0b095f59..899ddf9d8d4b2f1006ca416d7884520bd2bfaba8 100644 (file)
@@ -87,12 +87,13 @@ class Regrtest:
         self.cmdline_args: TestList = ns.args
 
         # Workers
-        if ns.use_mp is None:
-            num_workers = 0  # run sequentially
+        self.single_process: bool = ns.single_process
+        if self.single_process or ns.use_mp is None:
+            num_workers = 0   # run sequentially in a single process
         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:
-            num_workers = ns.use_mp
+            num_workers = ns.use_mp  # run in parallel
         self.num_workers: int = num_workers
         self.worker_json: StrJSON | None = ns.worker_json
 
@@ -234,7 +235,7 @@ class Regrtest:
 
     def _rerun_failed_tests(self, runtests: RunTests):
         # 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
             # initial state. Don't re-run tests in parallel but limit to a
             # single worker process to have side effects (on the system load
@@ -244,7 +245,6 @@ class Regrtest:
         tests, match_tests_dict = self.results.prepare_rerun()
 
         # Re-run failed tests
-        self.log(f"Re-running {len(tests)} failed tests in verbose mode in subprocesses")
         runtests = runtests.copy(
             tests=tests,
             rerun=True,
@@ -254,7 +254,15 @@ class Regrtest:
             match_tests_dict=match_tests_dict,
             output_on_failure=False)
         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
 
     def rerun_failed_tests(self, runtests: RunTests):
@@ -367,7 +375,7 @@ class Regrtest:
             tests = count(jobs, 'test')
         else:
             tests = 'tests'
-        msg = f"Run {tests} sequentially"
+        msg = f"Run {tests} sequentially in a single process"
         if runtests.timeout:
             msg += " (timeout: %s)" % format_duration(runtests.timeout)
         self.log(msg)
@@ -589,7 +597,7 @@ class Regrtest:
             keep_environ = True
 
         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;
                 # hostrunner can be expensive.
                 regrtest_opts.extend(['-j', '2'])
index 75196ac040a87e4505b1887bce350fabf66d89e7..6c97f5e0d2188e59adec859e451119f3aee4973d 100644 (file)
@@ -466,6 +466,19 @@ class ParseArgsTestCase(unittest.TestCase):
         self.assertEqual(regrtest.hunt_refleak.runs, 10)
         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)
 class Rerun:
diff --git a/Misc/NEWS.d/next/Tests/2024-05-29-15-28-08.gh-issue-119727.dVkaZM.rst b/Misc/NEWS.d/next/Tests/2024-05-29-15-28-08.gh-issue-119727.dVkaZM.rst
new file mode 100644 (file)
index 0000000..bf28d8b
--- /dev/null
@@ -0,0 +1,2 @@
+Add ``--single-process`` command line option to Python test runner (regrtest).
+Patch by Victor Stinner.