xref: /aosp_15_r20/external/pytorch/test/test_multiprocessing_spawn.py (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1*da0073e9SAndroid Build Coastguard Worker# Owner(s): ["module: multiprocessing"]
2*da0073e9SAndroid Build Coastguard Worker
3*da0073e9SAndroid Build Coastguard Workerimport os
4*da0073e9SAndroid Build Coastguard Workerimport pickle
5*da0073e9SAndroid Build Coastguard Workerimport random
6*da0073e9SAndroid Build Coastguard Workerimport signal
7*da0073e9SAndroid Build Coastguard Workerimport sys
8*da0073e9SAndroid Build Coastguard Workerimport time
9*da0073e9SAndroid Build Coastguard Workerimport unittest
10*da0073e9SAndroid Build Coastguard Worker
11*da0073e9SAndroid Build Coastguard Workerimport torch.multiprocessing as mp
12*da0073e9SAndroid Build Coastguard Worker
13*da0073e9SAndroid Build Coastguard Workerfrom torch.testing._internal.common_utils import (
14*da0073e9SAndroid Build Coastguard Worker    IS_WINDOWS,
15*da0073e9SAndroid Build Coastguard Worker    NO_MULTIPROCESSING_SPAWN,
16*da0073e9SAndroid Build Coastguard Worker    run_tests,
17*da0073e9SAndroid Build Coastguard Worker    TestCase,
18*da0073e9SAndroid Build Coastguard Worker)
19*da0073e9SAndroid Build Coastguard Worker
20*da0073e9SAndroid Build Coastguard Workerdef _test_success_func(i):
21*da0073e9SAndroid Build Coastguard Worker    pass
22*da0073e9SAndroid Build Coastguard Worker
23*da0073e9SAndroid Build Coastguard Worker
24*da0073e9SAndroid Build Coastguard Workerdef _test_success_single_arg_func(i, arg):
25*da0073e9SAndroid Build Coastguard Worker    if arg:
26*da0073e9SAndroid Build Coastguard Worker        arg.put(i)
27*da0073e9SAndroid Build Coastguard Worker
28*da0073e9SAndroid Build Coastguard Worker
29*da0073e9SAndroid Build Coastguard Workerdef _test_exception_single_func(i, arg):
30*da0073e9SAndroid Build Coastguard Worker    if i == arg:
31*da0073e9SAndroid Build Coastguard Worker        raise ValueError("legitimate exception from process %d" % i)
32*da0073e9SAndroid Build Coastguard Worker    time.sleep(1.0)
33*da0073e9SAndroid Build Coastguard Worker
34*da0073e9SAndroid Build Coastguard Worker
35*da0073e9SAndroid Build Coastguard Workerdef _test_exception_all_func(i):
36*da0073e9SAndroid Build Coastguard Worker    time.sleep(random.random() / 10)
37*da0073e9SAndroid Build Coastguard Worker    raise ValueError("legitimate exception from process %d" % i)
38*da0073e9SAndroid Build Coastguard Worker
39*da0073e9SAndroid Build Coastguard Worker
40*da0073e9SAndroid Build Coastguard Workerdef _test_terminate_signal_func(i):
41*da0073e9SAndroid Build Coastguard Worker    if i == 0:
42*da0073e9SAndroid Build Coastguard Worker        os.kill(os.getpid(), signal.SIGABRT)
43*da0073e9SAndroid Build Coastguard Worker    time.sleep(1.0)
44*da0073e9SAndroid Build Coastguard Worker
45*da0073e9SAndroid Build Coastguard Worker
46*da0073e9SAndroid Build Coastguard Workerdef _test_terminate_exit_func(i, arg):
47*da0073e9SAndroid Build Coastguard Worker    if i == 0:
48*da0073e9SAndroid Build Coastguard Worker        sys.exit(arg)
49*da0073e9SAndroid Build Coastguard Worker    time.sleep(1.0)
50*da0073e9SAndroid Build Coastguard Worker
51*da0073e9SAndroid Build Coastguard Worker
52*da0073e9SAndroid Build Coastguard Workerdef _test_success_first_then_exception_func(i, arg):
53*da0073e9SAndroid Build Coastguard Worker    if i == 0:
54*da0073e9SAndroid Build Coastguard Worker        return
55*da0073e9SAndroid Build Coastguard Worker    time.sleep(0.1)
56*da0073e9SAndroid Build Coastguard Worker    raise ValueError("legitimate exception")
57*da0073e9SAndroid Build Coastguard Worker
58*da0073e9SAndroid Build Coastguard Worker
59*da0073e9SAndroid Build Coastguard Workerdef _test_nested_child_body(i, ready_queue, nested_child_sleep):
60*da0073e9SAndroid Build Coastguard Worker    ready_queue.put(None)
61*da0073e9SAndroid Build Coastguard Worker    time.sleep(nested_child_sleep)
62*da0073e9SAndroid Build Coastguard Worker
63*da0073e9SAndroid Build Coastguard Worker
64*da0073e9SAndroid Build Coastguard Workerdef _test_infinite_task(i):
65*da0073e9SAndroid Build Coastguard Worker    while True:
66*da0073e9SAndroid Build Coastguard Worker        time.sleep(1)
67*da0073e9SAndroid Build Coastguard Worker
68*da0073e9SAndroid Build Coastguard Worker
69*da0073e9SAndroid Build Coastguard Workerdef _test_process_exit(idx):
70*da0073e9SAndroid Build Coastguard Worker    sys.exit(12)
71*da0073e9SAndroid Build Coastguard Worker
72*da0073e9SAndroid Build Coastguard Worker
73*da0073e9SAndroid Build Coastguard Workerdef _test_nested(i, pids_queue, nested_child_sleep, start_method):
74*da0073e9SAndroid Build Coastguard Worker    context = mp.get_context(start_method)
75*da0073e9SAndroid Build Coastguard Worker    nested_child_ready_queue = context.Queue()
76*da0073e9SAndroid Build Coastguard Worker    nprocs = 2
77*da0073e9SAndroid Build Coastguard Worker    mp_context = mp.start_processes(
78*da0073e9SAndroid Build Coastguard Worker        fn=_test_nested_child_body,
79*da0073e9SAndroid Build Coastguard Worker        args=(nested_child_ready_queue, nested_child_sleep),
80*da0073e9SAndroid Build Coastguard Worker        nprocs=nprocs,
81*da0073e9SAndroid Build Coastguard Worker        join=False,
82*da0073e9SAndroid Build Coastguard Worker        daemon=False,
83*da0073e9SAndroid Build Coastguard Worker        start_method=start_method,
84*da0073e9SAndroid Build Coastguard Worker    )
85*da0073e9SAndroid Build Coastguard Worker    pids_queue.put(mp_context.pids())
86*da0073e9SAndroid Build Coastguard Worker
87*da0073e9SAndroid Build Coastguard Worker    # Wait for both children to have started, to ensure that they
88*da0073e9SAndroid Build Coastguard Worker    # have called prctl(2) to register a parent death signal.
89*da0073e9SAndroid Build Coastguard Worker    for _ in range(nprocs):
90*da0073e9SAndroid Build Coastguard Worker        nested_child_ready_queue.get()
91*da0073e9SAndroid Build Coastguard Worker
92*da0073e9SAndroid Build Coastguard Worker    # Kill self. This should take down the child processes as well.
93*da0073e9SAndroid Build Coastguard Worker    os.kill(os.getpid(), signal.SIGTERM)
94*da0073e9SAndroid Build Coastguard Worker
95*da0073e9SAndroid Build Coastguard Workerclass _TestMultiProcessing:
96*da0073e9SAndroid Build Coastguard Worker    start_method = None
97*da0073e9SAndroid Build Coastguard Worker
98*da0073e9SAndroid Build Coastguard Worker    def test_success(self):
99*da0073e9SAndroid Build Coastguard Worker        mp.start_processes(_test_success_func, nprocs=2, start_method=self.start_method)
100*da0073e9SAndroid Build Coastguard Worker
101*da0073e9SAndroid Build Coastguard Worker    def test_success_non_blocking(self):
102*da0073e9SAndroid Build Coastguard Worker        mp_context = mp.start_processes(_test_success_func, nprocs=2, join=False, start_method=self.start_method)
103*da0073e9SAndroid Build Coastguard Worker
104*da0073e9SAndroid Build Coastguard Worker        # After all processes (nproc=2) have joined it must return True
105*da0073e9SAndroid Build Coastguard Worker        mp_context.join(timeout=None)
106*da0073e9SAndroid Build Coastguard Worker        mp_context.join(timeout=None)
107*da0073e9SAndroid Build Coastguard Worker        self.assertTrue(mp_context.join(timeout=None))
108*da0073e9SAndroid Build Coastguard Worker
109*da0073e9SAndroid Build Coastguard Worker    def test_first_argument_index(self):
110*da0073e9SAndroid Build Coastguard Worker        context = mp.get_context(self.start_method)
111*da0073e9SAndroid Build Coastguard Worker        queue = context.SimpleQueue()
112*da0073e9SAndroid Build Coastguard Worker        mp.start_processes(_test_success_single_arg_func, args=(queue,), nprocs=2, start_method=self.start_method)
113*da0073e9SAndroid Build Coastguard Worker        self.assertEqual([0, 1], sorted([queue.get(), queue.get()]))
114*da0073e9SAndroid Build Coastguard Worker
115*da0073e9SAndroid Build Coastguard Worker    def test_exception_single(self):
116*da0073e9SAndroid Build Coastguard Worker        nprocs = 2
117*da0073e9SAndroid Build Coastguard Worker        for i in range(nprocs):
118*da0073e9SAndroid Build Coastguard Worker            with self.assertRaisesRegex(
119*da0073e9SAndroid Build Coastguard Worker                Exception,
120*da0073e9SAndroid Build Coastguard Worker                "\nValueError: legitimate exception from process %d$" % i,
121*da0073e9SAndroid Build Coastguard Worker            ):
122*da0073e9SAndroid Build Coastguard Worker                mp.start_processes(_test_exception_single_func, args=(i,), nprocs=nprocs, start_method=self.start_method)
123*da0073e9SAndroid Build Coastguard Worker
124*da0073e9SAndroid Build Coastguard Worker    def test_exception_all(self):
125*da0073e9SAndroid Build Coastguard Worker        with self.assertRaisesRegex(
126*da0073e9SAndroid Build Coastguard Worker            Exception,
127*da0073e9SAndroid Build Coastguard Worker            "\nValueError: legitimate exception from process (0|1)$",
128*da0073e9SAndroid Build Coastguard Worker        ):
129*da0073e9SAndroid Build Coastguard Worker            mp.start_processes(_test_exception_all_func, nprocs=2, start_method=self.start_method)
130*da0073e9SAndroid Build Coastguard Worker
131*da0073e9SAndroid Build Coastguard Worker    def test_terminate_signal(self):
132*da0073e9SAndroid Build Coastguard Worker        # SIGABRT is aliased with SIGIOT
133*da0073e9SAndroid Build Coastguard Worker        message = "process 0 terminated with signal (SIGABRT|SIGIOT)"
134*da0073e9SAndroid Build Coastguard Worker
135*da0073e9SAndroid Build Coastguard Worker        # Termination through with signal is expressed as a negative exit code
136*da0073e9SAndroid Build Coastguard Worker        # in multiprocessing, so we know it was a signal that caused the exit.
137*da0073e9SAndroid Build Coastguard Worker        # This doesn't appear to exist on Windows, where the exit code is always
138*da0073e9SAndroid Build Coastguard Worker        # positive, and therefore results in a different exception message.
139*da0073e9SAndroid Build Coastguard Worker        # Exit code 22 means "ERROR_BAD_COMMAND".
140*da0073e9SAndroid Build Coastguard Worker        if IS_WINDOWS:
141*da0073e9SAndroid Build Coastguard Worker            message = "process 0 terminated with exit code 22"
142*da0073e9SAndroid Build Coastguard Worker
143*da0073e9SAndroid Build Coastguard Worker        with self.assertRaisesRegex(Exception, message):
144*da0073e9SAndroid Build Coastguard Worker            mp.start_processes(_test_terminate_signal_func, nprocs=2, start_method=self.start_method)
145*da0073e9SAndroid Build Coastguard Worker
146*da0073e9SAndroid Build Coastguard Worker    def test_terminate_exit(self):
147*da0073e9SAndroid Build Coastguard Worker        exitcode = 123
148*da0073e9SAndroid Build Coastguard Worker        with self.assertRaisesRegex(
149*da0073e9SAndroid Build Coastguard Worker            Exception,
150*da0073e9SAndroid Build Coastguard Worker            "process 0 terminated with exit code %d" % exitcode,
151*da0073e9SAndroid Build Coastguard Worker        ):
152*da0073e9SAndroid Build Coastguard Worker            mp.start_processes(_test_terminate_exit_func, args=(exitcode,), nprocs=2, start_method=self.start_method)
153*da0073e9SAndroid Build Coastguard Worker
154*da0073e9SAndroid Build Coastguard Worker    def test_success_first_then_exception(self):
155*da0073e9SAndroid Build Coastguard Worker        exitcode = 123
156*da0073e9SAndroid Build Coastguard Worker        with self.assertRaisesRegex(
157*da0073e9SAndroid Build Coastguard Worker            Exception,
158*da0073e9SAndroid Build Coastguard Worker            "ValueError: legitimate exception",
159*da0073e9SAndroid Build Coastguard Worker        ):
160*da0073e9SAndroid Build Coastguard Worker            mp.start_processes(_test_success_first_then_exception_func, args=(exitcode,), nprocs=2, start_method=self.start_method)
161*da0073e9SAndroid Build Coastguard Worker
162*da0073e9SAndroid Build Coastguard Worker    @unittest.skipIf(
163*da0073e9SAndroid Build Coastguard Worker        sys.platform != "linux",
164*da0073e9SAndroid Build Coastguard Worker        "Only runs on Linux; requires prctl(2)",
165*da0073e9SAndroid Build Coastguard Worker    )
166*da0073e9SAndroid Build Coastguard Worker    def _test_nested(self):
167*da0073e9SAndroid Build Coastguard Worker        context = mp.get_context(self.start_method)
168*da0073e9SAndroid Build Coastguard Worker        pids_queue = context.Queue()
169*da0073e9SAndroid Build Coastguard Worker        nested_child_sleep = 20.0
170*da0073e9SAndroid Build Coastguard Worker        mp_context = mp.start_processes(
171*da0073e9SAndroid Build Coastguard Worker            fn=_test_nested,
172*da0073e9SAndroid Build Coastguard Worker            args=(pids_queue, nested_child_sleep, self.start_method),
173*da0073e9SAndroid Build Coastguard Worker            nprocs=1,
174*da0073e9SAndroid Build Coastguard Worker            join=False,
175*da0073e9SAndroid Build Coastguard Worker            daemon=False,
176*da0073e9SAndroid Build Coastguard Worker            start_method=self.start_method,
177*da0073e9SAndroid Build Coastguard Worker        )
178*da0073e9SAndroid Build Coastguard Worker
179*da0073e9SAndroid Build Coastguard Worker        # Wait for nested children to terminate in time
180*da0073e9SAndroid Build Coastguard Worker        pids = pids_queue.get()
181*da0073e9SAndroid Build Coastguard Worker        start = time.time()
182*da0073e9SAndroid Build Coastguard Worker        while len(pids) > 0:
183*da0073e9SAndroid Build Coastguard Worker            for pid in pids:
184*da0073e9SAndroid Build Coastguard Worker                try:
185*da0073e9SAndroid Build Coastguard Worker                    os.kill(pid, 0)
186*da0073e9SAndroid Build Coastguard Worker                except ProcessLookupError:
187*da0073e9SAndroid Build Coastguard Worker                    pids.remove(pid)
188*da0073e9SAndroid Build Coastguard Worker                    break
189*da0073e9SAndroid Build Coastguard Worker
190*da0073e9SAndroid Build Coastguard Worker            # This assert fails if any nested child process is still
191*da0073e9SAndroid Build Coastguard Worker            # alive after (nested_child_sleep / 2) seconds. By
192*da0073e9SAndroid Build Coastguard Worker            # extension, this test times out with an assertion error
193*da0073e9SAndroid Build Coastguard Worker            # after (nested_child_sleep / 2) seconds.
194*da0073e9SAndroid Build Coastguard Worker            self.assertLess(time.time() - start, nested_child_sleep / 2)
195*da0073e9SAndroid Build Coastguard Worker            time.sleep(0.1)
196*da0073e9SAndroid Build Coastguard Worker
197*da0073e9SAndroid Build Coastguard Worker@unittest.skipIf(
198*da0073e9SAndroid Build Coastguard Worker    NO_MULTIPROCESSING_SPAWN,
199*da0073e9SAndroid Build Coastguard Worker    "Disabled for environments that don't support the spawn start method")
200*da0073e9SAndroid Build Coastguard Workerclass SpawnTest(TestCase, _TestMultiProcessing):
201*da0073e9SAndroid Build Coastguard Worker    start_method = 'spawn'
202*da0073e9SAndroid Build Coastguard Worker
203*da0073e9SAndroid Build Coastguard Worker    def test_exception_raises(self):
204*da0073e9SAndroid Build Coastguard Worker        with self.assertRaises(mp.ProcessRaisedException):
205*da0073e9SAndroid Build Coastguard Worker            mp.spawn(_test_success_first_then_exception_func, args=(), nprocs=1)
206*da0073e9SAndroid Build Coastguard Worker
207*da0073e9SAndroid Build Coastguard Worker    def test_signal_raises(self):
208*da0073e9SAndroid Build Coastguard Worker        context = mp.spawn(_test_infinite_task, args=(), nprocs=1, join=False)
209*da0073e9SAndroid Build Coastguard Worker        for pid in context.pids():
210*da0073e9SAndroid Build Coastguard Worker            os.kill(pid, signal.SIGTERM)
211*da0073e9SAndroid Build Coastguard Worker        with self.assertRaises(mp.ProcessExitedException):
212*da0073e9SAndroid Build Coastguard Worker            context.join()
213*da0073e9SAndroid Build Coastguard Worker
214*da0073e9SAndroid Build Coastguard Worker    def _test_process_exited(self):
215*da0073e9SAndroid Build Coastguard Worker        with self.assertRaises(mp.ProcessExitedException) as e:
216*da0073e9SAndroid Build Coastguard Worker            mp.spawn(_test_process_exit, args=(), nprocs=1)
217*da0073e9SAndroid Build Coastguard Worker            self.assertEqual(12, e.exit_code)
218*da0073e9SAndroid Build Coastguard Worker
219*da0073e9SAndroid Build Coastguard Worker
220*da0073e9SAndroid Build Coastguard Worker@unittest.skipIf(
221*da0073e9SAndroid Build Coastguard Worker    IS_WINDOWS,
222*da0073e9SAndroid Build Coastguard Worker    "Fork is only available on Unix",
223*da0073e9SAndroid Build Coastguard Worker)
224*da0073e9SAndroid Build Coastguard Workerclass ForkTest(TestCase, _TestMultiProcessing):
225*da0073e9SAndroid Build Coastguard Worker    start_method = 'fork'
226*da0073e9SAndroid Build Coastguard Worker
227*da0073e9SAndroid Build Coastguard Worker
228*da0073e9SAndroid Build Coastguard Worker@unittest.skipIf(
229*da0073e9SAndroid Build Coastguard Worker    IS_WINDOWS,
230*da0073e9SAndroid Build Coastguard Worker    "Fork is only available on Unix",
231*da0073e9SAndroid Build Coastguard Worker)
232*da0073e9SAndroid Build Coastguard Workerclass ParallelForkServerShouldWorkTest(TestCase, _TestMultiProcessing):
233*da0073e9SAndroid Build Coastguard Worker    orig_paralell_env_val = None
234*da0073e9SAndroid Build Coastguard Worker
235*da0073e9SAndroid Build Coastguard Worker    def setUp(self):
236*da0073e9SAndroid Build Coastguard Worker        super().setUp()
237*da0073e9SAndroid Build Coastguard Worker        self.orig_paralell_env_val = os.environ.get(mp.ENV_VAR_PARALLEL_START)
238*da0073e9SAndroid Build Coastguard Worker        os.environ[mp.ENV_VAR_PARALLEL_START] = "1"
239*da0073e9SAndroid Build Coastguard Worker
240*da0073e9SAndroid Build Coastguard Worker    def tearDown(self):
241*da0073e9SAndroid Build Coastguard Worker        super().tearDown()
242*da0073e9SAndroid Build Coastguard Worker        if self.orig_paralell_env_val is None:
243*da0073e9SAndroid Build Coastguard Worker            del os.environ[mp.ENV_VAR_PARALLEL_START]
244*da0073e9SAndroid Build Coastguard Worker        else:
245*da0073e9SAndroid Build Coastguard Worker            os.environ[mp.ENV_VAR_PARALLEL_START] = self.orig_paralell_env_val
246*da0073e9SAndroid Build Coastguard Worker
247*da0073e9SAndroid Build Coastguard Worker
248*da0073e9SAndroid Build Coastguard Worker@unittest.skipIf(
249*da0073e9SAndroid Build Coastguard Worker    IS_WINDOWS,
250*da0073e9SAndroid Build Coastguard Worker    "Fork is only available on Unix",
251*da0073e9SAndroid Build Coastguard Worker)
252*da0073e9SAndroid Build Coastguard Workerclass ParallelForkServerPerfTest(TestCase):
253*da0073e9SAndroid Build Coastguard Worker
254*da0073e9SAndroid Build Coastguard Worker    def test_forkserver_perf(self):
255*da0073e9SAndroid Build Coastguard Worker
256*da0073e9SAndroid Build Coastguard Worker        start_method = 'forkserver'
257*da0073e9SAndroid Build Coastguard Worker        expensive = Expensive()
258*da0073e9SAndroid Build Coastguard Worker        nprocs = 4
259*da0073e9SAndroid Build Coastguard Worker        orig_paralell_env_val = os.environ.get(mp.ENV_VAR_PARALLEL_START)
260*da0073e9SAndroid Build Coastguard Worker
261*da0073e9SAndroid Build Coastguard Worker        # test the non parallel case
262*da0073e9SAndroid Build Coastguard Worker        os.environ[mp.ENV_VAR_PARALLEL_START] = "0"
263*da0073e9SAndroid Build Coastguard Worker        start = time.perf_counter()
264*da0073e9SAndroid Build Coastguard Worker        mp.start_processes(expensive.my_call, nprocs=nprocs, start_method=start_method)
265*da0073e9SAndroid Build Coastguard Worker        elapsed = time.perf_counter() - start
266*da0073e9SAndroid Build Coastguard Worker        # the elapsed time should be at least {nprocs}x the sleep time
267*da0073e9SAndroid Build Coastguard Worker        self.assertGreaterEqual(elapsed, Expensive.SLEEP_SECS * nprocs)
268*da0073e9SAndroid Build Coastguard Worker
269*da0073e9SAndroid Build Coastguard Worker        # test the parallel case
270*da0073e9SAndroid Build Coastguard Worker        os.environ[mp.ENV_VAR_PARALLEL_START] = "1"
271*da0073e9SAndroid Build Coastguard Worker        start = time.perf_counter()
272*da0073e9SAndroid Build Coastguard Worker        mp.start_processes(expensive.my_call, nprocs=nprocs, start_method=start_method)
273*da0073e9SAndroid Build Coastguard Worker        elapsed = time.perf_counter() - start
274*da0073e9SAndroid Build Coastguard Worker        # the elapsed time should be less than {nprocs}x the sleep time
275*da0073e9SAndroid Build Coastguard Worker        self.assertLess(elapsed, Expensive.SLEEP_SECS * nprocs)
276*da0073e9SAndroid Build Coastguard Worker
277*da0073e9SAndroid Build Coastguard Worker        if orig_paralell_env_val is None:
278*da0073e9SAndroid Build Coastguard Worker            del os.environ[mp.ENV_VAR_PARALLEL_START]
279*da0073e9SAndroid Build Coastguard Worker        else:
280*da0073e9SAndroid Build Coastguard Worker            os.environ[mp.ENV_VAR_PARALLEL_START] = orig_paralell_env_val
281*da0073e9SAndroid Build Coastguard Worker
282*da0073e9SAndroid Build Coastguard Worker
283*da0073e9SAndroid Build Coastguard Workerclass Expensive:
284*da0073e9SAndroid Build Coastguard Worker    SLEEP_SECS = 5
285*da0073e9SAndroid Build Coastguard Worker    # Simulate startup overhead such as large imports
286*da0073e9SAndroid Build Coastguard Worker    time.sleep(SLEEP_SECS)
287*da0073e9SAndroid Build Coastguard Worker
288*da0073e9SAndroid Build Coastguard Worker    def __init__(self):
289*da0073e9SAndroid Build Coastguard Worker        self.config: str = "*" * 1000000
290*da0073e9SAndroid Build Coastguard Worker
291*da0073e9SAndroid Build Coastguard Worker    def my_call(self, *args):
292*da0073e9SAndroid Build Coastguard Worker        pass
293*da0073e9SAndroid Build Coastguard Worker
294*da0073e9SAndroid Build Coastguard Worker
295*da0073e9SAndroid Build Coastguard Workerclass ErrorTest(TestCase):
296*da0073e9SAndroid Build Coastguard Worker    def test_errors_pickleable(self):
297*da0073e9SAndroid Build Coastguard Worker        for error in (
298*da0073e9SAndroid Build Coastguard Worker            mp.ProcessRaisedException("Oh no!", 1, 1),
299*da0073e9SAndroid Build Coastguard Worker            mp.ProcessExitedException("Oh no!", 1, 1, 1),
300*da0073e9SAndroid Build Coastguard Worker        ):
301*da0073e9SAndroid Build Coastguard Worker            pickle.loads(pickle.dumps(error))
302*da0073e9SAndroid Build Coastguard Worker
303*da0073e9SAndroid Build Coastguard Worker
304*da0073e9SAndroid Build Coastguard Workerif __name__ == '__main__':
305*da0073e9SAndroid Build Coastguard Worker    run_tests()
306