summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorAntoine Pitrou <antoine@python.org>2024-03-18 09:22:19 (GMT)
committerGitHub <noreply@github.com>2024-03-18 09:22:19 (GMT)
commitfcb230180faff828aa67ca2ee1aa94fc522e6daa (patch)
tree506950e0cd5d6b9aed881395189988c29b6a085c /Lib/test
parent2ac1b48a044429d7a290310348b53a87b9f2033a (diff)
downloadcpython-fcb230180faff828aa67ca2ee1aa94fc522e6daa.zip
cpython-fcb230180faff828aa67ca2ee1aa94fc522e6daa.tar.gz
cpython-fcb230180faff828aa67ca2ee1aa94fc522e6daa.tar.bz2
[3.12] gh-112536: Add --tsan test for reasonable TSAN execution times. (gh-116601) (#116929)
(cherry picked from commit ebf29b3) Co-authored-by: Donghee Na <donghee.na@python.org>
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/libregrtest/cmdline.py3
-rw-r--r--Lib/test/libregrtest/main.py5
-rw-r--r--Lib/test/libregrtest/tsan.py31
-rw-r--r--Lib/test/support/script_helper.py4
-rw-r--r--Lib/test/test_threading.py16
5 files changed, 57 insertions, 2 deletions
diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py
index 23ca356..ccf5c2e 100644
--- a/Lib/test/libregrtest/cmdline.py
+++ b/Lib/test/libregrtest/cmdline.py
@@ -164,6 +164,7 @@ class Namespace(argparse.Namespace):
self.match_tests: TestFilter = []
self.pgo = False
self.pgo_extended = False
+ self.tsan = False
self.worker_json = None
self.start = None
self.timeout = None
@@ -333,6 +334,8 @@ def _create_parser():
help='enable Profile Guided Optimization (PGO) training')
group.add_argument('--pgo-extended', action='store_true',
help='enable extended PGO training (slower training)')
+ group.add_argument('--tsan', dest='tsan', action='store_true',
+ help='run a subset of test cases that are proper for the TSAN test')
group.add_argument('--fail-env-changed', action='store_true',
help='if a test file alters the environment, mark '
'the test as failed')
diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py
index a9725fa..1dcf747 100644
--- a/Lib/test/libregrtest/main.py
+++ b/Lib/test/libregrtest/main.py
@@ -18,6 +18,7 @@ from .results import TestResults, EXITCODE_INTERRUPTED
from .runtests import RunTests, HuntRefleak
from .setup import setup_process, setup_test_dir
from .single import run_single_test, PROGRESS_MIN_TIME
+from .tsan import setup_tsan_tests
from .utils import (
StrPath, StrJSON, TestName, TestList, TestTuple, TestFilter,
strip_py_suffix, count, format_duration,
@@ -56,6 +57,7 @@ class Regrtest:
self.quiet: bool = ns.quiet
self.pgo: bool = ns.pgo
self.pgo_extended: bool = ns.pgo_extended
+ self.tsan: bool = ns.tsan
# Test results
self.results: TestResults = TestResults()
@@ -182,6 +184,9 @@ class Regrtest:
# add default PGO tests if no tests are specified
setup_pgo_tests(self.cmdline_args, self.pgo_extended)
+ if self.tsan:
+ setup_tsan_tests(self.cmdline_args)
+
exclude_tests = set()
if self.exclude:
for arg in self.cmdline_args:
diff --git a/Lib/test/libregrtest/tsan.py b/Lib/test/libregrtest/tsan.py
new file mode 100644
index 0000000..99cef88
--- /dev/null
+++ b/Lib/test/libregrtest/tsan.py
@@ -0,0 +1,31 @@
+# Set of tests run by default if --tsan is specified. The tests below were
+# chosen because they use threads and run in a reasonable amount of time.
+
+TSAN_TESTS = [
+ 'test_capi',
+ 'test_code',
+ 'test_enum',
+ 'test_functools',
+ 'test_httpservers',
+ 'test_imaplib',
+ 'test_importlib',
+ 'test_io',
+ 'test_logging',
+ 'test_queue',
+ 'test_signal',
+ 'test_socket',
+ 'test_sqlite3',
+ 'test_ssl',
+ 'test_syslog',
+ 'test_thread',
+ 'test_threadedtempfile',
+ 'test_threading',
+ 'test_threading_local',
+ 'test_threadsignals',
+ 'test_weakref',
+]
+
+
+def setup_tsan_tests(cmdline_args):
+ if not cmdline_args:
+ cmdline_args[:] = TSAN_TESTS[:]
diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py
index c2b43f4..565f3b5 100644
--- a/Lib/test/support/script_helper.py
+++ b/Lib/test/support/script_helper.py
@@ -64,8 +64,8 @@ class _PythonRunResult(collections.namedtuple("_PythonRunResult",
"""Helper for reporting Python subprocess run results"""
def fail(self, cmd_line):
"""Provide helpful details about failed subcommand runs"""
- # Limit to 80 lines to ASCII characters
- maxlen = 80 * 100
+ # Limit to 300 lines of ASCII characters
+ maxlen = 300 * 100
out, err = self.out, self.err
if len(out) > maxlen:
out = b'(... truncated stdout ...)' + out[-maxlen:]
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 00d9e59..119b41f 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -47,6 +47,8 @@ def skip_unless_reliable_fork(test):
return unittest.skip("due to known OS bug related to thread+fork")(test)
if support.HAVE_ASAN_FORK_BUG:
return unittest.skip("libasan has a pthread_create() dead lock related to thread+fork")(test)
+ if support.check_sanitizer(thread=True):
+ return unittest.skip("TSAN doesn't support threads after fork")
return test
@@ -384,6 +386,10 @@ class ThreadTests(BaseTestCase):
# Issue 1402: the PyGILState_Ensure / _Release functions may be called
# very late on python exit: on deallocation of a running thread for
# example.
+ if support.check_sanitizer(thread=True):
+ # the thread running `time.sleep(100)` below will still be alive
+ # at process exit
+ self.skipTest("TSAN would report thread leak")
import_module("ctypes")
rc, out, err = assert_python_failure("-c", """if 1:
@@ -416,6 +422,11 @@ class ThreadTests(BaseTestCase):
def test_finalize_with_trace(self):
# Issue1733757
# Avoid a deadlock when sys.settrace steps into threading._shutdown
+ if support.check_sanitizer(thread=True):
+ # the thread running `time.sleep(2)` below will still be alive
+ # at process exit
+ self.skipTest("TSAN would report thread leak")
+
assert_python_ok("-c", """if 1:
import sys, threading
@@ -1223,6 +1234,11 @@ class ThreadJoinOnShutdown(BaseTestCase):
# Check that a daemon thread cannot crash the interpreter on shutdown
# by manipulating internal structures that are being disposed of in
# the main thread.
+ if support.check_sanitizer(thread=True):
+ # some of the threads running `random_io` below will still be alive
+ # at process exit
+ self.skipTest("TSAN would report thread leak")
+
script = """if True:
import os
import random