summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2024-06-03 16:34:36 (GMT)
committerGitHub <noreply@github.com>2024-06-03 16:34:36 (GMT)
commit4e8aa32245e2d72bf558b711ccdbcee594347615 (patch)
tree1b68abdc6ad2a62445b54525290fbf3002c5b9e2
parent1d4c2e4a877a48cdc8bcc9808d799b91c82b3757 (diff)
downloadcpython-4e8aa32245e2d72bf558b711ccdbcee594347615.zip
cpython-4e8aa32245e2d72bf558b711ccdbcee594347615.tar.gz
cpython-4e8aa32245e2d72bf558b711ccdbcee594347615.tar.bz2
gh-119727: Add --single-process option to regrtest (#119728)
-rw-r--r--Lib/test/libregrtest/cmdline.py11
-rw-r--r--Lib/test/libregrtest/main.py26
-rw-r--r--Lib/test/libregrtest/worker.py6
-rw-r--r--Lib/test/test_regrtest.py13
-rw-r--r--Misc/NEWS.d/next/Tests/2024-05-29-15-28-08.gh-issue-119727.dVkaZM.rst2
5 files changed, 46 insertions, 12 deletions
diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py
index d4dac77..2ff4715 100644
--- a/Lib/test/libregrtest/cmdline.py
+++ b/Lib/test/libregrtest/cmdline.py
@@ -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 '
@@ -435,6 +442,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:
diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py
index 9e7a7d6..5148d30 100644
--- a/Lib/test/libregrtest/main.py
+++ b/Lib/test/libregrtest/main.py
@@ -89,12 +89,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
@@ -236,7 +237,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
@@ -246,7 +247,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,
@@ -256,7 +256,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):
@@ -371,7 +379,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)
@@ -599,7 +607,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'])
diff --git a/Lib/test/libregrtest/worker.py b/Lib/test/libregrtest/worker.py
index 15d32b5..86cc308 100644
--- a/Lib/test/libregrtest/worker.py
+++ b/Lib/test/libregrtest/worker.py
@@ -14,9 +14,9 @@ from .utils import (
USE_PROCESS_GROUP = (hasattr(os, "setsid") and hasattr(os, "killpg"))
-NEED_TTY = set('''
- test_ioctl
-'''.split())
+NEED_TTY = {
+ 'test_ioctl',
+}
def create_worker_process(runtests: WorkerRunTests, output_fd: int,
diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py
index 17eff61..97ce797 100644
--- a/Lib/test/test_regrtest.py
+++ b/Lib/test/test_regrtest.py
@@ -473,6 +473,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
index 0000000..bf28d8b
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2024-05-29-15-28-08.gh-issue-119727.dVkaZM.rst
@@ -0,0 +1,2 @@
+Add ``--single-process`` command line option to Python test runner (regrtest).
+Patch by Victor Stinner.