From 47fbc4e45b35b3111e2d947a66490a43ac21d363 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 24 Jun 2019 12:03:00 +0200 Subject: [PATCH] bpo-37359: Add --cleanup option to python3 -m test (GH-14332) * regrtest: Add --cleanup option to remove "test_python_*" directories of previous failed test jobs. * Add "make cleantest" to run "python3 -m test --cleanup". --- Lib/test/libregrtest/cmdline.py | 4 +- Lib/test/libregrtest/main.py | 51 ++++++++++++++----- Lib/test/test_regrtest.py | 15 ++++++ Makefile.pre.in | 5 ++ .../2019-06-24-10-47-07.bpo-37359.CkdtyO.rst | 4 ++ 5 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-06-24-10-47-07.bpo-37359.CkdtyO.rst diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py index dc0d8807194..9f1bf680082 100644 --- a/Lib/test/libregrtest/cmdline.py +++ b/Lib/test/libregrtest/cmdline.py @@ -272,8 +272,10 @@ def _create_parser(): group.add_argument('--junit-xml', dest='xmlpath', metavar='FILENAME', help='writes JUnit-style XML results to the specified ' 'file') - group.add_argument('--tempdir', dest='tempdir', metavar='PATH', + group.add_argument('--tempdir', metavar='PATH', help='override the working directory for the test run') + group.add_argument('--cleanup', action='store_true', + help='remove old test_python_* directories') return parser diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index a9b2b352d12..98b4420f590 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -173,7 +173,19 @@ class Regrtest: # Strip .py extensions. removepy(ns.args) - return ns + if ns.huntrleaks: + warmup, repetitions, _ = ns.huntrleaks + if warmup < 1 or repetitions < 1: + msg = ("Invalid values for the --huntrleaks/-R parameters. The " + "number of warmups and repetitions must be at least 1 " + "each (1:1).") + print(msg, file=sys.stderr, flush=True) + sys.exit(2) + + if ns.tempdir: + ns.tempdir = os.path.expanduser(ns.tempdir) + + self.ns = ns def find_tests(self, tests): self.tests = tests @@ -537,7 +549,7 @@ class Regrtest: for s in ET.tostringlist(root): f.write(s) - def create_temp_dir(self): + def set_temp_dir(self): if self.ns.tempdir: self.tmp_dir = self.ns.tempdir @@ -558,6 +570,8 @@ class Regrtest: self.tmp_dir = tempfile.gettempdir() self.tmp_dir = os.path.abspath(self.tmp_dir) + + def create_temp_dir(self): os.makedirs(self.tmp_dir, exist_ok=True) # Define a writable temp dir that will be used as cwd while running @@ -565,14 +579,34 @@ class Regrtest: # testing (see the -j option). pid = os.getpid() if self.worker_test_name is not None: - test_cwd = 'worker_{}'.format(pid) + test_cwd = 'test_python_worker_{}'.format(pid) else: test_cwd = 'test_python_{}'.format(pid) test_cwd = os.path.join(self.tmp_dir, test_cwd) return test_cwd + def cleanup(self): + import glob + import shutil + + path = os.path.join(self.tmp_dir, 'test_python_*') + print("Cleanup %s directory" % self.tmp_dir) + for name in glob.glob(path): + print("Remove directory: %s" % name) + if os.path.isdir(name): + support.rmtree(name) + else: + print("Remove file: %s" % name) + support.unlink(name) + def main(self, tests=None, **kwargs): - self.ns = self.parse_args(kwargs) + self.parse_args(kwargs) + + self.set_temp_dir() + + if self.ns.cleanup: + self.cleanup() + sys.exit(0) test_cwd = self.create_temp_dir() @@ -597,15 +631,6 @@ class Regrtest: return None def _main(self, tests, kwargs): - if self.ns.huntrleaks: - warmup, repetitions, _ = self.ns.huntrleaks - if warmup < 1 or repetitions < 1: - msg = ("Invalid values for the --huntrleaks/-R parameters. The " - "number of warmups and repetitions must be at least 1 " - "each (1:1).") - print(msg, file=sys.stderr, flush=True) - sys.exit(2) - if self.worker_test_name is not None: from test.libregrtest.runtest_mp import run_tests_worker run_tests_worker(self.ns, self.worker_test_name) diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 0a009255cb9..2e5df00dc51 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -1156,6 +1156,21 @@ class ArgsTestCase(BaseTestCase): fail_env_changed=True) self.assertIn("Warning -- Unraisable exception", output) + def test_cleanup(self): + dirname = os.path.join(self.tmptestdir, "test_python_123") + os.mkdir(dirname) + filename = os.path.join(self.tmptestdir, "test_python_456") + open(filename, "wb").close() + names = [dirname, filename] + + cmdargs = ['-m', 'test', + '--tempdir=%s' % self.tmptestdir, + '--cleanup'] + self.run_python(cmdargs) + + for name in names: + self.assertFalse(os.path.exists(name), name) + class TestUtils(unittest.TestCase): def test_format_duration(self): diff --git a/Makefile.pre.in b/Makefile.pre.in index f6293364c0d..ef9a4f88598 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1104,6 +1104,11 @@ TESTTIMEOUT= 1200 .PHONY: test testall testuniversal buildbottest pythoninfo +# Remove "test_python_*" directories of previous failed test jobs. +# Pass TESTOPTS options because it can contain --tempdir option. +cleantest: build_all + $(TESTRUNNER) $(TESTOPTS) --cleanup + # Run a basic set of regression tests. # This excludes some tests that are particularly resource-intensive. test: @DEF_MAKE_RULE@ platform diff --git a/Misc/NEWS.d/next/Tests/2019-06-24-10-47-07.bpo-37359.CkdtyO.rst b/Misc/NEWS.d/next/Tests/2019-06-24-10-47-07.bpo-37359.CkdtyO.rst new file mode 100644 index 00000000000..3d5350de4f4 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-06-24-10-47-07.bpo-37359.CkdtyO.rst @@ -0,0 +1,4 @@ +Add --cleanup option to python3 -m test to remove ``test_python_*`` +directories of previous failed jobs. Add "make cleantest" to run +``python3 -m test --cleanup``. +