From d9d044b2067238e386961d9cc1785a774fc6faa1 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Mon, 12 Dec 2022 11:37:28 +0000 Subject: [PATCH 1/4] add tests --- Lib/test/test_asyncio/test_subprocess.py | 81 ++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 7411f735da3be6..639b9e40ed3f67 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -686,6 +686,87 @@ async def execute(): self.assertIsNone(self.loop.run_until_complete(execute())) + def test_create_subprocess_env_shell(self) -> None: + async def main() -> None: + cmd = f'''{sys.executable} -c "import os; print(os.getenv('FOO'))"''' + env = {"FOO": 'bar'} + proc = await asyncio.create_subprocess_shell( + cmd, env=env, stdout=subprocess.PIPE + ) + stdout, _ = await proc.communicate() + self.assertEqual(stdout, b"bar\n") + self.assertEqual(proc.returncode, 0) + task = asyncio.create_task(proc.wait()) + await asyncio.sleep(0) + self.assertEqual(task.result(), proc.returncode) + + self.loop.run_until_complete(main()) + + def test_create_subprocess_env_exec(self) -> None: + async def main() -> None: + cmd = [sys.executable, "-c", + "import os; print(os.getenv('FOO'))"] + env = {"FOO": 'bar'} + proc = await asyncio.create_subprocess_exec( + *cmd, env=env, stdout=subprocess.PIPE + ) + stdout, _ = await proc.communicate() + self.assertEqual(stdout, b"bar\n") + self.assertEqual(proc.returncode, 0) + task = asyncio.create_task(proc.wait()) + await asyncio.sleep(0) + self.assertEqual(task.result(), proc.returncode) + + self.loop.run_until_complete(main()) + + def test_subprocess_concurrent_wait(self) -> None: + async def main() -> None: + proc = await asyncio.create_subprocess_exec( + *PROGRAM_CAT, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + stdout, _ = await proc.communicate(b'some data') + self.assertEqual(stdout, b"some data") + self.assertEqual(proc.returncode, 0) + self.assertEqual(await asyncio.gather(*[proc.wait() for _ in range(10)]), + [proc.returncode] * 10) + + self.loop.run_until_complete(main()) + + def test_subprocess_consistent_callbacks(self): + events = [] + class Protocol(asyncio.SubprocessProtocol): + def __init__(self, exit_future: asyncio.Future) -> None: + self.exit_future = exit_future + + def pipe_data_received(self, fd, data) -> None: + events.append(('pipe_data_received', fd, data)) + + def pipe_connection_lost(self, fd, exc) -> None: + events.append('pipe_connection_lost') + + def process_exited(self) -> None: + events.append('process_exited') + self.exit_future.set_result(True) + + async def main() -> None: + loop = asyncio.get_running_loop() + exit_future = asyncio.Future() + code = 'import sys; sys.stdout.write("stdout"); sys.stderr.write("stderr")' + transport, _ = await loop.subprocess_exec(lambda: Protocol(exit_future), sys.executable, '-c', code, + stdin=None) + await exit_future + transport.close() + self.assertEqual(len(events), 5, events) + self.assertEqual(events[0], ('pipe_data_received', 1, b'stdout')) + self.assertEqual(events[1], ('pipe_data_received', 2, b'stderr')) + self.assertEqual(events[2], 'pipe_connection_lost') + self.assertEqual(events[3], 'pipe_connection_lost') + self.assertEqual(events[4], 'process_exited') + + self.loop.run_until_complete(main()) + if sys.platform != 'win32': # Unix From 1d96bf75e78d83e995516bd4871691686328968e Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Mon, 12 Dec 2022 12:13:28 +0000 Subject: [PATCH 2/4] fix tests on windows --- Lib/test/test_asyncio/test_subprocess.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 639b9e40ed3f67..89de7f94a2cfec 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -688,13 +688,13 @@ async def execute(): def test_create_subprocess_env_shell(self) -> None: async def main() -> None: - cmd = f'''{sys.executable} -c "import os; print(os.getenv('FOO'))"''' + cmd = f'''{sys.executable} -c "import os, sys; sys.stdout.write(os.getenv('FOO'))"''' env = {"FOO": 'bar'} proc = await asyncio.create_subprocess_shell( cmd, env=env, stdout=subprocess.PIPE ) stdout, _ = await proc.communicate() - self.assertEqual(stdout, b"bar\n") + self.assertEqual(stdout, b"bar") self.assertEqual(proc.returncode, 0) task = asyncio.create_task(proc.wait()) await asyncio.sleep(0) @@ -705,13 +705,13 @@ async def main() -> None: def test_create_subprocess_env_exec(self) -> None: async def main() -> None: cmd = [sys.executable, "-c", - "import os; print(os.getenv('FOO'))"] + "import os, sys; sys.stdout.write(os.getenv('FOO'))"] env = {"FOO": 'bar'} proc = await asyncio.create_subprocess_exec( *cmd, env=env, stdout=subprocess.PIPE ) stdout, _ = await proc.communicate() - self.assertEqual(stdout, b"bar\n") + self.assertEqual(stdout, b"bar") self.assertEqual(proc.returncode, 0) task = asyncio.create_task(proc.wait()) await asyncio.sleep(0) From cb694eda8fc56c6ca6e9e8350ad8851394b33154 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Thu, 22 Dec 2022 13:46:30 +0000 Subject: [PATCH 3/4] compare entire list --- Lib/test/test_asyncio/test_subprocess.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 54e0d1e1aa83f5..051d0c3e3e6a94 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -736,7 +736,7 @@ async def main() -> None: def test_subprocess_consistent_callbacks(self): events = [] - class Protocol(asyncio.SubprocessProtocol): + class MyProtocol(asyncio.SubprocessProtocol): def __init__(self, exit_future: asyncio.Future) -> None: self.exit_future = exit_future @@ -754,16 +754,17 @@ async def main() -> None: loop = asyncio.get_running_loop() exit_future = asyncio.Future() code = 'import sys; sys.stdout.write("stdout"); sys.stderr.write("stderr")' - transport, _ = await loop.subprocess_exec(lambda: Protocol(exit_future), sys.executable, '-c', code, - stdin=None) + transport, _ = await loop.subprocess_exec(lambda: MyProtocol(exit_future), + sys.executable, '-c', code, stdin=None) await exit_future transport.close() - self.assertEqual(len(events), 5, events) - self.assertEqual(events[0], ('pipe_data_received', 1, b'stdout')) - self.assertEqual(events[1], ('pipe_data_received', 2, b'stderr')) - self.assertEqual(events[2], 'pipe_connection_lost') - self.assertEqual(events[3], 'pipe_connection_lost') - self.assertEqual(events[4], 'process_exited') + self.assertEqual(events, [ + ('pipe_data_received', 1, b'stdout'), + ('pipe_data_received', 2, b'stderr'), + 'pipe_connection_lost', + 'pipe_connection_lost', + 'process_exited', + ]) self.loop.run_until_complete(main()) From 0a46c458920d19be091fb09b3b04f774e426b95c Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Thu, 22 Dec 2022 13:58:14 +0000 Subject: [PATCH 4/4] refactor to helper --- Lib/test/test_asyncio/test_subprocess.py | 30 ++++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 051d0c3e3e6a94..1ae290a003f212 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -686,6 +686,15 @@ async def execute(): self.assertIsNone(self.loop.run_until_complete(execute())) + async def check_stdout_output(self, coro, output): + proc = await coro + stdout, _ = await proc.communicate() + self.assertEqual(stdout, output) + self.assertEqual(proc.returncode, 0) + task = asyncio.create_task(proc.wait()) + await asyncio.sleep(0) + self.assertEqual(task.result(), proc.returncode) + def test_create_subprocess_env_shell(self) -> None: async def main() -> None: cmd = f'''{sys.executable} -c "import os, sys; sys.stdout.write(os.getenv('FOO'))"''' @@ -693,31 +702,22 @@ async def main() -> None: proc = await asyncio.create_subprocess_shell( cmd, env=env, stdout=subprocess.PIPE ) - stdout, _ = await proc.communicate() - self.assertEqual(stdout, b"bar") - self.assertEqual(proc.returncode, 0) - task = asyncio.create_task(proc.wait()) - await asyncio.sleep(0) - self.assertEqual(task.result(), proc.returncode) + return proc - self.loop.run_until_complete(main()) + self.loop.run_until_complete(self.check_stdout_output(main(), b'bar')) def test_create_subprocess_env_exec(self) -> None: async def main() -> None: cmd = [sys.executable, "-c", "import os, sys; sys.stdout.write(os.getenv('FOO'))"] - env = {"FOO": 'bar'} + env = {"FOO": 'baz'} proc = await asyncio.create_subprocess_exec( *cmd, env=env, stdout=subprocess.PIPE ) - stdout, _ = await proc.communicate() - self.assertEqual(stdout, b"bar") - self.assertEqual(proc.returncode, 0) - task = asyncio.create_task(proc.wait()) - await asyncio.sleep(0) - self.assertEqual(task.result(), proc.returncode) + return proc + + self.loop.run_until_complete(self.check_stdout_output(main(), b'baz')) - self.loop.run_until_complete(main()) def test_subprocess_concurrent_wait(self) -> None: async def main() -> None: