]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Move get_signal_name() to test.support (#121251)
authorVictor Stinner <vstinner@python.org>
Tue, 2 Jul 2024 08:34:13 +0000 (10:34 +0200)
committerGitHub <noreply@github.com>
Tue, 2 Jul 2024 08:34:13 +0000 (10:34 +0200)
* Move get_signal_name() from test.libregrtest to test.support.
* Use get_signal_name() in support.script_helper.
* support.script_helper now decodes stdout and stderr from UTF-8,
  instead of ASCII, if a command failed.

Lib/test/libregrtest/run_workers.py
Lib/test/libregrtest/utils.py
Lib/test/support/__init__.py
Lib/test/support/script_helper.py
Lib/test/test_regrtest.py
Lib/test/test_support.py

index a71050e66db3bd7a56172d668092cee5daae755f..387ddf9614cf7939849ae8e130459ad4750fdc25 100644 (file)
@@ -22,7 +22,7 @@ from .runtests import RunTests, WorkerRunTests, JsonFile, JsonFileType
 from .single import PROGRESS_MIN_TIME
 from .utils import (
     StrPath, TestName,
-    format_duration, print_warning, count, plural, get_signal_name)
+    format_duration, print_warning, count, plural)
 from .worker import create_worker_process, USE_PROCESS_GROUP
 
 if MS_WINDOWS:
@@ -366,7 +366,7 @@ class WorkerThread(threading.Thread):
                                   err_msg=None,
                                   state=State.TIMEOUT)
             if retcode != 0:
-                name = get_signal_name(retcode)
+                name = support.get_signal_name(retcode)
                 if name:
                     retcode = f"{retcode} ({name})"
                 raise WorkerError(self.test_name, f"Exit code {retcode}", stdout,
index 0167742d388a2c3f3c852aa9316c561daacb39df..0197e50125d96e07e2eae27e2dfffee27a174eb4 100644 (file)
@@ -685,35 +685,6 @@ def cleanup_temp_dir(tmp_dir: StrPath):
             print("Remove file: %s" % name)
             os_helper.unlink(name)
 
-WINDOWS_STATUS = {
-    0xC0000005: "STATUS_ACCESS_VIOLATION",
-    0xC00000FD: "STATUS_STACK_OVERFLOW",
-    0xC000013A: "STATUS_CONTROL_C_EXIT",
-}
-
-def get_signal_name(exitcode):
-    if exitcode < 0:
-        signum = -exitcode
-        try:
-            return signal.Signals(signum).name
-        except ValueError:
-            pass
-
-    # Shell exit code (ex: WASI build)
-    if 128 < exitcode < 256:
-        signum = exitcode - 128
-        try:
-            return signal.Signals(signum).name
-        except ValueError:
-            pass
-
-    try:
-        return WINDOWS_STATUS[exitcode]
-    except KeyError:
-        pass
-
-    return None
-
 
 ILLEGAL_XML_CHARS_RE = re.compile(
     '['
index dbea070929be9b57a0600b96df25265741adfffc..18455bb6e0ff52bf20172e6e3f408f787985c001 100644 (file)
@@ -2632,3 +2632,35 @@ def initialized_with_pyrepl():
     """Detect whether PyREPL was used during Python initialization."""
     # If the main module has a __file__ attribute it's a Python module, which means PyREPL.
     return hasattr(sys.modules["__main__"], "__file__")
+
+
+WINDOWS_STATUS = {
+    0xC0000005: "STATUS_ACCESS_VIOLATION",
+    0xC00000FD: "STATUS_STACK_OVERFLOW",
+    0xC000013A: "STATUS_CONTROL_C_EXIT",
+}
+
+def get_signal_name(exitcode):
+    import signal
+
+    if exitcode < 0:
+        signum = -exitcode
+        try:
+            return signal.Signals(signum).name
+        except ValueError:
+            pass
+
+    # Shell exit code (ex: WASI build)
+    if 128 < exitcode < 256:
+        signum = exitcode - 128
+        try:
+            return signal.Signals(signum).name
+        except ValueError:
+            pass
+
+    try:
+        return WINDOWS_STATUS[exitcode]
+    except KeyError:
+        pass
+
+    return None
index 65e0bc199e7f0b5924ab42f0e300ae45e6b07213..d0be3179b0efa3fb803d619be2cad50c3b724378 100644 (file)
@@ -70,23 +70,25 @@ class _PythonRunResult(collections.namedtuple("_PythonRunResult",
             out = b'(... truncated stdout ...)' + out[-maxlen:]
         if len(err) > maxlen:
             err = b'(... truncated stderr ...)' + err[-maxlen:]
-        out = out.decode('ascii', 'replace').rstrip()
-        err = err.decode('ascii', 'replace').rstrip()
-        raise AssertionError("Process return code is %d\n"
-                             "command line: %r\n"
-                             "\n"
-                             "stdout:\n"
-                             "---\n"
-                             "%s\n"
-                             "---\n"
-                             "\n"
-                             "stderr:\n"
-                             "---\n"
-                             "%s\n"
-                             "---"
-                             % (self.rc, cmd_line,
-                                out,
-                                err))
+        out = out.decode('utf8', 'replace').rstrip()
+        err = err.decode('utf8', 'replace').rstrip()
+
+        exitcode = self.rc
+        signame = support.get_signal_name(exitcode)
+        if signame:
+            exitcode = f"{exitcode} ({signame})"
+        raise AssertionError(f"Process return code is {exitcode}\n"
+                             f"command line: {cmd_line!r}\n"
+                             f"\n"
+                             f"stdout:\n"
+                             f"---\n"
+                             f"{out}\n"
+                             f"---\n"
+                             f"\n"
+                             f"stderr:\n"
+                             f"---\n"
+                             f"{err}\n"
+                             f"---")
 
 
 # Executing the interpreter in a subprocess
index 44fd11bfdc3fcbfd0a4b681672038cd83ed2a8ff..d4f4a69a7a38c10997f96d660374e24b67622796 100644 (file)
@@ -2329,16 +2329,6 @@ class TestUtils(unittest.TestCase):
         self.assertIsNone(normalize('setUpModule (test.test_x)', is_error=True))
         self.assertIsNone(normalize('tearDownModule (test.test_module)', is_error=True))
 
-    def test_get_signal_name(self):
-        for exitcode, expected in (
-            (-int(signal.SIGINT), 'SIGINT'),
-            (-int(signal.SIGSEGV), 'SIGSEGV'),
-            (128 + int(signal.SIGABRT), 'SIGABRT'),
-            (3221225477, "STATUS_ACCESS_VIOLATION"),
-            (0xC00000FD, "STATUS_STACK_OVERFLOW"),
-        ):
-            self.assertEqual(utils.get_signal_name(exitcode), expected, exitcode)
-
     def test_format_resources(self):
         format_resources = utils.format_resources
         ALL_RESOURCES = utils.ALL_RESOURCES
index d6f024a476920c44a1a1ba33e48fd213be2c9971..e60e5477d32e1fa3985d110e79c191324b8b8c06 100644 (file)
@@ -3,6 +3,7 @@ import importlib
 import io
 import os
 import shutil
+import signal
 import socket
 import stat
 import subprocess
@@ -732,6 +733,17 @@ class TestSupport(unittest.TestCase):
         self.assertEqual(support.copy_python_src_ignore(path, os.listdir(path)),
                          ignored)
 
+    def test_get_signal_name(self):
+        for exitcode, expected in (
+            (-int(signal.SIGINT), 'SIGINT'),
+            (-int(signal.SIGSEGV), 'SIGSEGV'),
+            (128 + int(signal.SIGABRT), 'SIGABRT'),
+            (3221225477, "STATUS_ACCESS_VIOLATION"),
+            (0xC00000FD, "STATUS_STACK_OVERFLOW"),
+        ):
+            self.assertEqual(support.get_signal_name(exitcode), expected,
+                             exitcode)
+
     # XXX -follows a list of untested API
     # make_legacy_pyc
     # is_resource_enabled