mirror of https://github.com/python/cpython.git
gh-101634: regrtest reports decoding error as failed test (#106169)
When running the Python test suite with -jN option, if a worker stdout
cannot be decoded from the locale encoding report a failed testn so the
exitcode is non-zero.
(cherry picked from commit 2ac3eec103
)
This commit is contained in:
parent
fbb0151e5e
commit
d5418e97fc
|
@ -269,6 +269,7 @@ def _runtest(self, test_name: str) -> MultiprocessResult:
|
||||||
encoding = locale.getencoding()
|
encoding = locale.getencoding()
|
||||||
else:
|
else:
|
||||||
encoding = sys.stdout.encoding
|
encoding = sys.stdout.encoding
|
||||||
|
|
||||||
# gh-94026: Write stdout+stderr to a tempfile as workaround for
|
# gh-94026: Write stdout+stderr to a tempfile as workaround for
|
||||||
# non-blocking pipes on Emscripten with NodeJS.
|
# non-blocking pipes on Emscripten with NodeJS.
|
||||||
with tempfile.TemporaryFile('w+', encoding=encoding) as stdout_fh:
|
with tempfile.TemporaryFile('w+', encoding=encoding) as stdout_fh:
|
||||||
|
@ -277,7 +278,14 @@ def _runtest(self, test_name: str) -> MultiprocessResult:
|
||||||
# Python finalization: too late for libregrtest.
|
# Python finalization: too late for libregrtest.
|
||||||
retcode = self._run_process(test_name, stdout_fh)
|
retcode = self._run_process(test_name, stdout_fh)
|
||||||
stdout_fh.seek(0)
|
stdout_fh.seek(0)
|
||||||
stdout = stdout_fh.read().strip()
|
|
||||||
|
try:
|
||||||
|
stdout = stdout_fh.read().strip()
|
||||||
|
except Exception as exc:
|
||||||
|
# gh-101634: Catch UnicodeDecodeError if stdout cannot be
|
||||||
|
# decoded from encoding
|
||||||
|
err_msg = f"Cannot read process stdout: {exc}"
|
||||||
|
return self.mp_result_error(ChildError(test_name), '', err_msg)
|
||||||
|
|
||||||
if retcode is None:
|
if retcode is None:
|
||||||
return self.mp_result_error(Timeout(test_name), stdout)
|
return self.mp_result_error(Timeout(test_name), stdout)
|
||||||
|
@ -452,6 +460,8 @@ def _process_result(self, item: QueueOutput) -> bool:
|
||||||
# Thread got an exception
|
# Thread got an exception
|
||||||
format_exc = item[1]
|
format_exc = item[1]
|
||||||
print_warning(f"regrtest worker thread failed: {format_exc}")
|
print_warning(f"regrtest worker thread failed: {format_exc}")
|
||||||
|
result = ChildError("<regrtest worker>")
|
||||||
|
self.regrtest.accumulate_result(result)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
self.test_index += 1
|
self.test_index += 1
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import contextlib
|
import contextlib
|
||||||
import glob
|
import glob
|
||||||
import io
|
import io
|
||||||
|
import locale
|
||||||
import os.path
|
import os.path
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
|
@ -1518,6 +1519,41 @@ def test_cleanup(self):
|
||||||
for name in names:
|
for name in names:
|
||||||
self.assertFalse(os.path.exists(name), name)
|
self.assertFalse(os.path.exists(name), name)
|
||||||
|
|
||||||
|
def test_mp_decode_error(self):
|
||||||
|
# gh-101634: If a worker stdout cannot be decoded, report a failed test
|
||||||
|
# and a non-zero exit code.
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
encoding = locale.getencoding()
|
||||||
|
else:
|
||||||
|
encoding = sys.stdout.encoding
|
||||||
|
if encoding is None:
|
||||||
|
encoding = sys.__stdout__.encoding
|
||||||
|
if encoding is None:
|
||||||
|
self.skipTest(f"cannot get regrtest worker encoding")
|
||||||
|
|
||||||
|
nonascii = b"byte:\xa0\xa9\xff\n"
|
||||||
|
try:
|
||||||
|
nonascii.decode(encoding)
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.skipTest(f"{encoding} can decode non-ASCII bytes {nonascii!a}")
|
||||||
|
|
||||||
|
code = textwrap.dedent(fr"""
|
||||||
|
import sys
|
||||||
|
# bytes which cannot be decoded from UTF-8
|
||||||
|
nonascii = {nonascii!a}
|
||||||
|
sys.stdout.buffer.write(nonascii)
|
||||||
|
sys.stdout.buffer.flush()
|
||||||
|
""")
|
||||||
|
testname = self.create_test(code=code)
|
||||||
|
|
||||||
|
output = self.run_tests("--fail-env-changed", "-v", "-j1", testname,
|
||||||
|
exitcode=EXITCODE_BAD_TEST)
|
||||||
|
self.check_executed_tests(output, [testname],
|
||||||
|
failed=[testname],
|
||||||
|
randomize=True)
|
||||||
|
|
||||||
|
|
||||||
class TestUtils(unittest.TestCase):
|
class TestUtils(unittest.TestCase):
|
||||||
def test_format_duration(self):
|
def test_format_duration(self):
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
When running the Python test suite with ``-jN`` option, if a worker stdout
|
||||||
|
cannot be decoded from the locale encoding report a failed testn so the
|
||||||
|
exitcode is non-zero. Patch by Victor Stinner.
|
Loading…
Reference in New Issue