[Python-checkins] Refactor sanitiser skip tests into test.support (GH-30889)

pablogsal webhook-mailer at python.org
Tue Jan 25 17:01:21 EST 2022


https://github.com/python/cpython/commit/b1cb8430504931f7854eac5d32cba74770078a4e
commit: b1cb8430504931f7854eac5d32cba74770078a4e
branch: main
author: Pablo Galindo Salgado <Pablogsal at gmail.com>
committer: pablogsal <Pablogsal at gmail.com>
date: 2022-01-25T22:01:10Z
summary:

Refactor sanitiser skip tests into test.support (GH-30889)

* Refactor sanitizer skip tests into test.support

* fixup! Refactor sanitizer skip tests into test.support

* fixup! fixup! Refactor sanitizer skip tests into test.support

files:
M Lib/test/support/__init__.py
M Lib/test/test_faulthandler.py
M Lib/test/test_io.py

diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 1e4935fc3e617..583d94f41e563 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -43,7 +43,7 @@
     "has_subprocess_support", "requires_subprocess",
     "anticipate_failure", "load_package_tests", "detect_api_mismatch",
     "check__all__", "skip_if_buggy_ucrt_strfptime",
-    "check_disallow_instantiation",
+    "check_disallow_instantiation", "skip_if_sanitizer",
     # sys
     "is_jython", "is_android", "is_emscripten", "is_wasi",
     "check_impl_detail", "unix_shell", "setswitchinterval",
@@ -384,6 +384,35 @@ def skip_if_buildbot(reason=None):
         isbuildbot = os.environ.get('USER') == 'buildbot'
     return unittest.skipIf(isbuildbot, reason)
 
+def skip_if_sanitizer(reason=None, *, address=False, memory=False, ub=False):
+    """Decorator raising SkipTest if running with a sanitizer active."""
+    if not (address or memory or ub):
+        raise ValueError('At least one of address, memory, or ub must be True')
+
+    if not reason:
+        reason = 'not working with sanitizers active'
+
+    _cflags = sysconfig.get_config_var('CFLAGS') or ''
+    _config_args = sysconfig.get_config_var('CONFIG_ARGS') or ''
+    memory_sanitizer = (
+        '-fsanitize=memory' in _cflags or
+        '--with-memory-sanitizer' in _config_args
+    )
+    address_sanitizer = (
+        '-fsanitize=address' in _cflags or
+        '--with-memory-sanitizer' in _config_args
+    )
+    ub_sanitizer = (
+        '-fsanitize=undefined' in _cflags or
+        '--with-undefined-behavior-sanitizer' in _config_args
+    )
+    skip = (
+        (memory and memory_sanitizer) or
+        (address and address_sanitizer) or
+        (ub and ub_sanitizer)
+    )
+    return unittest.skipIf(skip, reason)
+
 
 def system_must_validate_cert(f):
     """Skip the test on TLS certificate validation failures."""
diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py
index f7eaa77942476..daacdeef5bc80 100644
--- a/Lib/test/test_faulthandler.py
+++ b/Lib/test/test_faulthandler.py
@@ -6,10 +6,10 @@
 import signal
 import subprocess
 import sys
-import sysconfig
 from test import support
 from test.support import os_helper
 from test.support import script_helper, is_android
+from test.support import skip_if_sanitizer
 import tempfile
 import unittest
 from textwrap import dedent
@@ -21,16 +21,6 @@
 
 TIMEOUT = 0.5
 MS_WINDOWS = (os.name == 'nt')
-_cflags = sysconfig.get_config_var('CFLAGS') or ''
-_config_args = sysconfig.get_config_var('CONFIG_ARGS') or ''
-UB_SANITIZER = (
-    '-fsanitize=undefined' in _cflags or
-    '--with-undefined-behavior-sanitizer' in _config_args
-)
-MEMORY_SANITIZER = (
-    '-fsanitize=memory' in _cflags or
-    '--with-memory-sanitizer' in _config_args
-)
 
 
 def expected_traceback(lineno1, lineno2, header, min_count=1):
@@ -311,8 +301,8 @@ def test_gil_released(self):
             3,
             'Segmentation fault')
 
-    @unittest.skipIf(UB_SANITIZER or MEMORY_SANITIZER,
-                     "sanitizer builds change crashing process output.")
+    @skip_if_sanitizer(memory=True, ub=True, reason="sanitizer "
+                       "builds change crashing process output.")
     @skip_segfault_on_android
     def test_enable_file(self):
         with temporary_filename() as filename:
@@ -328,8 +318,8 @@ def test_enable_file(self):
 
     @unittest.skipIf(sys.platform == "win32",
                      "subprocess doesn't support pass_fds on Windows")
-    @unittest.skipIf(UB_SANITIZER or MEMORY_SANITIZER,
-                     "sanitizer builds change crashing process output.")
+    @skip_if_sanitizer(memory=True, ub=True, reason="sanitizer "
+                       "builds change crashing process output.")
     @skip_segfault_on_android
     def test_enable_fd(self):
         with tempfile.TemporaryFile('wb+') as fp:
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index 3619e749d1731..a10611abb13f4 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -28,7 +28,6 @@
 import random
 import signal
 import sys
-import sysconfig
 import textwrap
 import threading
 import time
@@ -44,6 +43,7 @@
 from test.support import os_helper
 from test.support import threading_helper
 from test.support import warnings_helper
+from test.support import skip_if_sanitizer
 from test.support.os_helper import FakePath
 
 import codecs
@@ -66,17 +66,6 @@ def byteslike(*pos, **kw):
     class EmptyStruct(ctypes.Structure):
         pass
 
-_cflags = sysconfig.get_config_var('CFLAGS') or ''
-_config_args = sysconfig.get_config_var('CONFIG_ARGS') or ''
-MEMORY_SANITIZER = (
-    '-fsanitize=memory' in _cflags or
-    '--with-memory-sanitizer' in _config_args
-)
-
-ADDRESS_SANITIZER = (
-    '-fsanitize=address' in _cflags
-)
-
 # Does io.IOBase finalizer log the exception if the close() method fails?
 # The exception is ignored silently by default in release build.
 IOBASE_EMITS_UNRAISABLE = (hasattr(sys, "gettotalrefcount") or sys.flags.dev_mode)
@@ -1550,8 +1539,8 @@ def test_truncate_on_read_only(self):
 class CBufferedReaderTest(BufferedReaderTest, SizeofTest):
     tp = io.BufferedReader
 
-    @unittest.skipIf(MEMORY_SANITIZER or ADDRESS_SANITIZER, "sanitizer defaults to crashing "
-                     "instead of returning NULL for malloc failure.")
+    @skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing "
+                       "instead of returning NULL for malloc failure.")
     def test_constructor(self):
         BufferedReaderTest.test_constructor(self)
         # The allocation can succeed on 32-bit builds, e.g. with more
@@ -1915,8 +1904,8 @@ def test_slow_close_from_thread(self):
 class CBufferedWriterTest(BufferedWriterTest, SizeofTest):
     tp = io.BufferedWriter
 
-    @unittest.skipIf(MEMORY_SANITIZER or ADDRESS_SANITIZER, "sanitizer defaults to crashing "
-                     "instead of returning NULL for malloc failure.")
+    @skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing "
+                       "instead of returning NULL for malloc failure.")
     def test_constructor(self):
         BufferedWriterTest.test_constructor(self)
         # The allocation can succeed on 32-bit builds, e.g. with more
@@ -2414,8 +2403,8 @@ def test_interleaved_readline_write(self):
 class CBufferedRandomTest(BufferedRandomTest, SizeofTest):
     tp = io.BufferedRandom
 
-    @unittest.skipIf(MEMORY_SANITIZER or ADDRESS_SANITIZER, "sanitizer defaults to crashing "
-                     "instead of returning NULL for malloc failure.")
+    @skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing "
+                       "instead of returning NULL for malloc failure.")
     def test_constructor(self):
         BufferedRandomTest.test_constructor(self)
         # The allocation can succeed on 32-bit builds, e.g. with more



More information about the Python-checkins mailing list