mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
bpo-40280: Add requires_fork test helper (GH-30622)
This commit is contained in:
parent
5cd9a162cd
commit
91e33ac3d0
10 changed files with 34 additions and 18 deletions
|
@ -39,12 +39,13 @@ __all__ = [
|
||||||
"requires_gzip", "requires_bz2", "requires_lzma",
|
"requires_gzip", "requires_bz2", "requires_lzma",
|
||||||
"bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute",
|
"bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute",
|
||||||
"requires_IEEE_754", "requires_zlib",
|
"requires_IEEE_754", "requires_zlib",
|
||||||
|
"has_fork_support", "requires_fork",
|
||||||
"anticipate_failure", "load_package_tests", "detect_api_mismatch",
|
"anticipate_failure", "load_package_tests", "detect_api_mismatch",
|
||||||
"check__all__", "skip_if_buggy_ucrt_strfptime",
|
"check__all__", "skip_if_buggy_ucrt_strfptime",
|
||||||
"check_disallow_instantiation",
|
"check_disallow_instantiation",
|
||||||
# sys
|
# sys
|
||||||
"is_jython", "is_android", "check_impl_detail", "unix_shell",
|
"is_jython", "is_android", "is_emscripten",
|
||||||
"setswitchinterval",
|
"check_impl_detail", "unix_shell", "setswitchinterval",
|
||||||
# network
|
# network
|
||||||
"open_urlresource",
|
"open_urlresource",
|
||||||
# processes
|
# processes
|
||||||
|
@ -466,6 +467,15 @@ if sys.platform not in ('win32', 'vxworks'):
|
||||||
else:
|
else:
|
||||||
unix_shell = None
|
unix_shell = None
|
||||||
|
|
||||||
|
# wasm32-emscripten is POSIX-like but does not provide a
|
||||||
|
# working fork() or subprocess API.
|
||||||
|
is_emscripten = sys.platform == "emscripten"
|
||||||
|
|
||||||
|
has_fork_support = hasattr(os, "fork") and not is_emscripten
|
||||||
|
|
||||||
|
def requires_fork():
|
||||||
|
return unittest.skipUnless(has_fork_support, "requires working os.fork()")
|
||||||
|
|
||||||
# Define the URL of a dedicated HTTP server for the network tests.
|
# Define the URL of a dedicated HTTP server for the network tests.
|
||||||
# The URL must use clear-text HTTP: no redirection to encrypted HTTPS.
|
# The URL must use clear-text HTTP: no redirection to encrypted HTTPS.
|
||||||
TEST_HTTP_URL = "http://www.pythontest.net"
|
TEST_HTTP_URL = "http://www.pythontest.net"
|
||||||
|
|
|
@ -14,7 +14,9 @@ from test import support
|
||||||
|
|
||||||
|
|
||||||
# Skip test if fork does not exist.
|
# Skip test if fork does not exist.
|
||||||
support.get_attribute(os, 'fork')
|
if not support.has_fork_support:
|
||||||
|
raise unittest.SkipTest("test module requires working os.fork")
|
||||||
|
|
||||||
|
|
||||||
class ForkTest(ForkWait):
|
class ForkTest(ForkWait):
|
||||||
def test_threaded_import_lock_fork(self):
|
def test_threaded_import_lock_fork(self):
|
||||||
|
|
|
@ -1293,7 +1293,7 @@ class TestModule(unittest.TestCase):
|
||||||
# tests validity but not completeness of the __all__ list
|
# tests validity but not completeness of the __all__ list
|
||||||
self.assertTrue(set(random.__all__) <= set(dir(random)))
|
self.assertTrue(set(random.__all__) <= set(dir(random)))
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, "fork"), "fork() required")
|
@test.support.requires_fork()
|
||||||
def test_after_fork(self):
|
def test_after_fork(self):
|
||||||
# Test the global Random instance gets reseeded in child
|
# Test the global Random instance gets reseeded in child
|
||||||
r, w = os.pipe()
|
r, w = os.pipe()
|
||||||
|
|
|
@ -198,7 +198,7 @@ class TestSupport(unittest.TestCase):
|
||||||
f'temporary directory {path!r}: '),
|
f'temporary directory {path!r}: '),
|
||||||
warn)
|
warn)
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, "fork"), "test requires os.fork")
|
@support.requires_fork()
|
||||||
def test_temp_dir__forked_child(self):
|
def test_temp_dir__forked_child(self):
|
||||||
"""Test that a forked child process does not remove the directory."""
|
"""Test that a forked child process does not remove the directory."""
|
||||||
# See bpo-30028 for details.
|
# See bpo-30028 for details.
|
||||||
|
@ -447,6 +447,7 @@ class TestSupport(unittest.TestCase):
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, 'waitpid') and hasattr(os, 'WNOHANG'),
|
@unittest.skipUnless(hasattr(os, 'waitpid') and hasattr(os, 'WNOHANG'),
|
||||||
'need os.waitpid() and os.WNOHANG')
|
'need os.waitpid() and os.WNOHANG')
|
||||||
|
@support.requires_fork()
|
||||||
def test_reap_children(self):
|
def test_reap_children(self):
|
||||||
# Make sure that there is no other pending child process
|
# Make sure that there is no other pending child process
|
||||||
support.reap_children()
|
support.reap_children()
|
||||||
|
|
|
@ -412,6 +412,8 @@ class TestSysConfig(unittest.TestCase):
|
||||||
'EXT_SUFFIX required for this test')
|
'EXT_SUFFIX required for this test')
|
||||||
def test_EXT_SUFFIX_in_vars(self):
|
def test_EXT_SUFFIX_in_vars(self):
|
||||||
import _imp
|
import _imp
|
||||||
|
if not _imp.extension_suffixes():
|
||||||
|
self.skipTest("stub loader has no suffixes")
|
||||||
vars = sysconfig.get_config_vars()
|
vars = sysconfig.get_config_vars()
|
||||||
self.assertIsNotNone(vars['SO'])
|
self.assertIsNotNone(vars['SO'])
|
||||||
self.assertEqual(vars['SO'], vars['EXT_SUFFIX'])
|
self.assertEqual(vars['SO'], vars['EXT_SUFFIX'])
|
||||||
|
|
|
@ -198,8 +198,7 @@ class TestRandomNameSequence(BaseTestCase):
|
||||||
if i == 20:
|
if i == 20:
|
||||||
break
|
break
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, 'fork'),
|
@support.requires_fork()
|
||||||
"os.fork is required for this test")
|
|
||||||
def test_process_awareness(self):
|
def test_process_awareness(self):
|
||||||
# ensure that the random source differs between
|
# ensure that the random source differs between
|
||||||
# child and parent.
|
# child and parent.
|
||||||
|
|
|
@ -224,7 +224,7 @@ class TestForkInThread(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.read_fd, self.write_fd = os.pipe()
|
self.read_fd, self.write_fd = os.pipe()
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
|
@support.requires_fork()
|
||||||
@threading_helper.reap_threads
|
@threading_helper.reap_threads
|
||||||
def test_forkinthread(self):
|
def test_forkinthread(self):
|
||||||
pid = None
|
pid = None
|
||||||
|
|
|
@ -505,7 +505,7 @@ class ThreadTests(BaseTestCase):
|
||||||
t = threading.Thread(daemon=True)
|
t = threading.Thread(daemon=True)
|
||||||
self.assertTrue(t.daemon)
|
self.assertTrue(t.daemon)
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, 'fork'), 'needs os.fork()')
|
@support.requires_fork()
|
||||||
def test_fork_at_exit(self):
|
def test_fork_at_exit(self):
|
||||||
# bpo-42350: Calling os.fork() after threading._shutdown() must
|
# bpo-42350: Calling os.fork() after threading._shutdown() must
|
||||||
# not log an error.
|
# not log an error.
|
||||||
|
@ -533,7 +533,7 @@ class ThreadTests(BaseTestCase):
|
||||||
self.assertEqual(out, b'')
|
self.assertEqual(out, b'')
|
||||||
self.assertEqual(err.rstrip(), b'child process ok')
|
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):
|
def test_dummy_thread_after_fork(self):
|
||||||
# Issue #14308: a dummy thread in the active list doesn't mess up
|
# Issue #14308: a dummy thread in the active list doesn't mess up
|
||||||
# the after-fork mechanism.
|
# the after-fork mechanism.
|
||||||
|
@ -560,7 +560,7 @@ class ThreadTests(BaseTestCase):
|
||||||
self.assertEqual(out, b'')
|
self.assertEqual(out, b'')
|
||||||
self.assertEqual(err, b'')
|
self.assertEqual(err, b'')
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, 'fork'), "needs os.fork()")
|
@support.requires_fork()
|
||||||
def test_is_alive_after_fork(self):
|
def test_is_alive_after_fork(self):
|
||||||
# Try hard to trigger #18418: is_alive() could sometimes be True on
|
# Try hard to trigger #18418: is_alive() could sometimes be True on
|
||||||
# threads that vanished after a fork.
|
# threads that vanished after a fork.
|
||||||
|
@ -594,7 +594,7 @@ class ThreadTests(BaseTestCase):
|
||||||
th.start()
|
th.start()
|
||||||
th.join()
|
th.join()
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()")
|
@support.requires_fork()
|
||||||
@unittest.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()")
|
@unittest.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()")
|
||||||
def test_main_thread_after_fork(self):
|
def test_main_thread_after_fork(self):
|
||||||
code = """if 1:
|
code = """if 1:
|
||||||
|
@ -616,7 +616,7 @@ class ThreadTests(BaseTestCase):
|
||||||
self.assertEqual(data, "MainThread\nTrue\nTrue\n")
|
self.assertEqual(data, "MainThread\nTrue\nTrue\n")
|
||||||
|
|
||||||
@unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
|
@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.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()")
|
||||||
def test_main_thread_after_fork_from_nonmain_thread(self):
|
def test_main_thread_after_fork_from_nonmain_thread(self):
|
||||||
code = """if 1:
|
code = """if 1:
|
||||||
|
@ -993,7 +993,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
|
||||||
"""
|
"""
|
||||||
self._run_and_join(script)
|
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.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
|
||||||
def test_2_join_in_forked_process(self):
|
def test_2_join_in_forked_process(self):
|
||||||
# Like the test above, but from a forked interpreter
|
# Like the test above, but from a forked interpreter
|
||||||
|
@ -1014,7 +1014,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
|
||||||
"""
|
"""
|
||||||
self._run_and_join(script)
|
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.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
|
||||||
def test_3_join_in_forked_from_thread(self):
|
def test_3_join_in_forked_from_thread(self):
|
||||||
# Like the test above, but fork() was called from a worker thread
|
# Like the test above, but fork() was called from a worker thread
|
||||||
|
@ -1085,7 +1085,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
|
||||||
rc, out, err = assert_python_ok('-c', script)
|
rc, out, err = assert_python_ok('-c', script)
|
||||||
self.assertFalse(err)
|
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")
|
@unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
|
||||||
def test_reinit_tls_after_fork(self):
|
def test_reinit_tls_after_fork(self):
|
||||||
# Issue #13817: fork() would deadlock in a multithreaded program with
|
# Issue #13817: fork() would deadlock in a multithreaded program with
|
||||||
|
@ -1109,7 +1109,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
|
||||||
for t in threads:
|
for t in threads:
|
||||||
t.join()
|
t.join()
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, 'fork'), "needs os.fork()")
|
@support.requires_fork()
|
||||||
def test_clear_threads_states_after_fork(self):
|
def test_clear_threads_states_after_fork(self):
|
||||||
# Issue #17094: check that threads states are cleared after fork()
|
# Issue #17094: check that threads states are cleared after fork()
|
||||||
|
|
||||||
|
|
|
@ -647,7 +647,7 @@ class BaseTestUUID:
|
||||||
equal(u, self.uuid.UUID(v))
|
equal(u, self.uuid.UUID(v))
|
||||||
equal(str(u), v)
|
equal(str(u), v)
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
|
@support.requires_fork()
|
||||||
def testIssue8621(self):
|
def testIssue8621(self):
|
||||||
# On at least some versions of OSX self.uuid.uuid4 generates
|
# On at least some versions of OSX self.uuid.uuid4 generates
|
||||||
# the same sequence of UUIDs in the parent and any
|
# the same sequence of UUIDs in the parent and any
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Add :func:`test.support.requires_fork` decorators to mark tests that require
|
||||||
|
a working :func:`os.fork`.
|
Loading…
Add table
Add a link
Reference in a new issue