]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-40280: Add requires_fork test helper (GH-30622)
authorChristian Heimes <christian@python.org>
Sun, 16 Jan 2022 21:52:43 +0000 (23:52 +0200)
committerGitHub <noreply@github.com>
Sun, 16 Jan 2022 21:52:43 +0000 (22:52 +0100)
Lib/test/support/__init__.py
Lib/test/test_fork1.py
Lib/test/test_random.py
Lib/test/test_support.py
Lib/test/test_sysconfig.py
Lib/test/test_tempfile.py
Lib/test/test_thread.py
Lib/test/test_threading.py
Lib/test/test_uuid.py
Misc/NEWS.d/next/Tests/2022-01-16-14-11-57.bpo-40280.fNnFfx.rst [new file with mode: 0644]

index f8faa41ad439c4713b74f7d3b93b96f8f9591ef0..ca903d302bdd31c995a3ed8d6f3a4930661c670f 100644 (file)
@@ -39,12 +39,13 @@ __all__ = [
     "requires_gzip", "requires_bz2", "requires_lzma",
     "bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute",
     "requires_IEEE_754", "requires_zlib",
+    "has_fork_support", "requires_fork",
     "anticipate_failure", "load_package_tests", "detect_api_mismatch",
     "check__all__", "skip_if_buggy_ucrt_strfptime",
     "check_disallow_instantiation",
     # sys
-    "is_jython", "is_android", "check_impl_detail", "unix_shell",
-    "setswitchinterval",
+    "is_jython", "is_android", "is_emscripten",
+    "check_impl_detail", "unix_shell", "setswitchinterval",
     # network
     "open_urlresource",
     # processes
@@ -466,6 +467,15 @@ if sys.platform not in ('win32', 'vxworks'):
 else:
     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.
 # The URL must use clear-text HTTP: no redirection to encrypted HTTPS.
 TEST_HTTP_URL = "http://www.pythontest.net"
index a2f7cfee9cf699bd91426cfbf72e9f9912649b68..a6523bbc518176946a832ad48e557f0b055ed495 100644 (file)
@@ -14,7 +14,9 @@ from test import support
 
 
 # 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):
     def test_threaded_import_lock_fork(self):
index b80aeca26cf48fcd41c3270e2cb7dc0fc7d5a0bf..f980c5b8df0d20ac84a6ef64deb3c8d01ffe2c0d 100644 (file)
@@ -1293,7 +1293,7 @@ class TestModule(unittest.TestCase):
         # tests validity but not completeness of the __all__ list
         self.assertTrue(set(random.__all__) <= set(dir(random)))
 
-    @unittest.skipUnless(hasattr(os, "fork"), "fork() required")
+    @test.support.requires_fork()
     def test_after_fork(self):
         # Test the global Random instance gets reseeded in child
         r, w = os.pipe()
index d5a1d447f05634345608508fa14ec2e397094fb9..4dac7f6cd420000162a62d0ec045a9e0bd521f70 100644 (file)
@@ -198,7 +198,7 @@ class TestSupport(unittest.TestCase):
                                         f'temporary directory {path!r}: '),
                         warn)
 
-    @unittest.skipUnless(hasattr(os, "fork"), "test requires os.fork")
+    @support.requires_fork()
     def test_temp_dir__forked_child(self):
         """Test that a forked child process does not remove the directory."""
         # See bpo-30028 for details.
@@ -447,6 +447,7 @@ class TestSupport(unittest.TestCase):
 
     @unittest.skipUnless(hasattr(os, 'waitpid') and hasattr(os, 'WNOHANG'),
                          'need os.waitpid() and os.WNOHANG')
+    @support.requires_fork()
     def test_reap_children(self):
         # Make sure that there is no other pending child process
         support.reap_children()
index 506266d08185da700f5e62f95d537c964984ec0a..6fbb80d77f793cd302040780ea2d97babdb61515 100644 (file)
@@ -412,6 +412,8 @@ class TestSysConfig(unittest.TestCase):
                      'EXT_SUFFIX required for this test')
     def test_EXT_SUFFIX_in_vars(self):
         import _imp
+        if not _imp.extension_suffixes():
+            self.skipTest("stub loader has no suffixes")
         vars = sysconfig.get_config_vars()
         self.assertIsNotNone(vars['SO'])
         self.assertEqual(vars['SO'], vars['EXT_SUFFIX'])
index 2b0ec46a1032761bb84412868351735fdd8897f3..25fddaec6d317d99e176312ed3462714a9709852 100644 (file)
@@ -198,8 +198,7 @@ class TestRandomNameSequence(BaseTestCase):
             if i == 20:
                 break
 
-    @unittest.skipUnless(hasattr(os, 'fork'),
-        "os.fork is required for this test")
+    @support.requires_fork()
     def test_process_awareness(self):
         # ensure that the random source differs between
         # child and parent.
index 4ae8a833b990d78f4acb5f18df440e42b6a6f596..d55fb731b6df54c0d5cd6b52f749abb18957a292 100644 (file)
@@ -224,7 +224,7 @@ class TestForkInThread(unittest.TestCase):
     def setUp(self):
         self.read_fd, self.write_fd = os.pipe()
 
-    @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
+    @support.requires_fork()
     @threading_helper.reap_threads
     def test_forkinthread(self):
         pid = None
index a8f3c139b24be15f601c80e1bb5d66c8d580c840..f03a64232e17c39543d2a5210f3f0351215743db 100644 (file)
@@ -505,7 +505,7 @@ class ThreadTests(BaseTestCase):
         t = threading.Thread(daemon=True)
         self.assertTrue(t.daemon)
 
-    @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.
@@ -533,7 +533,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.
@@ -560,7 +560,7 @@ class ThreadTests(BaseTestCase):
         self.assertEqual(out, b'')
         self.assertEqual(err, b'')
 
-    @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.
@@ -594,7 +594,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:
@@ -616,7 +616,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()")
     def test_main_thread_after_fork_from_nonmain_thread(self):
         code = """if 1:
@@ -993,7 +993,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")
     def test_2_join_in_forked_process(self):
         # Like the test above, but from a forked interpreter
@@ -1014,7 +1014,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")
     def test_3_join_in_forked_from_thread(self):
         # 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)
         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
@@ -1109,7 +1109,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
         for t in threads:
             t.join()
 
-    @unittest.skipUnless(hasattr(os, 'fork'), "needs os.fork()")
+    @support.requires_fork()
     def test_clear_threads_states_after_fork(self):
         # Issue #17094: check that threads states are cleared after fork()
 
index 3f56192c70e846cca7366fced14f0dacb039d5d2..411eec0f406215b55f117bfbb60094fdfd1da8f7 100755 (executable)
@@ -647,7 +647,7 @@ class BaseTestUUID:
             equal(u, self.uuid.UUID(v))
             equal(str(u), v)
 
-    @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
+    @support.requires_fork()
     def testIssue8621(self):
         # On at least some versions of OSX self.uuid.uuid4 generates
         # the same sequence of UUIDs in the parent and any
diff --git a/Misc/NEWS.d/next/Tests/2022-01-16-14-11-57.bpo-40280.fNnFfx.rst b/Misc/NEWS.d/next/Tests/2022-01-16-14-11-57.bpo-40280.fNnFfx.rst
new file mode 100644 (file)
index 0000000..2d66db1
--- /dev/null
@@ -0,0 +1,2 @@
+Add :func:`test.support.requires_fork` decorators to mark tests that require
+a working :func:`os.fork`.