| 
									
										
										
										
											2019-11-13 19:08:50 -08:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  | import signal | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2015-07-31 17:49:43 +02:00
										 |  |  | import warnings | 
					
						
							| 
									
										
										
										
											2014-11-25 17:20:33 +01:00
										 |  |  | from unittest import mock | 
					
						
							| 
									
										
										
										
											2014-12-18 12:29:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import asyncio | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | from asyncio import base_subprocess | 
					
						
							| 
									
										
										
										
											2014-12-18 12:29:53 +01:00
										 |  |  | from asyncio import subprocess | 
					
						
							| 
									
										
										
										
											2017-12-11 10:04:40 -05:00
										 |  |  | from test.test_asyncio import utils as test_utils | 
					
						
							|  |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2020-06-25 20:15:40 +08:00
										 |  |  | from test.support import os_helper | 
					
						
							| 
									
										
										
										
											2017-12-11 10:04:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-26 21:16:42 +01:00
										 |  |  | if sys.platform != 'win32': | 
					
						
							|  |  |  |     from asyncio import unix_events | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Program blocking | 
					
						
							|  |  |  | PROGRAM_BLOCKED = [sys.executable, '-c', 'import time; time.sleep(3600)'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Program copying input to output | 
					
						
							|  |  |  | PROGRAM_CAT = [ | 
					
						
							|  |  |  |     sys.executable, '-c', | 
					
						
							|  |  |  |     ';'.join(('import sys', | 
					
						
							|  |  |  |               'data = sys.stdin.buffer.read()', | 
					
						
							|  |  |  |               'sys.stdout.buffer.write(data)'))] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 20:34:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | def tearDownModule(): | 
					
						
							|  |  |  |     asyncio.set_event_loop_policy(None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | class TestSubprocessTransport(base_subprocess.BaseSubprocessTransport): | 
					
						
							|  |  |  |     def _start(self, *args, **kwargs): | 
					
						
							|  |  |  |         self._proc = mock.Mock() | 
					
						
							|  |  |  |         self._proc.stdin = None | 
					
						
							|  |  |  |         self._proc.stdout = None | 
					
						
							|  |  |  |         self._proc.stderr = None | 
					
						
							| 
									
										
										
										
											2018-05-20 19:57:13 +02:00
										 |  |  |         self._proc.pid = -1 | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SubprocessTransportTests(test_utils.TestCase): | 
					
						
							|  |  |  |     def setUp(self): | 
					
						
							| 
									
										
										
										
											2016-11-04 14:29:28 -04:00
										 |  |  |         super().setUp() | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |         self.loop = self.new_test_loop() | 
					
						
							|  |  |  |         self.set_event_loop(self.loop) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_transport(self, waiter=None): | 
					
						
							|  |  |  |         protocol = mock.Mock() | 
					
						
							|  |  |  |         protocol.connection_made._is_coroutine = False | 
					
						
							|  |  |  |         protocol.process_exited._is_coroutine = False | 
					
						
							|  |  |  |         transport = TestSubprocessTransport( | 
					
						
							|  |  |  |                         self.loop, protocol, ['test'], False, | 
					
						
							|  |  |  |                         None, None, None, 0, waiter=waiter) | 
					
						
							|  |  |  |         return (transport, protocol) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_proc_exited(self): | 
					
						
							| 
									
										
										
										
											2019-09-11 16:07:37 +03:00
										 |  |  |         waiter = self.loop.create_future() | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |         transport, protocol = self.create_transport(waiter) | 
					
						
							|  |  |  |         transport._process_exited(6) | 
					
						
							|  |  |  |         self.loop.run_until_complete(waiter) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(transport.get_returncode(), 6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(protocol.connection_made.called) | 
					
						
							|  |  |  |         self.assertTrue(protocol.process_exited.called) | 
					
						
							|  |  |  |         self.assertTrue(protocol.connection_lost.called) | 
					
						
							|  |  |  |         self.assertEqual(protocol.connection_lost.call_args[0], (None,)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-16 12:43:21 -05:00
										 |  |  |         self.assertFalse(transport.is_closing()) | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |         self.assertIsNone(transport._loop) | 
					
						
							|  |  |  |         self.assertIsNone(transport._proc) | 
					
						
							|  |  |  |         self.assertIsNone(transport._protocol) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # methods must raise ProcessLookupError if the process exited | 
					
						
							|  |  |  |         self.assertRaises(ProcessLookupError, | 
					
						
							|  |  |  |                           transport.send_signal, signal.SIGTERM) | 
					
						
							|  |  |  |         self.assertRaises(ProcessLookupError, transport.terminate) | 
					
						
							|  |  |  |         self.assertRaises(ProcessLookupError, transport.kill) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-30 00:11:42 +01:00
										 |  |  |         transport.close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-20 19:57:13 +02:00
										 |  |  |     def test_subprocess_repr(self): | 
					
						
							| 
									
										
										
										
											2019-09-11 16:07:37 +03:00
										 |  |  |         waiter = self.loop.create_future() | 
					
						
							| 
									
										
										
										
											2018-05-20 19:57:13 +02:00
										 |  |  |         transport, protocol = self.create_transport(waiter) | 
					
						
							|  |  |  |         transport._process_exited(6) | 
					
						
							|  |  |  |         self.loop.run_until_complete(waiter) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             repr(transport), | 
					
						
							|  |  |  |             "<TestSubprocessTransport pid=-1 returncode=6>" | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         transport._returncode = None | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             repr(transport), | 
					
						
							|  |  |  |             "<TestSubprocessTransport pid=-1 running>" | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         transport._pid = None | 
					
						
							|  |  |  |         transport._returncode = None | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             repr(transport), | 
					
						
							|  |  |  |             "<TestSubprocessTransport not started>" | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         transport.close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  | class SubprocessMixin: | 
					
						
							| 
									
										
										
										
											2014-02-18 22:56:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |     def test_stdin_stdout(self): | 
					
						
							|  |  |  |         args = PROGRAM_CAT | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def run(data): | 
					
						
							|  |  |  |             proc = await asyncio.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |                 *args, | 
					
						
							|  |  |  |                 stdin=subprocess.PIPE, | 
					
						
							|  |  |  |                 stdout=subprocess.PIPE, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # feed data | 
					
						
							|  |  |  |             proc.stdin.write(data) | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             await proc.stdin.drain() | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |             proc.stdin.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # get output and exitcode | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             data = await proc.stdout.read() | 
					
						
							|  |  |  |             exitcode = await proc.wait() | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |             return (exitcode, data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         task = run(b'some data') | 
					
						
							| 
									
										
										
										
											2018-10-02 13:53:06 -04:00
										 |  |  |         task = asyncio.wait_for(task, 60.0) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         exitcode, stdout = self.loop.run_until_complete(task) | 
					
						
							|  |  |  |         self.assertEqual(exitcode, 0) | 
					
						
							|  |  |  |         self.assertEqual(stdout, b'some data') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_communicate(self): | 
					
						
							|  |  |  |         args = PROGRAM_CAT | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def run(data): | 
					
						
							|  |  |  |             proc = await asyncio.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |                 *args, | 
					
						
							|  |  |  |                 stdin=subprocess.PIPE, | 
					
						
							|  |  |  |                 stdout=subprocess.PIPE, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             stdout, stderr = await proc.communicate(data) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |             return proc.returncode, stdout | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         task = run(b'some data') | 
					
						
							| 
									
										
										
										
											2019-10-30 16:00:44 +01:00
										 |  |  |         task = asyncio.wait_for(task, support.LONG_TIMEOUT) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         exitcode, stdout = self.loop.run_until_complete(task) | 
					
						
							|  |  |  |         self.assertEqual(exitcode, 0) | 
					
						
							|  |  |  |         self.assertEqual(stdout, b'some data') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_shell(self): | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |         proc = self.loop.run_until_complete( | 
					
						
							|  |  |  |             asyncio.create_subprocess_shell('exit 7') | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         exitcode = self.loop.run_until_complete(proc.wait()) | 
					
						
							|  |  |  |         self.assertEqual(exitcode, 7) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_start_new_session(self): | 
					
						
							|  |  |  |         # start the new process in a new session | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |         proc = self.loop.run_until_complete( | 
					
						
							|  |  |  |             asyncio.create_subprocess_shell( | 
					
						
							|  |  |  |                 'exit 8', | 
					
						
							|  |  |  |                 start_new_session=True, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         exitcode = self.loop.run_until_complete(proc.wait()) | 
					
						
							|  |  |  |         self.assertEqual(exitcode, 8) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_kill(self): | 
					
						
							|  |  |  |         args = PROGRAM_BLOCKED | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |         proc = self.loop.run_until_complete( | 
					
						
							|  |  |  |             asyncio.create_subprocess_exec(*args) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         proc.kill() | 
					
						
							|  |  |  |         returncode = self.loop.run_until_complete(proc.wait()) | 
					
						
							|  |  |  |         if sys.platform == 'win32': | 
					
						
							|  |  |  |             self.assertIsInstance(returncode, int) | 
					
						
							|  |  |  |             # expect 1 but sometimes get 0 | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.assertEqual(-signal.SIGKILL, returncode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_terminate(self): | 
					
						
							|  |  |  |         args = PROGRAM_BLOCKED | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |         proc = self.loop.run_until_complete( | 
					
						
							|  |  |  |             asyncio.create_subprocess_exec(*args) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         proc.terminate() | 
					
						
							|  |  |  |         returncode = self.loop.run_until_complete(proc.wait()) | 
					
						
							|  |  |  |         if sys.platform == 'win32': | 
					
						
							|  |  |  |             self.assertIsInstance(returncode, int) | 
					
						
							|  |  |  |             # expect 1 but sometimes get 0 | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.assertEqual(-signal.SIGTERM, returncode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") | 
					
						
							|  |  |  |     def test_send_signal(self): | 
					
						
							| 
									
										
										
										
											2017-07-25 19:19:09 +02:00
										 |  |  |         # bpo-31034: Make sure that we get the default signal handler (killing | 
					
						
							|  |  |  |         # the process). The parent process may have decided to ignore SIGHUP, | 
					
						
							|  |  |  |         # and signal handlers are inherited. | 
					
						
							|  |  |  |         old_handler = signal.signal(signal.SIGHUP, signal.SIG_DFL) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             code = 'import time; print("sleeping", flush=True); time.sleep(3600)' | 
					
						
							|  |  |  |             args = [sys.executable, '-c', code] | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |             proc = self.loop.run_until_complete( | 
					
						
							|  |  |  |                 asyncio.create_subprocess_exec( | 
					
						
							|  |  |  |                     *args, | 
					
						
							|  |  |  |                     stdout=subprocess.PIPE, | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-07-25 19:19:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             async def send_signal(proc): | 
					
						
							| 
									
										
										
										
											2017-07-25 19:19:09 +02:00
										 |  |  |                 # basic synchronization to wait until the program is sleeping | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |                 line = await proc.stdout.readline() | 
					
						
							| 
									
										
										
										
											2017-07-25 19:19:09 +02:00
										 |  |  |                 self.assertEqual(line, b'sleeping\n') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 proc.send_signal(signal.SIGHUP) | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |                 returncode = await proc.wait() | 
					
						
							| 
									
										
										
										
											2017-07-25 19:19:09 +02:00
										 |  |  |                 return returncode | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             returncode = self.loop.run_until_complete(send_signal(proc)) | 
					
						
							|  |  |  |             self.assertEqual(-signal.SIGHUP, returncode) | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             signal.signal(signal.SIGHUP, old_handler) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-17 12:25:27 +02:00
										 |  |  |     def prepare_broken_pipe_test(self): | 
					
						
							|  |  |  |         # buffer large enough to feed the whole pipe buffer | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         large_data = b'x' * support.PIPE_MAX_SIZE | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-17 12:25:27 +02:00
										 |  |  |         # the program ends before the stdin can be feeded | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |         proc = self.loop.run_until_complete( | 
					
						
							|  |  |  |             asyncio.create_subprocess_exec( | 
					
						
							|  |  |  |                 sys.executable, '-c', 'pass', | 
					
						
							|  |  |  |                 stdin=subprocess.PIPE, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-17 12:25:27 +02:00
										 |  |  |         return (proc, large_data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_stdin_broken_pipe(self): | 
					
						
							|  |  |  |         proc, large_data = self.prepare_broken_pipe_test() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def write_stdin(proc, data): | 
					
						
							| 
									
										
										
										
											2018-10-02 13:53:06 -04:00
										 |  |  |             await asyncio.sleep(0.5) | 
					
						
							| 
									
										
										
										
											2014-07-21 16:23:33 +02:00
										 |  |  |             proc.stdin.write(data) | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             await proc.stdin.drain() | 
					
						
							| 
									
										
										
										
											2014-07-21 16:23:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         coro = write_stdin(proc, large_data) | 
					
						
							| 
									
										
										
										
											2014-07-17 14:01:14 +02:00
										 |  |  |         # drain() must raise BrokenPipeError or ConnectionResetError | 
					
						
							| 
									
										
										
										
											2014-08-25 23:20:52 +02:00
										 |  |  |         with test_utils.disable_logger(): | 
					
						
							|  |  |  |             self.assertRaises((BrokenPipeError, ConnectionResetError), | 
					
						
							|  |  |  |                               self.loop.run_until_complete, coro) | 
					
						
							| 
									
										
										
										
											2014-07-17 12:25:27 +02:00
										 |  |  |         self.loop.run_until_complete(proc.wait()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_communicate_ignore_broken_pipe(self): | 
					
						
							|  |  |  |         proc, large_data = self.prepare_broken_pipe_test() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # communicate() must ignore BrokenPipeError when feeding stdin | 
					
						
							| 
									
										
										
										
											2019-06-24 19:47:28 +03:00
										 |  |  |         self.loop.set_exception_handler(lambda loop, msg: None) | 
					
						
							|  |  |  |         self.loop.run_until_complete(proc.communicate(large_data)) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         self.loop.run_until_complete(proc.wait()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-25 17:20:33 +01:00
										 |  |  |     def test_pause_reading(self): | 
					
						
							| 
									
										
										
										
											2014-11-28 18:02:03 +01:00
										 |  |  |         limit = 10 | 
					
						
							|  |  |  |         size = (limit * 2 + 1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def test_pause_reading(): | 
					
						
							| 
									
										
										
										
											2014-11-25 17:20:33 +01:00
										 |  |  |             code = '\n'.join(( | 
					
						
							|  |  |  |                 'import sys', | 
					
						
							| 
									
										
										
										
											2014-11-28 18:02:03 +01:00
										 |  |  |                 'sys.stdout.write("x" * %s)' % size, | 
					
						
							| 
									
										
										
										
											2014-11-25 17:20:33 +01:00
										 |  |  |                 'sys.stdout.flush()', | 
					
						
							|  |  |  |             )) | 
					
						
							| 
									
										
										
										
											2015-01-15 22:52:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             connect_read_pipe = self.loop.connect_read_pipe | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             async def connect_read_pipe_mock(*args, **kw): | 
					
						
							|  |  |  |                 transport, protocol = await connect_read_pipe(*args, **kw) | 
					
						
							| 
									
										
										
										
											2015-01-15 22:52:59 +01:00
										 |  |  |                 transport.pause_reading = mock.Mock() | 
					
						
							|  |  |  |                 transport.resume_reading = mock.Mock() | 
					
						
							|  |  |  |                 return (transport, protocol) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.loop.connect_read_pipe = connect_read_pipe_mock | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             proc = await asyncio.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |                 sys.executable, '-c', code, | 
					
						
							|  |  |  |                 stdin=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 stdout=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 limit=limit, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2014-11-25 17:20:33 +01:00
										 |  |  |             stdout_transport = proc._transport.get_pipe_transport(1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             stdout, stderr = await proc.communicate() | 
					
						
							| 
									
										
										
										
											2014-11-25 17:20:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # The child process produced more than limit bytes of output, | 
					
						
							|  |  |  |             # the stream reader transport should pause the protocol to not | 
					
						
							|  |  |  |             # allocate too much memory. | 
					
						
							| 
									
										
										
										
											2014-11-28 18:02:03 +01:00
										 |  |  |             return (stdout, stdout_transport) | 
					
						
							| 
									
										
										
										
											2014-11-25 17:20:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Issue #22685: Ensure that the stream reader pauses the protocol | 
					
						
							|  |  |  |         # when the child process produces too much data | 
					
						
							| 
									
										
										
										
											2014-11-28 18:02:03 +01:00
										 |  |  |         stdout, transport = self.loop.run_until_complete(test_pause_reading()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(stdout, b'x' * size) | 
					
						
							|  |  |  |         self.assertTrue(transport.pause_reading.called) | 
					
						
							| 
									
										
										
										
											2014-12-04 23:06:13 +01:00
										 |  |  |         self.assertTrue(transport.resume_reading.called) | 
					
						
							| 
									
										
										
										
											2014-11-25 17:20:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-11 23:30:17 +01:00
										 |  |  |     def test_stdin_not_inheritable(self): | 
					
						
							| 
									
										
										
										
											2015-07-09 23:13:50 +02:00
										 |  |  |         # asyncio issue #209: stdin must not be inheritable, otherwise | 
					
						
							| 
									
										
										
										
											2014-12-11 23:30:17 +01:00
										 |  |  |         # the Process.communicate() hangs | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def len_message(message): | 
					
						
							| 
									
										
										
										
											2014-12-11 23:30:17 +01:00
										 |  |  |             code = 'import sys; data = sys.stdin.read(); print(len(data))' | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             proc = await asyncio.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |                 sys.executable, '-c', code, | 
					
						
							|  |  |  |                 stdin=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 stdout=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 stderr=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 close_fds=False, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             stdout, stderr = await proc.communicate(message) | 
					
						
							|  |  |  |             exitcode = await proc.wait() | 
					
						
							| 
									
										
										
										
											2014-12-11 23:30:17 +01:00
										 |  |  |             return (stdout, exitcode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         output, exitcode = self.loop.run_until_complete(len_message(b'abc')) | 
					
						
							|  |  |  |         self.assertEqual(output.rstrip(), b'3') | 
					
						
							|  |  |  |         self.assertEqual(exitcode, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-13 15:35:28 -04:00
										 |  |  |     def test_empty_input(self): | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         async def empty_input(): | 
					
						
							| 
									
										
										
										
											2016-05-13 15:35:28 -04:00
										 |  |  |             code = 'import sys; data = sys.stdin.read(); print(len(data))' | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             proc = await asyncio.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |                 sys.executable, '-c', code, | 
					
						
							|  |  |  |                 stdin=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 stdout=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 stderr=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 close_fds=False, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             stdout, stderr = await proc.communicate(b'') | 
					
						
							|  |  |  |             exitcode = await proc.wait() | 
					
						
							| 
									
										
										
										
											2016-05-13 15:35:28 -04:00
										 |  |  |             return (stdout, exitcode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         output, exitcode = self.loop.run_until_complete(empty_input()) | 
					
						
							|  |  |  |         self.assertEqual(output.rstrip(), b'0') | 
					
						
							|  |  |  |         self.assertEqual(exitcode, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-27 19:51:19 -04:00
										 |  |  |     def test_devnull_input(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def empty_input(): | 
					
						
							|  |  |  |             code = 'import sys; data = sys.stdin.read(); print(len(data))' | 
					
						
							|  |  |  |             proc = await asyncio.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |                 sys.executable, '-c', code, | 
					
						
							|  |  |  |                 stdin=asyncio.subprocess.DEVNULL, | 
					
						
							|  |  |  |                 stdout=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 stderr=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 close_fds=False, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2019-05-27 19:51:19 -04:00
										 |  |  |             stdout, stderr = await proc.communicate() | 
					
						
							|  |  |  |             exitcode = await proc.wait() | 
					
						
							|  |  |  |             return (stdout, exitcode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         output, exitcode = self.loop.run_until_complete(empty_input()) | 
					
						
							|  |  |  |         self.assertEqual(output.rstrip(), b'0') | 
					
						
							|  |  |  |         self.assertEqual(exitcode, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_devnull_output(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def empty_output(): | 
					
						
							|  |  |  |             code = 'import sys; data = sys.stdin.read(); print(len(data))' | 
					
						
							|  |  |  |             proc = await asyncio.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |                 sys.executable, '-c', code, | 
					
						
							|  |  |  |                 stdin=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 stdout=asyncio.subprocess.DEVNULL, | 
					
						
							|  |  |  |                 stderr=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 close_fds=False, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2019-05-27 19:51:19 -04:00
										 |  |  |             stdout, stderr = await proc.communicate(b"abc") | 
					
						
							|  |  |  |             exitcode = await proc.wait() | 
					
						
							|  |  |  |             return (stdout, exitcode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         output, exitcode = self.loop.run_until_complete(empty_output()) | 
					
						
							|  |  |  |         self.assertEqual(output, None) | 
					
						
							|  |  |  |         self.assertEqual(exitcode, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_devnull_error(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def empty_error(): | 
					
						
							|  |  |  |             code = 'import sys; data = sys.stdin.read(); print(len(data))' | 
					
						
							|  |  |  |             proc = await asyncio.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |                 sys.executable, '-c', code, | 
					
						
							|  |  |  |                 stdin=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 stdout=asyncio.subprocess.PIPE, | 
					
						
							|  |  |  |                 stderr=asyncio.subprocess.DEVNULL, | 
					
						
							|  |  |  |                 close_fds=False, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2019-05-27 19:51:19 -04:00
										 |  |  |             stdout, stderr = await proc.communicate(b"abc") | 
					
						
							|  |  |  |             exitcode = await proc.wait() | 
					
						
							|  |  |  |             return (stderr, exitcode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         output, exitcode = self.loop.run_until_complete(empty_error()) | 
					
						
							|  |  |  |         self.assertEqual(output, None) | 
					
						
							|  |  |  |         self.assertEqual(exitcode, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 01:13:49 +01:00
										 |  |  |     def test_cancel_process_wait(self): | 
					
						
							|  |  |  |         # Issue #23140: cancel Process.wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def cancel_wait(): | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |             proc = await asyncio.create_subprocess_exec(*PROGRAM_BLOCKED) | 
					
						
							| 
									
										
										
										
											2015-01-06 01:13:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # Create an internal future waiting on the process exit | 
					
						
							| 
									
										
										
										
											2015-01-06 01:22:45 +01:00
										 |  |  |             task = self.loop.create_task(proc.wait()) | 
					
						
							|  |  |  |             self.loop.call_soon(task.cancel) | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |                 await task | 
					
						
							| 
									
										
										
										
											2015-01-06 01:22:45 +01:00
										 |  |  |             except asyncio.CancelledError: | 
					
						
							|  |  |  |                 pass | 
					
						
							| 
									
										
										
										
											2015-01-06 01:13:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # Cancel the future | 
					
						
							|  |  |  |             task.cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Kill the process and wait until it is done | 
					
						
							|  |  |  |             proc.kill() | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             await proc.wait() | 
					
						
							| 
									
										
										
										
											2015-01-06 01:13:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.loop.run_until_complete(cancel_wait()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |     def test_cancel_make_subprocess_transport_exec(self): | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         async def cancel_make_transport(): | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |             coro = asyncio.create_subprocess_exec(*PROGRAM_BLOCKED) | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |             task = self.loop.create_task(coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.loop.call_soon(task.cancel) | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |                 await task | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |             except asyncio.CancelledError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # ignore the log: | 
					
						
							|  |  |  |         # "Exception during subprocess creation, kill the subprocess" | 
					
						
							|  |  |  |         with test_utils.disable_logger(): | 
					
						
							|  |  |  |             self.loop.run_until_complete(cancel_make_transport()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_cancel_post_init(self): | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         async def cancel_make_transport(): | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |             coro = self.loop.subprocess_exec(asyncio.SubprocessProtocol, | 
					
						
							|  |  |  |                                              *PROGRAM_BLOCKED) | 
					
						
							|  |  |  |             task = self.loop.create_task(coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.loop.call_soon(task.cancel) | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |                 await task | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |             except asyncio.CancelledError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # ignore the log: | 
					
						
							|  |  |  |         # "Exception during subprocess creation, kill the subprocess" | 
					
						
							|  |  |  |         with test_utils.disable_logger(): | 
					
						
							|  |  |  |             self.loop.run_until_complete(cancel_make_transport()) | 
					
						
							| 
									
										
										
										
											2015-01-15 14:24:55 +01:00
										 |  |  |             test_utils.run_briefly(self.loop) | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-10 14:49:32 +01:00
										 |  |  |     def test_close_kill_running(self): | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         async def kill_running(): | 
					
						
							| 
									
										
										
										
											2015-02-10 14:49:32 +01:00
										 |  |  |             create = self.loop.subprocess_exec(asyncio.SubprocessProtocol, | 
					
						
							|  |  |  |                                                *PROGRAM_BLOCKED) | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             transport, protocol = await create | 
					
						
							| 
									
										
										
										
											2015-02-17 22:54:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             kill_called = False | 
					
						
							|  |  |  |             def kill(): | 
					
						
							|  |  |  |                 nonlocal kill_called | 
					
						
							|  |  |  |                 kill_called = True | 
					
						
							|  |  |  |                 orig_kill() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-10 14:49:32 +01:00
										 |  |  |             proc = transport.get_extra_info('subprocess') | 
					
						
							| 
									
										
										
										
											2015-02-17 22:54:11 +01:00
										 |  |  |             orig_kill = proc.kill | 
					
						
							|  |  |  |             proc.kill = kill | 
					
						
							| 
									
										
										
										
											2015-02-10 14:49:32 +01:00
										 |  |  |             returncode = transport.get_returncode() | 
					
						
							|  |  |  |             transport.close() | 
					
						
							| 
									
										
										
										
											2020-02-27 00:15:12 +02:00
										 |  |  |             await asyncio.wait_for(transport._wait(), 5) | 
					
						
							| 
									
										
										
										
											2015-02-17 22:54:11 +01:00
										 |  |  |             return (returncode, kill_called) | 
					
						
							| 
									
										
										
										
											2015-02-10 14:49:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Ignore "Close running child process: kill ..." log | 
					
						
							|  |  |  |         with test_utils.disable_logger(): | 
					
						
							| 
									
										
										
										
											2020-02-27 00:15:12 +02:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 returncode, killed = self.loop.run_until_complete( | 
					
						
							|  |  |  |                     kill_running() | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             except asyncio.TimeoutError: | 
					
						
							|  |  |  |                 self.skipTest( | 
					
						
							|  |  |  |                     "Timeout failure on waiting for subprocess stopping" | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2015-02-10 14:49:32 +01:00
										 |  |  |         self.assertIsNone(returncode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # transport.close() must kill the process if it is still running | 
					
						
							|  |  |  |         self.assertTrue(killed) | 
					
						
							|  |  |  |         test_utils.run_briefly(self.loop) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_close_dont_kill_finished(self): | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         async def kill_running(): | 
					
						
							| 
									
										
										
										
											2015-02-10 14:49:32 +01:00
										 |  |  |             create = self.loop.subprocess_exec(asyncio.SubprocessProtocol, | 
					
						
							|  |  |  |                                                *PROGRAM_BLOCKED) | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |             transport, protocol = await create | 
					
						
							| 
									
										
										
										
											2015-02-10 14:49:32 +01:00
										 |  |  |             proc = transport.get_extra_info('subprocess') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-26 05:35:26 +00:00
										 |  |  |             # kill the process (but asyncio is not notified immediately) | 
					
						
							| 
									
										
										
										
											2015-02-10 14:49:32 +01:00
										 |  |  |             proc.kill() | 
					
						
							|  |  |  |             proc.wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             proc.kill = mock.Mock() | 
					
						
							|  |  |  |             proc_returncode = proc.poll() | 
					
						
							|  |  |  |             transport_returncode = transport.get_returncode() | 
					
						
							|  |  |  |             transport.close() | 
					
						
							|  |  |  |             return (proc_returncode, transport_returncode, proc.kill.called) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Ignore "Unknown child process pid ..." log of SafeChildWatcher, | 
					
						
							|  |  |  |         # emitted because the test already consumes the exit status: | 
					
						
							|  |  |  |         # proc.wait() | 
					
						
							|  |  |  |         with test_utils.disable_logger(): | 
					
						
							|  |  |  |             result = self.loop.run_until_complete(kill_running()) | 
					
						
							|  |  |  |             test_utils.run_briefly(self.loop) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         proc_returncode, transport_return_code, killed = result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertIsNotNone(proc_returncode) | 
					
						
							|  |  |  |         self.assertIsNone(transport_return_code) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # transport.close() must not kill the process if it finished, even if | 
					
						
							|  |  |  |         # the transport was not notified yet | 
					
						
							|  |  |  |         self.assertFalse(killed) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 16:57:12 -04:00
										 |  |  |         # Unlike SafeChildWatcher, FastChildWatcher does not pop the | 
					
						
							|  |  |  |         # callbacks if waitpid() is called elsewhere. Let's clear them | 
					
						
							|  |  |  |         # manually to avoid a warning when the watcher is detached. | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         if (sys.platform != 'win32' and | 
					
						
							|  |  |  |                 isinstance(self, SubprocessFastWatcherTests)): | 
					
						
							| 
									
										
										
										
											2016-10-05 16:57:12 -04:00
										 |  |  |             asyncio.get_child_watcher()._callbacks.clear() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |     async def _test_popen_error(self, stdin): | 
					
						
							| 
									
										
										
										
											2015-08-09 18:21:25 -04:00
										 |  |  |         if sys.platform == 'win32': | 
					
						
							|  |  |  |             target = 'asyncio.windows_utils.Popen' | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             target = 'subprocess.Popen' | 
					
						
							|  |  |  |         with mock.patch(target) as popen: | 
					
						
							| 
									
										
										
										
											2015-07-31 17:49:43 +02:00
										 |  |  |             exc = ZeroDivisionError | 
					
						
							|  |  |  |             popen.side_effect = exc | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-02 10:37:59 -05:00
										 |  |  |             with warnings.catch_warnings(record=True) as warns: | 
					
						
							| 
									
										
										
										
											2015-07-31 17:49:43 +02:00
										 |  |  |                 with self.assertRaises(exc): | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |                     await asyncio.create_subprocess_exec( | 
					
						
							|  |  |  |                         sys.executable, | 
					
						
							|  |  |  |                         '-c', | 
					
						
							|  |  |  |                         'pass', | 
					
						
							|  |  |  |                         stdin=stdin | 
					
						
							|  |  |  |                     ) | 
					
						
							| 
									
										
										
										
											2016-03-02 10:37:59 -05:00
										 |  |  |                 self.assertEqual(warns, []) | 
					
						
							| 
									
										
										
										
											2015-07-31 17:49:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-20 14:02:17 +02:00
										 |  |  |     def test_popen_error(self): | 
					
						
							|  |  |  |         # Issue #24763: check that the subprocess transport is closed | 
					
						
							|  |  |  |         # when BaseSubprocessTransport fails | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |         self.loop.run_until_complete(self._test_popen_error(stdin=None)) | 
					
						
							| 
									
										
										
										
											2019-05-20 14:02:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_popen_error_with_stdin_pipe(self): | 
					
						
							|  |  |  |         # Issue #35721: check that newly created socket pair is closed when | 
					
						
							|  |  |  |         # Popen fails | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |         self.loop.run_until_complete( | 
					
						
							|  |  |  |             self._test_popen_error(stdin=subprocess.PIPE)) | 
					
						
							| 
									
										
										
										
											2019-05-20 14:02:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 22:21:18 -06:00
										 |  |  |     def test_read_stdout_after_process_exit(self): | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         async def execute(): | 
					
						
							| 
									
										
										
										
											2017-03-02 22:21:18 -06:00
										 |  |  |             code = '\n'.join(['import sys', | 
					
						
							|  |  |  |                               'for _ in range(64):', | 
					
						
							|  |  |  |                               '    sys.stdout.write("x" * 4096)', | 
					
						
							|  |  |  |                               'sys.stdout.flush()', | 
					
						
							|  |  |  |                               'sys.exit(1)']) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |             process = await asyncio.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2017-03-02 23:25:31 -05:00
										 |  |  |                 sys.executable, '-c', code, | 
					
						
							|  |  |  |                 stdout=asyncio.subprocess.PIPE, | 
					
						
							| 
									
										
										
										
											2019-09-12 15:40:40 +03:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-03-02 23:25:31 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 22:21:18 -06:00
										 |  |  |             while True: | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |                 data = await process.stdout.read(65536) | 
					
						
							| 
									
										
										
										
											2017-03-02 22:21:18 -06:00
										 |  |  |                 if data: | 
					
						
							| 
									
										
										
										
											2018-10-02 13:53:06 -04:00
										 |  |  |                     await asyncio.sleep(0.3) | 
					
						
							| 
									
										
										
										
											2017-03-02 22:21:18 -06:00
										 |  |  |                 else: | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.loop.run_until_complete(execute()) | 
					
						
							| 
									
										
										
										
											2017-03-02 23:25:31 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-27 19:51:19 -04:00
										 |  |  |     def test_create_subprocess_exec_text_mode_fails(self): | 
					
						
							|  |  |  |         async def execute(): | 
					
						
							|  |  |  |             with self.assertRaises(ValueError): | 
					
						
							|  |  |  |                 await subprocess.create_subprocess_exec(sys.executable, | 
					
						
							|  |  |  |                                                         text=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             with self.assertRaises(ValueError): | 
					
						
							|  |  |  |                 await subprocess.create_subprocess_exec(sys.executable, | 
					
						
							|  |  |  |                                                         encoding="utf-8") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             with self.assertRaises(ValueError): | 
					
						
							|  |  |  |                 await subprocess.create_subprocess_exec(sys.executable, | 
					
						
							|  |  |  |                                                         errors="strict") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.loop.run_until_complete(execute()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_create_subprocess_shell_text_mode_fails(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def execute(): | 
					
						
							|  |  |  |             with self.assertRaises(ValueError): | 
					
						
							|  |  |  |                 await subprocess.create_subprocess_shell(sys.executable, | 
					
						
							|  |  |  |                                                          text=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             with self.assertRaises(ValueError): | 
					
						
							|  |  |  |                 await subprocess.create_subprocess_shell(sys.executable, | 
					
						
							|  |  |  |                                                          encoding="utf-8") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             with self.assertRaises(ValueError): | 
					
						
							|  |  |  |                 await subprocess.create_subprocess_shell(sys.executable, | 
					
						
							|  |  |  |                                                          errors="strict") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.loop.run_until_complete(execute()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-29 14:50:59 +08:00
										 |  |  |     def test_create_subprocess_exec_with_path(self): | 
					
						
							|  |  |  |         async def execute(): | 
					
						
							|  |  |  |             p = await subprocess.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2020-06-25 20:15:40 +08:00
										 |  |  |                 os_helper.FakePath(sys.executable), '-c', 'pass') | 
					
						
							| 
									
										
										
										
											2019-05-29 14:50:59 +08:00
										 |  |  |             await p.wait() | 
					
						
							|  |  |  |             p = await subprocess.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2020-06-25 20:15:40 +08:00
										 |  |  |                 sys.executable, '-c', 'pass', os_helper.FakePath('.')) | 
					
						
							| 
									
										
										
										
											2019-05-29 14:50:59 +08:00
										 |  |  |             await p.wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertIsNone(self.loop.run_until_complete(execute())) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-30 12:54:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  | if sys.platform != 'win32': | 
					
						
							|  |  |  |     # Unix | 
					
						
							|  |  |  |     class SubprocessWatcherMixin(SubprocessMixin): | 
					
						
							| 
									
										
										
										
											2014-02-18 22:56:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         Watcher = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def setUp(self): | 
					
						
							| 
									
										
										
										
											2016-11-04 14:29:28 -04:00
										 |  |  |             super().setUp() | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |             policy = asyncio.get_event_loop_policy() | 
					
						
							|  |  |  |             self.loop = policy.new_event_loop() | 
					
						
							| 
									
										
										
										
											2014-12-26 21:07:52 +01:00
										 |  |  |             self.set_event_loop(self.loop) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             watcher = self.Watcher() | 
					
						
							|  |  |  |             watcher.attach_loop(self.loop) | 
					
						
							|  |  |  |             policy.set_child_watcher(watcher) | 
					
						
							| 
									
										
										
										
											2019-06-30 12:54:59 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def tearDown(self): | 
					
						
							|  |  |  |             super().tearDown() | 
					
						
							|  |  |  |             policy = asyncio.get_event_loop_policy() | 
					
						
							|  |  |  |             watcher = policy.get_child_watcher() | 
					
						
							|  |  |  |             policy.set_child_watcher(None) | 
					
						
							|  |  |  |             watcher.attach_loop(None) | 
					
						
							|  |  |  |             watcher.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class SubprocessThreadedWatcherTests(SubprocessWatcherMixin, | 
					
						
							|  |  |  |                                          test_utils.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Watcher = unix_events.ThreadedChildWatcher | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class SubprocessMultiLoopWatcherTests(SubprocessWatcherMixin, | 
					
						
							|  |  |  |                                           test_utils.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Watcher = unix_events.MultiLoopChildWatcher | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 22:56:15 -05:00
										 |  |  |     class SubprocessSafeWatcherTests(SubprocessWatcherMixin, | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  |                                      test_utils.TestCase): | 
					
						
							| 
									
										
										
										
											2014-02-18 22:56:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         Watcher = unix_events.SafeChildWatcher | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 22:56:15 -05:00
										 |  |  |     class SubprocessFastWatcherTests(SubprocessWatcherMixin, | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  |                                      test_utils.TestCase): | 
					
						
							| 
									
										
										
										
											2014-02-18 22:56:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         Watcher = unix_events.FastChildWatcher | 
					
						
							| 
									
										
										
										
											2014-02-18 22:56:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-13 19:08:50 -08:00
										 |  |  |     def has_pidfd_support(): | 
					
						
							|  |  |  |         if not hasattr(os, 'pidfd_open'): | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             os.close(os.pidfd_open(os.getpid())) | 
					
						
							|  |  |  |         except OSError: | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @unittest.skipUnless( | 
					
						
							|  |  |  |         has_pidfd_support(), | 
					
						
							|  |  |  |         "operating system does not support pidfds", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     class SubprocessPidfdWatcherTests(SubprocessWatcherMixin, | 
					
						
							|  |  |  |                                       test_utils.TestCase): | 
					
						
							|  |  |  |         Watcher = unix_events.PidfdChildWatcher | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  | else: | 
					
						
							|  |  |  |     # Windows | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  |     class SubprocessProactorTests(SubprocessMixin, test_utils.TestCase): | 
					
						
							| 
									
										
										
										
											2014-02-18 22:56:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |         def setUp(self): | 
					
						
							| 
									
										
										
										
											2016-11-04 14:29:28 -04:00
										 |  |  |             super().setUp() | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |             self.loop = asyncio.ProactorEventLoop() | 
					
						
							| 
									
										
										
										
											2014-12-26 21:07:52 +01:00
										 |  |  |             self.set_event_loop(self.loop) | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-30 12:54:59 +03:00
										 |  |  | class GenericWatcherTests: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_create_subprocess_fails_with_inactive_watcher(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def execute(): | 
					
						
							|  |  |  |             watcher = mock.create_authspec(asyncio.AbstractChildWatcher) | 
					
						
							|  |  |  |             watcher.is_active.return_value = False | 
					
						
							|  |  |  |             asyncio.set_child_watcher(watcher) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             with self.assertRaises(RuntimeError): | 
					
						
							|  |  |  |                 await subprocess.create_subprocess_exec( | 
					
						
							| 
									
										
										
										
											2020-06-25 20:15:40 +08:00
										 |  |  |                     os_helper.FakePath(sys.executable), '-c', 'pass') | 
					
						
							| 
									
										
										
										
											2019-06-30 12:54:59 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |             watcher.add_child_handler.assert_not_called() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertIsNone(self.loop.run_until_complete(execute())) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     unittest.main() |