Issue #7151: regrtest would generate a JSON failure if there was output

to stderr during the test run and it happened to get emitted after the
worker thread emitted the result JSON.  Now we capture stdout and stderr
separately, which avoids that problem.  It also means that _all_ stderr
output is after all stdout output when we print the test results, but
that seems acceptable, since output ordering is not guaranteed anyway.
The patch also moves the emit of the test name into the output block
generated after the test completes.  Otherwise test names and test
output/errors were mixed in the terminal display, making it difficult
to determine which test generated the output.
This commit is contained in:
R. David Murray 2009-10-18 21:12:37 +00:00
parent 603acf99d0
commit 282396f27a
2 changed files with 19 additions and 13 deletions

View file

@ -426,35 +426,38 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
try: try:
test, args_tuple = pending.popleft() test, args_tuple = pending.popleft()
except IndexError: except IndexError:
output.put((None, None, None)) output.put((None, None, None, None))
return return
if not quiet:
print test
sys.stdout.flush()
# -E is needed by some tests, e.g. test_import # -E is needed by some tests, e.g. test_import
popen = Popen([sys.executable, '-E', '-m', 'test.regrtest', popen = Popen([sys.executable, '-E', '-m', 'test.regrtest',
'--slaveargs', json.dumps(args_tuple)], '--slaveargs', json.dumps(args_tuple)],
stdout=PIPE, stderr=STDOUT, stdout=PIPE, stderr=PIPE,
universal_newlines=True, close_fds=True) universal_newlines=True, close_fds=True)
out = popen.communicate()[0].strip() stdout, stderr = popen.communicate()
out = debug_output_pat.sub("", out) # Strip last refcount output line if it exists, since it
out, _, result = out.strip().rpartition("\n") # comes from the shutdown of the interpreter in the subcommand.
stderr = debug_output_pat.sub("", stderr)
stdout, _, result = stdout.strip().rpartition("\n")
result = json.loads(result) result = json.loads(result)
output.put((test, out.strip(), result)) if not quiet:
stdout = test+'\n'+stdout
output.put((test, stdout.rstrip(), stderr.rstrip(), result))
except BaseException: except BaseException:
output.put((None, None, None)) output.put((None, None, None, None))
raise raise
workers = [Thread(target=work) for i in range(use_mp)] workers = [Thread(target=work) for i in range(use_mp)]
for worker in workers: for worker in workers:
worker.start() worker.start()
finished = 0 finished = 0
while finished < use_mp: while finished < use_mp:
test, out, result = output.get() test, stdout, stderr, result = output.get()
if test is None: if test is None:
finished += 1 finished += 1
continue continue
if out: if stdout:
print out print stdout
if stderr:
print >>sys.stderr, stderr
if result[0] == -4: if result[0] == -4:
assert result[1] == 'KeyboardInterrupt' assert result[1] == 'KeyboardInterrupt'
pending.clear() pending.clear()

View file

@ -1473,6 +1473,9 @@ Extension Modules
Tests Tests
----- -----
- Issue #7151: fixed regrtest -j so that output to stderr from a test no
longer runs the risk of causing the worker thread to fail.
- Issue #7055: test___all__ now greedily detects all modules which have an - Issue #7055: test___all__ now greedily detects all modules which have an
__all__ attribute, rather than using a hardcoded and incomplete list. __all__ attribute, rather than using a hardcoded and incomplete list.