mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Update threading lib and tests from CPython 3.12.0a0 (#4156)
* Update threading.py from CPython v3.12.0a0 * Update test_threading.py from CPython v3.12.0a0 * mark failing tests --------- Co-authored-by: Jeong YunWon <jeong@youknowone.org>
This commit is contained in:
1 parent
6cc103bad3
commit
ce5e1bd455
2 files changed
+117
-27
No files matched your search
Vendored
+106
-27
@@ -3,7 +3,7 @@ Tests for the threading module.
|
||||
"""
|
||||
|
||||
import test.support
|
||||
from test.support import threading_helper
|
||||
from test.support import threading_helper, requires_subprocess
|
||||
from test.support import verbose, cpython_only, os_helper
|
||||
from test.support.import_helper import import_module
|
||||
from test.support.script_helper import assert_python_ok, assert_python_failure
|
||||
@@ -25,6 +25,7 @@ from unittest import mock
|
||||
from test import lock_tests
|
||||
from test import support
|
||||
|
||||
threading_helper.requires_working_threading(module=True)
|
||||
|
||||
# Between fork() and exec(), only async-safe functions are allowed (issues
|
||||
# #12316 and #11870), and fork() from a worker thread is known to trigger
|
||||
@@ -32,9 +33,6 @@ from test import support
|
||||
# on platforms known to behave badly.
|
||||
platforms_to_skip = ('netbsd5', 'hp-ux11')
|
||||
|
||||
# Is Python built with Py_DEBUG macro defined?
|
||||
Py_DEBUG = hasattr(sys, 'gettotalrefcount')
|
||||
|
||||
|
||||
def restore_default_excepthook(testcase):
|
||||
testcase.addCleanup(setattr, threading, 'excepthook', threading.excepthook)
|
||||
@@ -123,6 +121,33 @@ class ThreadTests(BaseTestCase):
|
||||
thread = threading.Thread(target=func)
|
||||
self.assertEqual(thread.name, "Thread-5 (func)")
|
||||
|
||||
def test_args_argument(self):
|
||||
# bpo-45735: Using list or tuple as *args* in constructor could
|
||||
# achieve the same effect.
|
||||
num_list = [1]
|
||||
num_tuple = (1,)
|
||||
|
||||
str_list = ["str"]
|
||||
str_tuple = ("str",)
|
||||
|
||||
list_in_tuple = ([1],)
|
||||
tuple_in_list = [(1,)]
|
||||
|
||||
test_cases = (
|
||||
(num_list, lambda arg: self.assertEqual(arg, 1)),
|
||||
(num_tuple, lambda arg: self.assertEqual(arg, 1)),
|
||||
(str_list, lambda arg: self.assertEqual(arg, "str")),
|
||||
(str_tuple, lambda arg: self.assertEqual(arg, "str")),
|
||||
(list_in_tuple, lambda arg: self.assertEqual(arg, [1])),
|
||||
(tuple_in_list, lambda arg: self.assertEqual(arg, (1,)))
|
||||
)
|
||||
|
||||
for args, target in test_cases:
|
||||
with self.subTest(target=target, args=args):
|
||||
t = threading.Thread(target=target, args=args)
|
||||
t.start()
|
||||
t.join()
|
||||
|
||||
@cpython_only
|
||||
def test_disallow_instantiation(self):
|
||||
# Ensure that the type disallows instantiation (bpo-43916)
|
||||
@@ -509,8 +534,7 @@ class ThreadTests(BaseTestCase):
|
||||
t = threading.Thread(daemon=True)
|
||||
self.assertTrue(t.daemon)
|
||||
|
||||
@unittest.skipUnless(hasattr(threading.Lock(), '_at_fork_reinit'), 'TODO: RUSTPYTHON, exit_handler needs lock._at_fork_reinit')
|
||||
@unittest.skipUnless(hasattr(os, 'fork'), 'needs os.fork()')
|
||||
@support.requires_fork()
|
||||
def test_fork_at_exit(self):
|
||||
# bpo-42350: Calling os.fork() after threading._shutdown() must
|
||||
# not log an error.
|
||||
@@ -538,7 +562,7 @@ class ThreadTests(BaseTestCase):
|
||||
self.assertEqual(out, b'')
|
||||
self.assertEqual(err.rstrip(), b'child process ok')
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'fork'), 'test needs fork()')
|
||||
@support.requires_fork()
|
||||
def test_dummy_thread_after_fork(self):
|
||||
# Issue #14308: a dummy thread in the active list doesn't mess up
|
||||
# the after-fork mechanism.
|
||||
@@ -565,8 +589,7 @@ class ThreadTests(BaseTestCase):
|
||||
self.assertEqual(out, b'')
|
||||
self.assertEqual(err, b'')
|
||||
|
||||
@unittest.skipUnless(hasattr(sys, 'getswitchinterval'), "TODO: RUSTPYTHON, needs sys.getswitchinterval()")
|
||||
@unittest.skipUnless(hasattr(os, 'fork'), "needs os.fork()")
|
||||
@support.requires_fork()
|
||||
def test_is_alive_after_fork(self):
|
||||
# Try hard to trigger #18418: is_alive() could sometimes be True on
|
||||
# threads that vanished after a fork.
|
||||
@@ -600,7 +623,7 @@ class ThreadTests(BaseTestCase):
|
||||
th.start()
|
||||
th.join()
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()")
|
||||
@support.requires_fork()
|
||||
@unittest.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()")
|
||||
def test_main_thread_after_fork(self):
|
||||
code = """if 1:
|
||||
@@ -622,7 +645,7 @@ class ThreadTests(BaseTestCase):
|
||||
self.assertEqual(data, "MainThread\nTrue\nTrue\n")
|
||||
|
||||
@unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
|
||||
@unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()")
|
||||
@support.requires_fork()
|
||||
@unittest.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()")
|
||||
@unittest.skipIf(os.name != 'posix', "test needs POSIX semantics")
|
||||
def test_main_thread_after_fork_from_nonmain_thread(self):
|
||||
@@ -837,6 +860,7 @@ class ThreadTests(BaseTestCase):
|
||||
callback()
|
||||
finally:
|
||||
sys.settrace(old_trace)
|
||||
threading.settrace(old_trace)
|
||||
|
||||
def test_gettrace(self):
|
||||
def noop_trace(frame, event, arg):
|
||||
@@ -850,6 +874,37 @@ class ThreadTests(BaseTestCase):
|
||||
finally:
|
||||
threading.settrace(old_trace)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_gettrace_all_threads(self):
|
||||
def fn(*args): pass
|
||||
old_trace = threading.gettrace()
|
||||
first_check = threading.Event()
|
||||
second_check = threading.Event()
|
||||
|
||||
trace_funcs = []
|
||||
def checker():
|
||||
trace_funcs.append(sys.gettrace())
|
||||
first_check.set()
|
||||
second_check.wait()
|
||||
trace_funcs.append(sys.gettrace())
|
||||
|
||||
try:
|
||||
t = threading.Thread(target=checker)
|
||||
t.start()
|
||||
first_check.wait()
|
||||
threading.settrace_all_threads(fn)
|
||||
second_check.set()
|
||||
t.join()
|
||||
self.assertEqual(trace_funcs, [None, fn])
|
||||
self.assertEqual(threading.gettrace(), fn)
|
||||
self.assertEqual(sys.gettrace(), fn)
|
||||
finally:
|
||||
threading.settrace_all_threads(old_trace)
|
||||
|
||||
self.assertEqual(threading.gettrace(), old_trace)
|
||||
self.assertEqual(sys.gettrace(), old_trace)
|
||||
|
||||
def test_getprofile(self):
|
||||
def fn(*args): pass
|
||||
old_profile = threading.getprofile()
|
||||
@@ -859,6 +914,37 @@ class ThreadTests(BaseTestCase):
|
||||
finally:
|
||||
threading.setprofile(old_profile)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_getprofile_all_threads(self):
|
||||
def fn(*args): pass
|
||||
old_profile = threading.getprofile()
|
||||
first_check = threading.Event()
|
||||
second_check = threading.Event()
|
||||
|
||||
profile_funcs = []
|
||||
def checker():
|
||||
profile_funcs.append(sys.getprofile())
|
||||
first_check.set()
|
||||
second_check.wait()
|
||||
profile_funcs.append(sys.getprofile())
|
||||
|
||||
try:
|
||||
t = threading.Thread(target=checker)
|
||||
t.start()
|
||||
first_check.wait()
|
||||
threading.setprofile_all_threads(fn)
|
||||
second_check.set()
|
||||
t.join()
|
||||
self.assertEqual(profile_funcs, [None, fn])
|
||||
self.assertEqual(threading.getprofile(), fn)
|
||||
self.assertEqual(sys.getprofile(), fn)
|
||||
finally:
|
||||
threading.setprofile_all_threads(old_profile)
|
||||
|
||||
self.assertEqual(threading.getprofile(), old_profile)
|
||||
self.assertEqual(sys.getprofile(), old_profile)
|
||||
|
||||
@cpython_only
|
||||
def test_shutdown_locks(self):
|
||||
for daemon in (False, True):
|
||||
@@ -929,16 +1015,6 @@ class ThreadTests(BaseTestCase):
|
||||
threading.Thread(target=noop).start()
|
||||
# Thread.join() is not called
|
||||
|
||||
@unittest.skipUnless(Py_DEBUG, 'need debug build (Py_DEBUG)')
|
||||
def test_debug_deprecation(self):
|
||||
# bpo-44584: The PYTHONTHREADDEBUG environment variable is deprecated
|
||||
rc, out, err = assert_python_ok("-Wdefault", "-c", "pass",
|
||||
PYTHONTHREADDEBUG="1")
|
||||
msg = (b'DeprecationWarning: The threading debug '
|
||||
b'(PYTHONTHREADDEBUG environment variable) '
|
||||
b'is deprecated and will be removed in Python 3.12')
|
||||
self.assertIn(msg, err)
|
||||
|
||||
def test_import_from_another_thread(self):
|
||||
# bpo-1596321: If the threading module is first import from a thread
|
||||
# different than the main thread, threading._shutdown() must handle
|
||||
@@ -1006,7 +1082,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
|
||||
"""
|
||||
self._run_and_join(script)
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'fork'), "needs os.fork()")
|
||||
@support.requires_fork()
|
||||
@unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
|
||||
# TODO: RUSTPYTHON need to fix test_1_join_on_shutdown then this might work
|
||||
@unittest.expectedFailure
|
||||
@@ -1029,7 +1105,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
|
||||
"""
|
||||
self._run_and_join(script)
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'fork'), "needs os.fork()")
|
||||
@support.requires_fork()
|
||||
@unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
|
||||
@unittest.skip("TODO: RUSTPYTHON, flaky test")
|
||||
def test_3_join_in_forked_from_thread(self):
|
||||
@@ -1075,8 +1151,9 @@ class ThreadJoinOnShutdown(BaseTestCase):
|
||||
|
||||
def random_io():
|
||||
'''Loop for a while sleeping random tiny amounts and doing some I/O.'''
|
||||
import test.test_threading as mod
|
||||
while True:
|
||||
with open(os.__file__, 'rb') as in_f:
|
||||
with open(mod.__file__, 'rb') as in_f:
|
||||
stuff = in_f.read(200)
|
||||
with open(os.devnull, 'wb') as null_f:
|
||||
null_f.write(stuff)
|
||||
@@ -1100,7 +1177,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
|
||||
rc, out, err = assert_python_ok('-c', script)
|
||||
self.assertFalse(err)
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'fork'), "needs os.fork()")
|
||||
@support.requires_fork()
|
||||
@unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
|
||||
def test_reinit_tls_after_fork(self):
|
||||
# Issue #13817: fork() would deadlock in a multithreaded program with
|
||||
@@ -1124,8 +1201,9 @@ class ThreadJoinOnShutdown(BaseTestCase):
|
||||
for t in threads:
|
||||
t.join()
|
||||
|
||||
@unittest.skipUnless(hasattr(sys, '_current_frames'), "TODO: RUSTPYTHON, needs sys._current_frames()")
|
||||
@unittest.skipUnless(hasattr(os, 'fork'), "needs os.fork()")
|
||||
@support.requires_fork()
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_clear_threads_states_after_fork(self):
|
||||
# Issue #17094: check that threads states are cleared after fork()
|
||||
|
||||
@@ -1280,6 +1358,7 @@ class ThreadingExceptionTests(BaseTestCase):
|
||||
self.assertRaises(RuntimeError, lock.release)
|
||||
|
||||
@unittest.skip("TODO: RUSTPYTHON, flaky test")
|
||||
@requires_subprocess()
|
||||
def test_recursion_limit(self):
|
||||
# Issue 9670
|
||||
# test that excessive recursion within a non-main thread causes
|
||||
|
||||
Vendored
+11
@@ -79,6 +79,17 @@ def settrace(func):
|
||||
global _trace_hook
|
||||
_trace_hook = func
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
def settrace_all_threads(func):
|
||||
"""Set a trace function for all threads started from the threading module
|
||||
and all Python threads that are currently executing.
|
||||
|
||||
The func will be passed to sys.settrace() for each thread, before its run()
|
||||
method is called.
|
||||
"""
|
||||
settrace(func)
|
||||
_sys._settraceallthreads(func)
|
||||
|
||||
def gettrace():
|
||||
"""Get the trace function as set by threading.settrace()."""
|
||||
return _trace_hook
|
||||
|
||||
Reference in new issue
Block a user