Skip to content

Commit b1cb843

Browse files
authored
Refactor sanitiser skip tests into test.support (pythonGH-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
1 parent cef0a54 commit b1cb843

File tree

3 files changed

+42
-34
lines changed

3 files changed

+42
-34
lines changed

Lib/test/support/__init__.py

+30-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
"has_subprocess_support", "requires_subprocess",
4444
"anticipate_failure", "load_package_tests", "detect_api_mismatch",
4545
"check__all__", "skip_if_buggy_ucrt_strfptime",
46-
"check_disallow_instantiation",
46+
"check_disallow_instantiation", "skip_if_sanitizer",
4747
# sys
4848
"is_jython", "is_android", "is_emscripten", "is_wasi",
4949
"check_impl_detail", "unix_shell", "setswitchinterval",
@@ -384,6 +384,35 @@ def skip_if_buildbot(reason=None):
384384
isbuildbot = os.environ.get('USER') == 'buildbot'
385385
return unittest.skipIf(isbuildbot, reason)
386386

387+
def skip_if_sanitizer(reason=None, *, address=False, memory=False, ub=False):
388+
"""Decorator raising SkipTest if running with a sanitizer active."""
389+
if not (address or memory or ub):
390+
raise ValueError('At least one of address, memory, or ub must be True')
391+
392+
if not reason:
393+
reason = 'not working with sanitizers active'
394+
395+
_cflags = sysconfig.get_config_var('CFLAGS') or ''
396+
_config_args = sysconfig.get_config_var('CONFIG_ARGS') or ''
397+
memory_sanitizer = (
398+
'-fsanitize=memory' in _cflags or
399+
'--with-memory-sanitizer' in _config_args
400+
)
401+
address_sanitizer = (
402+
'-fsanitize=address' in _cflags or
403+
'--with-memory-sanitizer' in _config_args
404+
)
405+
ub_sanitizer = (
406+
'-fsanitize=undefined' in _cflags or
407+
'--with-undefined-behavior-sanitizer' in _config_args
408+
)
409+
skip = (
410+
(memory and memory_sanitizer) or
411+
(address and address_sanitizer) or
412+
(ub and ub_sanitizer)
413+
)
414+
return unittest.skipIf(skip, reason)
415+
387416

388417
def system_must_validate_cert(f):
389418
"""Skip the test on TLS certificate validation failures."""

Lib/test/test_faulthandler.py

+5-15
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
import signal
77
import subprocess
88
import sys
9-
import sysconfig
109
from test import support
1110
from test.support import os_helper
1211
from test.support import script_helper, is_android
12+
from test.support import skip_if_sanitizer
1313
import tempfile
1414
import unittest
1515
from textwrap import dedent
@@ -21,16 +21,6 @@
2121

2222
TIMEOUT = 0.5
2323
MS_WINDOWS = (os.name == 'nt')
24-
_cflags = sysconfig.get_config_var('CFLAGS') or ''
25-
_config_args = sysconfig.get_config_var('CONFIG_ARGS') or ''
26-
UB_SANITIZER = (
27-
'-fsanitize=undefined' in _cflags or
28-
'--with-undefined-behavior-sanitizer' in _config_args
29-
)
30-
MEMORY_SANITIZER = (
31-
'-fsanitize=memory' in _cflags or
32-
'--with-memory-sanitizer' in _config_args
33-
)
3424

3525

3626
def expected_traceback(lineno1, lineno2, header, min_count=1):
@@ -311,8 +301,8 @@ def test_gil_released(self):
311301
3,
312302
'Segmentation fault')
313303

314-
@unittest.skipIf(UB_SANITIZER or MEMORY_SANITIZER,
315-
"sanitizer builds change crashing process output.")
304+
@skip_if_sanitizer(memory=True, ub=True, reason="sanitizer "
305+
"builds change crashing process output.")
316306
@skip_segfault_on_android
317307
def test_enable_file(self):
318308
with temporary_filename() as filename:
@@ -328,8 +318,8 @@ def test_enable_file(self):
328318

329319
@unittest.skipIf(sys.platform == "win32",
330320
"subprocess doesn't support pass_fds on Windows")
331-
@unittest.skipIf(UB_SANITIZER or MEMORY_SANITIZER,
332-
"sanitizer builds change crashing process output.")
321+
@skip_if_sanitizer(memory=True, ub=True, reason="sanitizer "
322+
"builds change crashing process output.")
333323
@skip_segfault_on_android
334324
def test_enable_fd(self):
335325
with tempfile.TemporaryFile('wb+') as fp:

Lib/test/test_io.py

+7-18
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import random
2929
import signal
3030
import sys
31-
import sysconfig
3231
import textwrap
3332
import threading
3433
import time
@@ -44,6 +43,7 @@
4443
from test.support import os_helper
4544
from test.support import threading_helper
4645
from test.support import warnings_helper
46+
from test.support import skip_if_sanitizer
4747
from test.support.os_helper import FakePath
4848

4949
import codecs
@@ -66,17 +66,6 @@ def byteslike(*pos, **kw):
6666
class EmptyStruct(ctypes.Structure):
6767
pass
6868

69-
_cflags = sysconfig.get_config_var('CFLAGS') or ''
70-
_config_args = sysconfig.get_config_var('CONFIG_ARGS') or ''
71-
MEMORY_SANITIZER = (
72-
'-fsanitize=memory' in _cflags or
73-
'--with-memory-sanitizer' in _config_args
74-
)
75-
76-
ADDRESS_SANITIZER = (
77-
'-fsanitize=address' in _cflags
78-
)
79-
8069
# Does io.IOBase finalizer log the exception if the close() method fails?
8170
# The exception is ignored silently by default in release build.
8271
IOBASE_EMITS_UNRAISABLE = (hasattr(sys, "gettotalrefcount") or sys.flags.dev_mode)
@@ -1550,8 +1539,8 @@ def test_truncate_on_read_only(self):
15501539
class CBufferedReaderTest(BufferedReaderTest, SizeofTest):
15511540
tp = io.BufferedReader
15521541

1553-
@unittest.skipIf(MEMORY_SANITIZER or ADDRESS_SANITIZER, "sanitizer defaults to crashing "
1554-
"instead of returning NULL for malloc failure.")
1542+
@skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing "
1543+
"instead of returning NULL for malloc failure.")
15551544
def test_constructor(self):
15561545
BufferedReaderTest.test_constructor(self)
15571546
# The allocation can succeed on 32-bit builds, e.g. with more
@@ -1915,8 +1904,8 @@ def test_slow_close_from_thread(self):
19151904
class CBufferedWriterTest(BufferedWriterTest, SizeofTest):
19161905
tp = io.BufferedWriter
19171906

1918-
@unittest.skipIf(MEMORY_SANITIZER or ADDRESS_SANITIZER, "sanitizer defaults to crashing "
1919-
"instead of returning NULL for malloc failure.")
1907+
@skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing "
1908+
"instead of returning NULL for malloc failure.")
19201909
def test_constructor(self):
19211910
BufferedWriterTest.test_constructor(self)
19221911
# The allocation can succeed on 32-bit builds, e.g. with more
@@ -2414,8 +2403,8 @@ def test_interleaved_readline_write(self):
24142403
class CBufferedRandomTest(BufferedRandomTest, SizeofTest):
24152404
tp = io.BufferedRandom
24162405

2417-
@unittest.skipIf(MEMORY_SANITIZER or ADDRESS_SANITIZER, "sanitizer defaults to crashing "
2418-
"instead of returning NULL for malloc failure.")
2406+
@skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing "
2407+
"instead of returning NULL for malloc failure.")
24192408
def test_constructor(self):
24202409
BufferedRandomTest.test_constructor(self)
24212410
# The allocation can succeed on 32-bit builds, e.g. with more

0 commit comments

Comments
 (0)