Merge from 3.5 for issue #25188.
This commit is contained in:
commit
11faa21843
|
@ -236,6 +236,8 @@ def _create_parser():
|
||||||
group.add_argument('--list-tests', action='store_true',
|
group.add_argument('--list-tests', action='store_true',
|
||||||
help="only write the name of tests that will be run, "
|
help="only write the name of tests that will be run, "
|
||||||
"don't execute them")
|
"don't execute them")
|
||||||
|
group.add_argument('-P', '--pgo', dest='pgo', action='store_true',
|
||||||
|
help='enable Profile Guided Optimization training')
|
||||||
|
|
||||||
parser.add_argument('args', nargs=argparse.REMAINDER,
|
parser.add_argument('args', nargs=argparse.REMAINDER,
|
||||||
help=argparse.SUPPRESS)
|
help=argparse.SUPPRESS)
|
||||||
|
@ -279,7 +281,7 @@ def _parse_args(args, **kwargs):
|
||||||
findleaks=False, use_resources=None, trace=False, coverdir='coverage',
|
findleaks=False, use_resources=None, trace=False, coverdir='coverage',
|
||||||
runleaks=False, huntrleaks=False, verbose2=False, print_slow=False,
|
runleaks=False, huntrleaks=False, verbose2=False, print_slow=False,
|
||||||
random_seed=None, use_mp=None, verbose3=False, forever=False,
|
random_seed=None, use_mp=None, verbose3=False, forever=False,
|
||||||
header=False, failfast=False, match_tests=None)
|
header=False, failfast=False, match_tests=None, pgo=False)
|
||||||
for k, v in kwargs.items():
|
for k, v in kwargs.items():
|
||||||
if not hasattr(ns, k):
|
if not hasattr(ns, k):
|
||||||
raise TypeError('%r is an invalid keyword argument '
|
raise TypeError('%r is an invalid keyword argument '
|
||||||
|
@ -299,6 +301,8 @@ def _parse_args(args, **kwargs):
|
||||||
parser.error("-l and -j don't go together!")
|
parser.error("-l and -j don't go together!")
|
||||||
if ns.failfast and not (ns.verbose or ns.verbose3):
|
if ns.failfast and not (ns.verbose or ns.verbose3):
|
||||||
parser.error("-G/--failfast needs either -v or -W")
|
parser.error("-G/--failfast needs either -v or -W")
|
||||||
|
if ns.pgo and (ns.verbose or ns.verbose2 or ns.verbose3):
|
||||||
|
parser.error("--pgo/-v don't go together!")
|
||||||
|
|
||||||
if ns.quiet:
|
if ns.quiet:
|
||||||
ns.verbose = 0
|
ns.verbose = 0
|
||||||
|
|
|
@ -103,7 +103,10 @@ class Regrtest:
|
||||||
def display_progress(self, test_index, test):
|
def display_progress(self, test_index, test):
|
||||||
if self.ns.quiet:
|
if self.ns.quiet:
|
||||||
return
|
return
|
||||||
fmt = "[{1:{0}}{2}/{3}] {4}" if self.bad else "[{1:{0}}{2}] {4}"
|
if self.bad and not self.ns.pgo:
|
||||||
|
fmt = "[{1:{0}}{2}/{3}] {4}"
|
||||||
|
else:
|
||||||
|
fmt = "[{1:{0}}{2}] {4}"
|
||||||
print(fmt.format(self.test_count_width, test_index,
|
print(fmt.format(self.test_count_width, test_index,
|
||||||
self.test_count, len(self.bad), test),
|
self.test_count, len(self.bad), test),
|
||||||
flush=True)
|
flush=True)
|
||||||
|
@ -238,6 +241,11 @@ class Regrtest:
|
||||||
print(count(len(omitted), "test"), "omitted:")
|
print(count(len(omitted), "test"), "omitted:")
|
||||||
printlist(omitted)
|
printlist(omitted)
|
||||||
|
|
||||||
|
# If running the test suite for PGO then no one cares about
|
||||||
|
# results.
|
||||||
|
if self.ns.pgo:
|
||||||
|
return
|
||||||
|
|
||||||
if self.good and not self.ns.quiet:
|
if self.good and not self.ns.quiet:
|
||||||
if (not self.bad
|
if (not self.bad
|
||||||
and not self.skipped
|
and not self.skipped
|
||||||
|
@ -314,7 +322,7 @@ class Regrtest:
|
||||||
# For a partial run, we do not need to clutter the output.
|
# For a partial run, we do not need to clutter the output.
|
||||||
if (self.ns.verbose
|
if (self.ns.verbose
|
||||||
or self.ns.header
|
or self.ns.header
|
||||||
or not (self.ns.quiet or self.ns.single
|
or not (self.ns.pgo or self.ns.quiet or self.ns.single
|
||||||
or self.tests or self.ns.args)):
|
or self.tests or self.ns.args)):
|
||||||
# Print basic platform information
|
# Print basic platform information
|
||||||
print("==", platform.python_implementation(), *sys.version.split())
|
print("==", platform.python_implementation(), *sys.version.split())
|
||||||
|
|
|
@ -65,6 +65,7 @@ def runtest(ns, test):
|
||||||
timeout -- dump the traceback and exit if a test takes more than
|
timeout -- dump the traceback and exit if a test takes more than
|
||||||
timeout seconds
|
timeout seconds
|
||||||
failfast, match_tests -- See regrtest command-line flags for these.
|
failfast, match_tests -- See regrtest command-line flags for these.
|
||||||
|
pgo -- if true, suppress any info irrelevant to a generating a PGO build
|
||||||
|
|
||||||
Returns the tuple result, test_time, where result is one of the constants:
|
Returns the tuple result, test_time, where result is one of the constants:
|
||||||
INTERRUPTED KeyboardInterrupt when run under -j
|
INTERRUPTED KeyboardInterrupt when run under -j
|
||||||
|
@ -82,6 +83,7 @@ def runtest(ns, test):
|
||||||
failfast = ns.failfast
|
failfast = ns.failfast
|
||||||
match_tests = ns.match_tests
|
match_tests = ns.match_tests
|
||||||
timeout = ns.timeout
|
timeout = ns.timeout
|
||||||
|
pgo = ns.pgo
|
||||||
|
|
||||||
use_timeout = (timeout is not None)
|
use_timeout = (timeout is not None)
|
||||||
if use_timeout:
|
if use_timeout:
|
||||||
|
@ -110,7 +112,7 @@ def runtest(ns, test):
|
||||||
sys.stdout = stream
|
sys.stdout = stream
|
||||||
sys.stderr = stream
|
sys.stderr = stream
|
||||||
result = runtest_inner(test, verbose, quiet, huntrleaks,
|
result = runtest_inner(test, verbose, quiet, huntrleaks,
|
||||||
display_failure=False)
|
display_failure=False, pgo=pgo)
|
||||||
if result[0] == FAILED:
|
if result[0] == FAILED:
|
||||||
output = stream.getvalue()
|
output = stream.getvalue()
|
||||||
orig_stderr.write(output)
|
orig_stderr.write(output)
|
||||||
|
@ -121,7 +123,7 @@ def runtest(ns, test):
|
||||||
else:
|
else:
|
||||||
support.verbose = verbose # Tell tests to be moderately quiet
|
support.verbose = verbose # Tell tests to be moderately quiet
|
||||||
result = runtest_inner(test, verbose, quiet, huntrleaks,
|
result = runtest_inner(test, verbose, quiet, huntrleaks,
|
||||||
display_failure=not verbose)
|
display_failure=not verbose, pgo=pgo)
|
||||||
return result
|
return result
|
||||||
finally:
|
finally:
|
||||||
if use_timeout:
|
if use_timeout:
|
||||||
|
@ -131,7 +133,7 @@ runtest.stringio = None
|
||||||
|
|
||||||
|
|
||||||
def runtest_inner(test, verbose, quiet,
|
def runtest_inner(test, verbose, quiet,
|
||||||
huntrleaks=False, display_failure=True):
|
huntrleaks=False, display_failure=True, *, pgo=False):
|
||||||
support.unload(test)
|
support.unload(test)
|
||||||
|
|
||||||
test_time = 0.0
|
test_time = 0.0
|
||||||
|
@ -142,7 +144,7 @@ def runtest_inner(test, verbose, quiet,
|
||||||
else:
|
else:
|
||||||
# Always import it from the test package
|
# Always import it from the test package
|
||||||
abstest = 'test.' + test
|
abstest = 'test.' + test
|
||||||
with saved_test_environment(test, verbose, quiet) as environment:
|
with saved_test_environment(test, verbose, quiet, pgo=pgo) as environment:
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
the_module = importlib.import_module(abstest)
|
the_module = importlib.import_module(abstest)
|
||||||
# If the test has a test_main, that will run the appropriate
|
# If the test has a test_main, that will run the appropriate
|
||||||
|
@ -162,24 +164,28 @@ def runtest_inner(test, verbose, quiet,
|
||||||
refleak = dash_R(the_module, test, test_runner, huntrleaks)
|
refleak = dash_R(the_module, test, test_runner, huntrleaks)
|
||||||
test_time = time.time() - start_time
|
test_time = time.time() - start_time
|
||||||
except support.ResourceDenied as msg:
|
except support.ResourceDenied as msg:
|
||||||
if not quiet:
|
if not quiet and not pgo:
|
||||||
print(test, "skipped --", msg, flush=True)
|
print(test, "skipped --", msg, flush=True)
|
||||||
return RESOURCE_DENIED, test_time
|
return RESOURCE_DENIED, test_time
|
||||||
except unittest.SkipTest as msg:
|
except unittest.SkipTest as msg:
|
||||||
if not quiet:
|
if not quiet and not pgo:
|
||||||
print(test, "skipped --", msg, flush=True)
|
print(test, "skipped --", msg, flush=True)
|
||||||
return SKIPPED, test_time
|
return SKIPPED, test_time
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise
|
raise
|
||||||
except support.TestFailed as msg:
|
except support.TestFailed as msg:
|
||||||
if display_failure:
|
if not pgo:
|
||||||
print("test", test, "failed --", msg, file=sys.stderr, flush=True)
|
if display_failure:
|
||||||
else:
|
print("test", test, "failed --", msg, file=sys.stderr,
|
||||||
print("test", test, "failed", file=sys.stderr, flush=True)
|
flush=True)
|
||||||
|
else:
|
||||||
|
print("test", test, "failed", file=sys.stderr, flush=True)
|
||||||
return FAILED, test_time
|
return FAILED, test_time
|
||||||
except:
|
except:
|
||||||
msg = traceback.format_exc()
|
msg = traceback.format_exc()
|
||||||
print("test", test, "crashed --", msg, file=sys.stderr, flush=True)
|
if not pgo:
|
||||||
|
print("test", test, "crashed --", msg, file=sys.stderr,
|
||||||
|
flush=True)
|
||||||
return FAILED, test_time
|
return FAILED, test_time
|
||||||
else:
|
else:
|
||||||
if refleak:
|
if refleak:
|
||||||
|
|
|
@ -42,6 +42,8 @@ def run_test_in_subprocess(testname, ns):
|
||||||
'-X', 'faulthandler',
|
'-X', 'faulthandler',
|
||||||
'-m', 'test.regrtest',
|
'-m', 'test.regrtest',
|
||||||
'--slaveargs', slaveargs]
|
'--slaveargs', slaveargs]
|
||||||
|
if ns.pgo:
|
||||||
|
cmd += ['--pgo']
|
||||||
|
|
||||||
# Running the child from the same working directory as regrtest's original
|
# Running the child from the same working directory as regrtest's original
|
||||||
# invocation ensures that TEMPDIR for the child is the same when
|
# invocation ensures that TEMPDIR for the child is the same when
|
||||||
|
@ -175,7 +177,7 @@ def run_tests_multiprocess(regrtest):
|
||||||
item = output.get(timeout=timeout)
|
item = output.get(timeout=timeout)
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
running = get_running(workers)
|
running = get_running(workers)
|
||||||
if running:
|
if running and not regrtest.ns.pgo:
|
||||||
print('running: %s' % ', '.join(running))
|
print('running: %s' % ', '.join(running))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -189,17 +191,18 @@ def run_tests_multiprocess(regrtest):
|
||||||
text = test
|
text = test
|
||||||
ok, test_time = result
|
ok, test_time = result
|
||||||
if (ok not in (CHILD_ERROR, INTERRUPTED)
|
if (ok not in (CHILD_ERROR, INTERRUPTED)
|
||||||
and test_time >= PROGRESS_MIN_TIME):
|
and test_time >= PROGRESS_MIN_TIME
|
||||||
|
and not regrtest.ns.pgo):
|
||||||
text += ' (%.0f sec)' % test_time
|
text += ' (%.0f sec)' % test_time
|
||||||
running = get_running(workers)
|
running = get_running(workers)
|
||||||
if running:
|
if running and not regrtest.ns.pgo:
|
||||||
text += ' -- running: %s' % ', '.join(running)
|
text += ' -- running: %s' % ', '.join(running)
|
||||||
regrtest.display_progress(test_index, text)
|
regrtest.display_progress(test_index, text)
|
||||||
|
|
||||||
# Copy stdout and stderr from the child process
|
# Copy stdout and stderr from the child process
|
||||||
if stdout:
|
if stdout:
|
||||||
print(stdout, flush=True)
|
print(stdout, flush=True)
|
||||||
if stderr:
|
if stderr and not regrtest.ns.pgo:
|
||||||
print(stderr, file=sys.stderr, flush=True)
|
print(stderr, file=sys.stderr, flush=True)
|
||||||
|
|
||||||
if result[0] == INTERRUPTED:
|
if result[0] == INTERRUPTED:
|
||||||
|
|
|
@ -41,10 +41,11 @@ class saved_test_environment:
|
||||||
|
|
||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
def __init__(self, testname, verbose=0, quiet=False):
|
def __init__(self, testname, verbose=0, quiet=False, *, pgo=False):
|
||||||
self.testname = testname
|
self.testname = testname
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
self.quiet = quiet
|
self.quiet = quiet
|
||||||
|
self.pgo = pgo
|
||||||
|
|
||||||
# To add things to save and restore, add a name XXX to the resources list
|
# To add things to save and restore, add a name XXX to the resources list
|
||||||
# and add corresponding get_XXX/restore_XXX functions. get_XXX should
|
# and add corresponding get_XXX/restore_XXX functions. get_XXX should
|
||||||
|
@ -273,7 +274,7 @@ class saved_test_environment:
|
||||||
if current != original:
|
if current != original:
|
||||||
self.changed = True
|
self.changed = True
|
||||||
restore(original)
|
restore(original)
|
||||||
if not self.quiet:
|
if not self.quiet and not self.pgo:
|
||||||
print("Warning -- {} was modified by {}".format(
|
print("Warning -- {} was modified by {}".format(
|
||||||
name, self.testname),
|
name, self.testname),
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
|
|
|
@ -231,7 +231,7 @@ TCLTK_INCLUDES= @TCLTK_INCLUDES@
|
||||||
TCLTK_LIBS= @TCLTK_LIBS@
|
TCLTK_LIBS= @TCLTK_LIBS@
|
||||||
|
|
||||||
# The task to run while instrument when building the profile-opt target
|
# The task to run while instrument when building the profile-opt target
|
||||||
PROFILE_TASK=-m test.regrtest >/dev/null 2>&1
|
PROFILE_TASK=-m test.regrtest --pgo
|
||||||
|
|
||||||
# report files for gcov / lcov coverage report
|
# report files for gcov / lcov coverage report
|
||||||
COVERAGE_INFO= $(abs_builddir)/coverage.info
|
COVERAGE_INFO= $(abs_builddir)/coverage.info
|
||||||
|
|
|
@ -170,6 +170,10 @@ Documentation
|
||||||
Tests
|
Tests
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- Issue #25188: Add -P/--pgo to test.regrtest to suppress error output when
|
||||||
|
running the test suite for the purposes of a PGO build. Initial patch by
|
||||||
|
Alecsandru Patrascu.
|
||||||
|
|
||||||
- Issue #22806: Add ``python -m test --list-tests`` command to list tests.
|
- Issue #22806: Add ``python -m test --list-tests`` command to list tests.
|
||||||
|
|
||||||
- Issue #18174: ``python -m test --huntrleaks ...`` now also checks for leak of
|
- Issue #18174: ``python -m test --huntrleaks ...`` now also checks for leak of
|
||||||
|
|
Loading…
Reference in New Issue