diff options
author | Christian Heimes <christian@python.org> | 2022-01-16 21:52:43 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-16 21:52:43 (GMT) |
commit | 91e33ac3d08a1c6004c469da2c0e2a97b5bdc53c (patch) | |
tree | 93e1ad6d692a706bd319b6c705642487499f4965 | |
parent | 5cd9a162cd02a3d0f1b0a182d80feeb17439e84f (diff) | |
download | cpython-91e33ac3d08a1c6004c469da2c0e2a97b5bdc53c.zip cpython-91e33ac3d08a1c6004c469da2c0e2a97b5bdc53c.tar.gz cpython-91e33ac3d08a1c6004c469da2c0e2a97b5bdc53c.tar.bz2 |
bpo-40280: Add requires_fork test helper (GH-30622)
-rw-r--r-- | Lib/test/support/__init__.py | 14 | ||||
-rw-r--r-- | Lib/test/test_fork1.py | 4 | ||||
-rw-r--r-- | Lib/test/test_random.py | 2 | ||||
-rw-r--r-- | Lib/test/test_support.py | 3 | ||||
-rw-r--r-- | Lib/test/test_sysconfig.py | 2 | ||||
-rw-r--r-- | Lib/test/test_tempfile.py | 3 | ||||
-rw-r--r-- | Lib/test/test_thread.py | 2 | ||||
-rw-r--r-- | Lib/test/test_threading.py | 18 | ||||
-rwxr-xr-x | Lib/test/test_uuid.py | 2 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Tests/2022-01-16-14-11-57.bpo-40280.fNnFfx.rst | 2 |
10 files changed, 34 insertions, 18 deletions
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index f8faa41..ca903d3 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -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" diff --git a/Lib/test/test_fork1.py b/Lib/test/test_fork1.py index a2f7cfe..a6523bb 100644 --- a/Lib/test/test_fork1.py +++ b/Lib/test/test_fork1.py @@ -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): diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index b80aeca..f980c5b 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -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() diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index d5a1d44..4dac7f6 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -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() diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 506266d..6fbb80d 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -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']) diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 2b0ec46..25fddae 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -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. diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py index 4ae8a83..d55fb73 100644 --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -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 diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index a8f3c13..f03a642 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -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() diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py index 3f56192..411eec0 100755 --- a/Lib/test/test_uuid.py +++ b/Lib/test/test_uuid.py @@ -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 index 0000000..2d66db1 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-01-16-14-11-57.bpo-40280.fNnFfx.rst @@ -0,0 +1,2 @@ +Add :func:`test.support.requires_fork` decorators to mark tests that require +a working :func:`os.fork`. |