[Python-checkins] bpo-33873: Backport regrtest from master to 3.7 (GH-7935) (GH-7937)

Victor Stinner webhook-mailer at python.org
Tue Jun 26 18:44:51 EDT 2018


https://github.com/python/cpython/commit/1d55888a78bcefed3723fb7e48df2a75b4f0adb0
commit: 1d55888a78bcefed3723fb7e48df2a75b4f0adb0
branch: 3.6
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2018-06-27T00:44:43+02:00
summary:

bpo-33873: Backport regrtest from master to 3.7 (GH-7935) (GH-7937)

* bpo-33718: regrtest: use format_duration() to display failed tests (GH-7686)

* Enhance also format_duration(): work on integers and rounds towards
  +infinity (math.ceil).
* Write unit tests on format_duration()

(cherry picked from commit 4ffe9c2b251f6e027b26250b7a2618e78d4edd22)

* bpo-33873: regrtest: Add warning on -R 1:3 (GH-7736)

regrtest: Add warning when using less than 3 warmup runs like -R 1:3.
(cherry picked from commit cac4fef8860e66a9da67d09762f5b614b9471a12)

* bpo-33873: Fix bug in `runtest.py` and add checks for invalid `-R` parameters (GH-7735)

Fix bug in `Lib/test/libregrtest/runtest.py` that makes running tests an extra time than the specified number of runs.

Add check for invalid --huntrleaks/-R parameters.

(cherry picked from commit 58ed7307ea0b5c5aa052291ebc3030f314f938d8)
(cherry picked from commit d1f9481b7a2d31c40fca1347ef99d819eb656ce7)

files:
A Misc/NEWS.d/next/Tests/2018-06-16-01-37-31.bpo-33873.d86vab.rst
M Lib/test/libregrtest/main.py
M Lib/test/libregrtest/runtest.py
M Lib/test/libregrtest/runtest_mp.py
M Lib/test/libregrtest/utils.py
M Lib/test/test_regrtest.py

diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py
index 3429b3726abe..e262a7a172b9 100644
--- a/Lib/test/libregrtest/main.py
+++ b/Lib/test/libregrtest/main.py
@@ -462,6 +462,13 @@ def run_tests(self):
                    or self.tests or self.ns.args)):
             self.display_header()
 
+        if self.ns.huntrleaks:
+            warmup, repetitions, _ = self.ns.huntrleaks
+            if warmup < 3:
+                msg = ("WARNING: Running tests with --huntrleaks/-R and less than "
+                        "3 warmup repetitions can give false positives!")
+                print(msg, file=sys.stdout, flush=True)
+
         if self.ns.randomize:
             print("Using random seed", self.ns.random_seed)
 
@@ -526,6 +533,15 @@ def main(self, tests=None, **kwargs):
     def _main(self, tests, kwargs):
         self.ns = self.parse_args(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.ns.slaveargs is not None:
             from test.libregrtest.runtest_mp import run_tests_slave
             run_tests_slave(self.ns.slaveargs)
diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py
index 12bf422c902d..3e1afd41997a 100644
--- a/Lib/test/libregrtest/runtest.py
+++ b/Lib/test/libregrtest/runtest.py
@@ -173,9 +173,10 @@ def test_runner():
                     if loader.errors:
                         raise Exception("errors while loading tests")
                     support.run_unittest(tests)
-            test_runner()
             if ns.huntrleaks:
                 refleak = dash_R(the_module, test, test_runner, ns.huntrleaks)
+            else:
+                test_runner()
             test_time = time.time() - start_time
         post_test_cleanup()
     except support.ResourceDenied as msg:
diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py
index 108b56d8d22f..fa9178a863e1 100644
--- a/Lib/test/libregrtest/runtest_mp.py
+++ b/Lib/test/libregrtest/runtest_mp.py
@@ -204,7 +204,7 @@ def get_running(workers):
             if (ok not in (CHILD_ERROR, INTERRUPTED)
                 and test_time >= PROGRESS_MIN_TIME
                 and not regrtest.ns.pgo):
-                text += ' (%.0f sec)' % test_time
+                text += ' (%s)' % format_duration(test_time)
             elif ok == CHILD_ERROR:
                 text = '%s (%s)' % (text, test_time)
             running = get_running(workers)
diff --git a/Lib/test/libregrtest/utils.py b/Lib/test/libregrtest/utils.py
index 85049cb06b36..d36bf9196626 100644
--- a/Lib/test/libregrtest/utils.py
+++ b/Lib/test/libregrtest/utils.py
@@ -1,19 +1,28 @@
 import os.path
+import math
 import textwrap
 
 
 def format_duration(seconds):
-    if seconds < 1.0:
-        return '%.0f ms' % (seconds * 1e3)
-    if seconds < 60.0:
-        return '%.0f sec' % seconds
+    ms = math.ceil(seconds * 1e3)
+    seconds, ms = divmod(ms, 1000)
+    minutes, seconds = divmod(seconds, 60)
+    hours, minutes = divmod(minutes, 60)
 
-    minutes, seconds = divmod(seconds, 60.0)
-    hours, minutes = divmod(minutes, 60.0)
+    parts = []
     if hours:
-        return '%.0f hour %.0f min' % (hours, minutes)
-    else:
-        return '%.0f min %.0f sec' % (minutes, seconds)
+        parts.append('%s hour' % hours)
+    if minutes:
+        parts.append('%s min' % minutes)
+    if seconds:
+        parts.append('%s sec' % seconds)
+    if ms:
+        parts.append('%s ms' % ms)
+    if not parts:
+        return '0 ms'
+
+    parts = parts[:2]
+    return ' '.join(parts)
 
 
 def removepy(names):
diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py
index e2b52283cd11..0b590ad8f188 100644
--- a/Lib/test/test_regrtest.py
+++ b/Lib/test/test_regrtest.py
@@ -18,6 +18,7 @@
 import unittest
 from test import libregrtest
 from test import support
+from test.libregrtest import utils
 
 
 Py_DEBUG = hasattr(sys, 'getobjects')
@@ -984,5 +985,29 @@ def test_bug(self):
                                   failed=testname, rerun=testname)
 
 
+class TestUtils(unittest.TestCase):
+    def test_format_duration(self):
+        self.assertEqual(utils.format_duration(0),
+                         '0 ms')
+        self.assertEqual(utils.format_duration(1e-9),
+                         '1 ms')
+        self.assertEqual(utils.format_duration(10e-3),
+                         '10 ms')
+        self.assertEqual(utils.format_duration(1.5),
+                         '1 sec 500 ms')
+        self.assertEqual(utils.format_duration(1),
+                         '1 sec')
+        self.assertEqual(utils.format_duration(2 * 60),
+                         '2 min')
+        self.assertEqual(utils.format_duration(2 * 60 + 1),
+                         '2 min 1 sec')
+        self.assertEqual(utils.format_duration(3 * 3600),
+                         '3 hour')
+        self.assertEqual(utils.format_duration(3 * 3600  + 2 * 60 + 1),
+                         '3 hour 2 min')
+        self.assertEqual(utils.format_duration(3 * 3600 + 1),
+                         '3 hour 1 sec')
+
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/Misc/NEWS.d/next/Tests/2018-06-16-01-37-31.bpo-33873.d86vab.rst b/Misc/NEWS.d/next/Tests/2018-06-16-01-37-31.bpo-33873.d86vab.rst
new file mode 100644
index 000000000000..f4f425570267
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2018-06-16-01-37-31.bpo-33873.d86vab.rst
@@ -0,0 +1,4 @@
+Fix a bug in ``regrtest`` that caused an extra test to run if
+--huntrleaks/-R was used. Exit with error in case that invalid
+parameters are specified to --huntrleaks/-R (at least one warmup
+run and one repetition must be used).



More information about the Python-checkins mailing list