diff options
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/_test_multiprocessing.py | 21 | ||||
-rw-r--r-- | Lib/test/_test_venv_multiprocessing.py | 1 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_events.py | 9 | ||||
-rw-r--r-- | Lib/test/test_concurrent_futures.py | 19 | ||||
-rw-r--r-- | Lib/test/test_fcntl.py | 8 | ||||
-rw-r--r-- | Lib/test/test_logging.py | 5 | ||||
-rw-r--r-- | Lib/test/test_multiprocessing_defaults.py | 82 | ||||
-rw-r--r-- | Lib/test/test_pickle.py | 2 | ||||
-rw-r--r-- | Lib/test/test_re.py | 3 |
9 files changed, 135 insertions, 15 deletions
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 2fa75eb..e4a60a4 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4098,9 +4098,10 @@ class _TestSharedMemory(BaseTestCase): def test_shared_memory_SharedMemoryManager_reuses_resource_tracker(self): # bpo-36867: test that a SharedMemoryManager uses the # same resource_tracker process as its parent. - cmd = '''if 1: + cmd = f'''if 1: from multiprocessing.managers import SharedMemoryManager - + from multiprocessing import set_start_method + set_start_method({multiprocessing.get_start_method()!r}) smm = SharedMemoryManager() smm.start() @@ -4967,11 +4968,13 @@ class TestFlags(unittest.TestCase): conn.send(tuple(sys.flags)) @classmethod - def run_in_child(cls): + def run_in_child(cls, start_method): import json - r, w = multiprocessing.Pipe(duplex=False) - p = multiprocessing.Process(target=cls.run_in_grandchild, args=(w,)) - p.start() + mp = multiprocessing.get_context(start_method) + r, w = mp.Pipe(duplex=False) + p = mp.Process(target=cls.run_in_grandchild, args=(w,)) + with warnings.catch_warnings(category=DeprecationWarning): + p.start() grandchild_flags = r.recv() p.join() r.close() @@ -4982,8 +4985,10 @@ class TestFlags(unittest.TestCase): def test_flags(self): import json # start child process using unusual flags - prog = ('from test._test_multiprocessing import TestFlags; ' + - 'TestFlags.run_in_child()') + prog = ( + 'from test._test_multiprocessing import TestFlags; ' + f'TestFlags.run_in_child({multiprocessing.get_start_method()!r})' + ) data = subprocess.check_output( [sys.executable, '-E', '-S', '-O', '-c', prog]) child_flags, grandchild_flags = json.loads(data.decode('ascii')) diff --git a/Lib/test/_test_venv_multiprocessing.py b/Lib/test/_test_venv_multiprocessing.py index af72e91..044a0c6 100644 --- a/Lib/test/_test_venv_multiprocessing.py +++ b/Lib/test/_test_venv_multiprocessing.py @@ -30,6 +30,7 @@ def test_func(): def main(): + multiprocessing.set_start_method('spawn') test_pool = multiprocessing.Process(target=test_func) test_pool.start() test_pool.join() diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 214544b..b906905 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -4,6 +4,7 @@ import collections.abc import concurrent.futures import functools import io +import multiprocessing import os import platform import re @@ -2762,7 +2763,13 @@ class GetEventLoopTestsMixin: support.skip_if_broken_multiprocessing_synchronize() async def main(): - pool = concurrent.futures.ProcessPoolExecutor() + if multiprocessing.get_start_method() == 'fork': + # Avoid 'fork' DeprecationWarning. + mp_context = multiprocessing.get_context('forkserver') + else: + mp_context = None + pool = concurrent.futures.ProcessPoolExecutor( + mp_context=mp_context) result = await self.loop.run_in_executor( pool, _test_get_event_loop_new_process__sub_proc) pool.shutdown() diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index b3520ae..4493cd3 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -18,6 +18,7 @@ import sys import threading import time import unittest +import warnings import weakref from pickle import PicklingError @@ -571,6 +572,24 @@ class ProcessPoolShutdownTest(ExecutorShutdownTest): assert all([r == abs(v) for r, v in zip(res, range(-5, 5))]) +@unittest.skipIf(mp.get_all_start_methods()[0] != "fork", "non-fork default.") +class ProcessPoolExecutorDefaultForkWarning(unittest.TestCase): + def test_fork_default_warns(self): + with self.assertWarns(mp.context.DefaultForkDeprecationWarning): + with futures.ProcessPoolExecutor(2): + pass + + def test_explicit_fork_does_not_warn(self): + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter("ignore") + warnings.filterwarnings( + 'always', category=mp.context.DefaultForkDeprecationWarning) + ctx = mp.get_context("fork") # Non-default fork context. + with futures.ProcessPoolExecutor(2, mp_context=ctx): + pass + self.assertEqual(len(ws), 0, msg=[str(x) for x in ws]) + + create_executor_tests(ProcessPoolShutdownTest, executor_mixins=(ProcessPoolForkMixin, ProcessPoolForkserverMixin, diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index fc8c393..113c780 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -1,11 +1,11 @@ """Test program for the fcntl C module. """ +import multiprocessing import platform import os import struct import sys import unittest -from multiprocessing import Process from test.support import verbose, cpython_only from test.support.import_helper import import_module from test.support.os_helper import TESTFN, unlink @@ -160,7 +160,8 @@ class TestFcntl(unittest.TestCase): self.f = open(TESTFN, 'wb+') cmd = fcntl.LOCK_EX | fcntl.LOCK_NB fcntl.lockf(self.f, cmd) - p = Process(target=try_lockf_on_other_process_fail, args=(TESTFN, cmd)) + mp = multiprocessing.get_context('spawn') + p = mp.Process(target=try_lockf_on_other_process_fail, args=(TESTFN, cmd)) p.start() p.join() fcntl.lockf(self.f, fcntl.LOCK_UN) @@ -171,7 +172,8 @@ class TestFcntl(unittest.TestCase): self.f = open(TESTFN, 'wb+') cmd = fcntl.LOCK_SH | fcntl.LOCK_NB fcntl.lockf(self.f, cmd) - p = Process(target=try_lockf_on_other_process, args=(TESTFN, cmd)) + mp = multiprocessing.get_context('spawn') + p = mp.Process(target=try_lockf_on_other_process, args=(TESTFN, cmd)) p.start() p.join() fcntl.lockf(self.f, fcntl.LOCK_UN) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 072056d..8a12d57 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -4759,8 +4759,9 @@ class LogRecordTest(BaseTest): # In other processes, processName is correct when multiprocessing in imported, # but it is (incorrectly) defaulted to 'MainProcess' otherwise (bpo-38762). import multiprocessing - parent_conn, child_conn = multiprocessing.Pipe() - p = multiprocessing.Process( + mp = multiprocessing.get_context('spawn') + parent_conn, child_conn = mp.Pipe() + p = mp.Process( target=self._extract_logrecord_process_name, args=(2, LOG_MULTI_PROCESSING, child_conn,) ) diff --git a/Lib/test/test_multiprocessing_defaults.py b/Lib/test/test_multiprocessing_defaults.py new file mode 100644 index 0000000..1da4c06 --- /dev/null +++ b/Lib/test/test_multiprocessing_defaults.py @@ -0,0 +1,82 @@ +"""Test default behavior of multiprocessing.""" + +from inspect import currentframe, getframeinfo +import multiprocessing +from multiprocessing.context import DefaultForkDeprecationWarning +import sys +from test.support import threading_helper +import unittest +import warnings + + +def do_nothing(): + pass + + +# Process has the same API as Thread so this helper works. +join_process = threading_helper.join_thread + + +class DefaultWarningsTest(unittest.TestCase): + + @unittest.skipIf(sys.platform in ('win32', 'darwin'), + 'The default is not "fork" on Windows or macOS.') + def setUp(self): + self.assertEqual(multiprocessing.get_start_method(), 'fork') + self.assertIsInstance(multiprocessing.get_context(), + multiprocessing.context._DefaultForkContext) + + def test_default_fork_start_method_warning_process(self): + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter('ignore') + warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) + process = multiprocessing.Process(target=do_nothing) + process.start() # warning should point here. + join_process(process) + self.assertIsInstance(ws[0].message, DefaultForkDeprecationWarning) + self.assertIn(__file__, ws[0].filename) + self.assertEqual(getframeinfo(currentframe()).lineno-4, ws[0].lineno) + self.assertIn("'fork'", str(ws[0].message)) + self.assertIn("get_context", str(ws[0].message)) + self.assertEqual(len(ws), 1, msg=[str(x) for x in ws]) + + def test_default_fork_start_method_warning_pool(self): + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter('ignore') + warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) + pool = multiprocessing.Pool(1) # warning should point here. + pool.terminate() + pool.join() + self.assertIsInstance(ws[0].message, DefaultForkDeprecationWarning) + self.assertIn(__file__, ws[0].filename) + self.assertEqual(getframeinfo(currentframe()).lineno-5, ws[0].lineno) + self.assertIn("'fork'", str(ws[0].message)) + self.assertIn("get_context", str(ws[0].message)) + self.assertEqual(len(ws), 1, msg=[str(x) for x in ws]) + + def test_default_fork_start_method_warning_manager(self): + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter('ignore') + warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) + manager = multiprocessing.Manager() # warning should point here. + manager.shutdown() + self.assertIsInstance(ws[0].message, DefaultForkDeprecationWarning) + self.assertIn(__file__, ws[0].filename) + self.assertEqual(getframeinfo(currentframe()).lineno-4, ws[0].lineno) + self.assertIn("'fork'", str(ws[0].message)) + self.assertIn("get_context", str(ws[0].message)) + self.assertEqual(len(ws), 1, msg=[str(x) for x in ws]) + + def test_no_mp_warning_when_using_explicit_fork_context(self): + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter('ignore') + warnings.filterwarnings('always', category=DefaultForkDeprecationWarning) + fork_mp = multiprocessing.get_context('fork') + pool = fork_mp.Pool(1) + pool.terminate() + pool.join() + self.assertEqual(len(ws), 0, msg=[str(x) for x in ws]) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py index 44fdca7..80e7a4d 100644 --- a/Lib/test/test_pickle.py +++ b/Lib/test/test_pickle.py @@ -533,6 +533,8 @@ class CompatPickleTests(unittest.TestCase): def test_multiprocessing_exceptions(self): module = import_helper.import_module('multiprocessing.context') for name, exc in get_exceptions(module): + if issubclass(exc, Warning): + continue with self.subTest(name): self.assertEqual(reverse_mapping('multiprocessing.context', name), ('multiprocessing', name)) diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 11628a2..eacb1a7 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -2431,7 +2431,8 @@ class ReTests(unittest.TestCase): input_js = '''a(function() { /////////////////////////////////////////////////////////////////// });''' - p = multiprocessing.Process(target=pattern.sub, args=('', input_js)) + mp = multiprocessing.get_context('spawn') + p = mp.Process(target=pattern.sub, args=('', input_js)) p.start() p.join(SHORT_TIMEOUT) try: |