diff options
author | Antoine Pitrou <antoine@python.org> | 2024-03-18 09:22:19 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-18 09:22:19 (GMT) |
commit | fcb230180faff828aa67ca2ee1aa94fc522e6daa (patch) | |
tree | 506950e0cd5d6b9aed881395189988c29b6a085c /Lib/test | |
parent | 2ac1b48a044429d7a290310348b53a87b9f2033a (diff) | |
download | cpython-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.py | 3 | ||||
-rw-r--r-- | Lib/test/libregrtest/main.py | 5 | ||||
-rw-r--r-- | Lib/test/libregrtest/tsan.py | 31 | ||||
-rw-r--r-- | Lib/test/support/script_helper.py | 4 | ||||
-rw-r--r-- | Lib/test/test_threading.py | 16 |
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 |