Merge from 3.5 for issue #25188.

This commit is contained in:
Brett Cannon 2015-10-02 16:20:49 -07:00
commit 11faa21843
7 changed files with 47 additions and 21 deletions

View File

@ -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

View File

@ -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())

View File

@ -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:

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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