Skip to content

Commit 5430c14

Browse files
authored
[2.7] bpo-33873: Backport regrtest from master (GH-7936)
* 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 4ffe9c2) * 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 cac4fef) * 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 58ed730)
1 parent 16137fe commit 5430c14

File tree

3 files changed

+73
-18
lines changed

3 files changed

+73
-18
lines changed

Lib/test/regrtest.py

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -174,20 +174,21 @@
174174
import StringIO
175175
import datetime
176176
import getopt
177+
import imp
177178
import json
179+
import math
178180
import os
181+
import platform
179182
import random
180183
import re
181184
import shutil
182185
import sys
186+
import sysconfig
187+
import tempfile
183188
import time
184189
import traceback
185-
import warnings
186190
import unittest
187-
import tempfile
188-
import imp
189-
import platform
190-
import sysconfig
191+
import warnings
191192

192193

193194
# Some times __path__ and __file__ are not absolute (e.g. while running from
@@ -270,17 +271,25 @@ def usage(code, msg=''):
270271

271272

272273
def format_duration(seconds):
273-
if seconds < 1.0:
274-
return '%.0f ms' % (seconds * 1e3)
275-
if seconds < 60.0:
276-
return '%.0f sec' % seconds
274+
ms = int(math.ceil(seconds * 1e3))
275+
seconds, ms = divmod(ms, 1000)
276+
minutes, seconds = divmod(seconds, 60)
277+
hours, minutes = divmod(minutes, 60)
277278

278-
minutes, seconds = divmod(seconds, 60.0)
279-
hours, minutes = divmod(minutes, 60.0)
279+
parts = []
280280
if hours:
281-
return '%.0f hour %.0f min' % (hours, minutes)
282-
else:
283-
return '%.0f min %.0f sec' % (minutes, seconds)
281+
parts.append('%s hour' % hours)
282+
if minutes:
283+
parts.append('%s min' % minutes)
284+
if seconds:
285+
parts.append('%s sec' % seconds)
286+
if ms:
287+
parts.append('%s ms' % ms)
288+
if not parts:
289+
return '0 ms'
290+
291+
parts = parts[:2]
292+
return ' '.join(parts)
284293

285294

286295
_FORMAT_TEST_RESULT = {
@@ -507,6 +516,15 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
507516
except ValueError:
508517
pass
509518

519+
if huntrleaks:
520+
warmup, repetitions, _ = huntrleaks
521+
if warmup < 1 or repetitions < 1:
522+
msg = ("Invalid values for the --huntrleaks/-R parameters. The "
523+
"number of warmups and repetitions must be at least 1 "
524+
"each (1:1).")
525+
print >>sys.stderr, msg
526+
sys.exit(2)
527+
510528
if slaveargs is not None:
511529
args, kwargs = json.loads(slaveargs)
512530
if kwargs['huntrleaks']:
@@ -682,6 +700,12 @@ def display_progress(test_index, test):
682700
if ncpu:
683701
print "== CPU count:", ncpu
684702

703+
if huntrleaks:
704+
warmup, repetitions, _ = huntrleaks
705+
if warmup < 3:
706+
print("WARNING: Running tests with --huntrleaks/-R and less than "
707+
"3 warmup repetitions can give false positives!")
708+
685709
if randomize:
686710
random.seed(random_seed)
687711
print "Using random seed", random_seed
@@ -809,7 +833,7 @@ def get_running(workers):
809833
if (ok not in (CHILD_ERROR, INTERRUPTED)
810834
and test_time >= PROGRESS_MIN_TIME
811835
and not pgo):
812-
text += ' (%.0f sec)' % test_time
836+
text += ' (%s)' % format_duration(test_time)
813837
running = get_running(workers)
814838
if running and not pgo:
815839
text += ' -- running: %s' % ', '.join(running)
@@ -1293,11 +1317,12 @@ def runtest_inner(test, verbose, quiet, huntrleaks=False, pgo=False, testdir=Non
12931317
# being imported. For tests based on unittest or doctest,
12941318
# explicitly invoke their test_main() function (if it exists).
12951319
indirect_test = getattr(the_module, "test_main", None)
1296-
if indirect_test is not None:
1297-
indirect_test()
12981320
if huntrleaks:
12991321
refleak = dash_R(the_module, test, indirect_test,
13001322
huntrleaks)
1323+
else:
1324+
if indirect_test is not None:
1325+
indirect_test()
13011326
test_time = time.time() - start_time
13021327
post_test_cleanup()
13031328
finally:

Lib/test/test_regrtest.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import textwrap
1818
import unittest
1919
from test import support
20+
# Use utils alias to use the same code for TestUtils in master and 2.7 branches
21+
import regrtest as utils
2022

2123

2224
Py_DEBUG = hasattr(sys, 'getobjects')
@@ -683,8 +685,32 @@ def test_main():
683685
failed=testname, rerun=testname)
684686

685687

688+
class TestUtils(unittest.TestCase):
689+
def test_format_duration(self):
690+
self.assertEqual(utils.format_duration(0),
691+
'0 ms')
692+
self.assertEqual(utils.format_duration(1e-9),
693+
'1 ms')
694+
self.assertEqual(utils.format_duration(10e-3),
695+
'10 ms')
696+
self.assertEqual(utils.format_duration(1.5),
697+
'1 sec 500 ms')
698+
self.assertEqual(utils.format_duration(1),
699+
'1 sec')
700+
self.assertEqual(utils.format_duration(2 * 60),
701+
'2 min')
702+
self.assertEqual(utils.format_duration(2 * 60 + 1),
703+
'2 min 1 sec')
704+
self.assertEqual(utils.format_duration(3 * 3600),
705+
'3 hour')
706+
self.assertEqual(utils.format_duration(3 * 3600 + 2 * 60 + 1),
707+
'3 hour 2 min')
708+
self.assertEqual(utils.format_duration(3 * 3600 + 1),
709+
'3 hour 1 sec')
710+
711+
686712
def test_main():
687-
support.run_unittest(ProgramsTestCase, ArgsTestCase)
713+
support.run_unittest(ProgramsTestCase, ArgsTestCase, TestUtils)
688714

689715

690716
if __name__ == "__main__":
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix a bug in ``regrtest`` that caused an extra test to run if
2+
--huntrleaks/-R was used. Exit with error in case that invalid
3+
parameters are specified to --huntrleaks/-R (at least one warmup
4+
run and one repetition must be used).

0 commit comments

Comments
 (0)