Skip to content

Commit

Permalink
bpo-45410: regrtest replaces print_warning.orig_stderr (GH-28926)
Browse files Browse the repository at this point in the history
When running Python tests with -W, runtest() now replaces
support.print_warning.orig_stderr to preserve the messages order.

Add an unit test.
  • Loading branch information
vstinner committed Oct 13, 2021
1 parent 713bb19 commit 676201a
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
9 changes: 9 additions & 0 deletions Lib/test/libregrtest/runtest.py
Expand Up @@ -196,17 +196,26 @@ def _runtest(ns: Namespace, test_name: str) -> TestResult:
stream = io.StringIO()
orig_stdout = sys.stdout
orig_stderr = sys.stderr
print_warning = support.print_warning
orig_print_warnings_stderr = print_warning.orig_stderr

output = None
try:
sys.stdout = stream
sys.stderr = stream
# print_warning() writes into the temporary stream to preserve
# messages order. If support.environment_altered becomes true,
# warnings will be written to sys.stderr below.
print_warning.orig_stderr = stream

result = _runtest_inner(ns, test_name,
display_failure=False)
if not isinstance(result, Passed):
output = stream.getvalue()
finally:
sys.stdout = orig_stdout
sys.stderr = orig_stderr
print_warning.orig_stderr = orig_print_warnings_stderr

if output is not None:
sys.stderr.write(output)
Expand Down
7 changes: 4 additions & 3 deletions Lib/test/libregrtest/save_env.py
Expand Up @@ -320,7 +320,8 @@ def __exit__(self, exc_type, exc_val, exc_tb):
support.environment_altered = True
restore(original)
if not self.quiet and not self.pgo:
print_warning(f"{name} was modified by {self.testname}")
print(f" Before: {original}\n After: {current} ",
file=sys.stderr, flush=True)
print_warning(
f"{name} was modified by {self.testname}\n"
f" Before: {original}\n"
f" After: {current} ")
return False
40 changes: 40 additions & 0 deletions Lib/test/test_regrtest.py
Expand Up @@ -1300,6 +1300,46 @@ def test_threading_excepthook(self):
self.assertIn("Warning -- Uncaught thread exception", output)
self.assertIn("Exception: bug in thread", output)

def test_print_warning(self):
# bpo-45410: The order of messages must be preserved when -W and
# support.print_warning() are used.
code = textwrap.dedent(r"""
import sys
import unittest
from test import support
class MyObject:
pass
def func_bug():
raise Exception("bug in thread")
class Tests(unittest.TestCase):
def test_print_warning(self):
print("msg1: stdout")
support.print_warning("msg2: print_warning")
# Fail with ENV CHANGED to see print_warning() log
support.environment_altered = True
""")
testname = self.create_test(code=code)

# Expect an output like:
#
# test_threading_excepthook (test.test_x.Tests) ... msg1: stdout
# Warning -- msg2: print_warning
# ok
regex = (r"test_print_warning.*msg1: stdout\n"
r"Warning -- msg2: print_warning\n"
r"ok\n")
for option in ("-v", "-W"):
with self.subTest(option=option):
cmd = ["--fail-env-changed", option, testname]
output = self.run_tests(*cmd, exitcode=3)
self.check_executed_tests(output, [testname],
env_changed=[testname],
fail_env_changed=True)
self.assertRegex(output, regex)

def test_unicode_guard_env(self):
guard = os.environ.get(setup.UNICODE_GUARD_ENV)
self.assertIsNotNone(guard, f"{setup.UNICODE_GUARD_ENV} not set")
Expand Down

0 comments on commit 676201a

Please sign in to comment.