Skip to content

Commit e97afef

Browse files
GH-100192: add more asyncio subprocess tests (#100194)
1 parent 08e5594 commit e97afef

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

Lib/test/test_asyncio/test_subprocess.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,88 @@ async def execute():
686686

687687
self.assertIsNone(self.loop.run_until_complete(execute()))
688688

689+
async def check_stdout_output(self, coro, output):
690+
proc = await coro
691+
stdout, _ = await proc.communicate()
692+
self.assertEqual(stdout, output)
693+
self.assertEqual(proc.returncode, 0)
694+
task = asyncio.create_task(proc.wait())
695+
await asyncio.sleep(0)
696+
self.assertEqual(task.result(), proc.returncode)
697+
698+
def test_create_subprocess_env_shell(self) -> None:
699+
async def main() -> None:
700+
cmd = f'''{sys.executable} -c "import os, sys; sys.stdout.write(os.getenv('FOO'))"'''
701+
env = {"FOO": 'bar'}
702+
proc = await asyncio.create_subprocess_shell(
703+
cmd, env=env, stdout=subprocess.PIPE
704+
)
705+
return proc
706+
707+
self.loop.run_until_complete(self.check_stdout_output(main(), b'bar'))
708+
709+
def test_create_subprocess_env_exec(self) -> None:
710+
async def main() -> None:
711+
cmd = [sys.executable, "-c",
712+
"import os, sys; sys.stdout.write(os.getenv('FOO'))"]
713+
env = {"FOO": 'baz'}
714+
proc = await asyncio.create_subprocess_exec(
715+
*cmd, env=env, stdout=subprocess.PIPE
716+
)
717+
return proc
718+
719+
self.loop.run_until_complete(self.check_stdout_output(main(), b'baz'))
720+
721+
722+
def test_subprocess_concurrent_wait(self) -> None:
723+
async def main() -> None:
724+
proc = await asyncio.create_subprocess_exec(
725+
*PROGRAM_CAT,
726+
stdin=subprocess.PIPE,
727+
stdout=subprocess.PIPE,
728+
)
729+
stdout, _ = await proc.communicate(b'some data')
730+
self.assertEqual(stdout, b"some data")
731+
self.assertEqual(proc.returncode, 0)
732+
self.assertEqual(await asyncio.gather(*[proc.wait() for _ in range(10)]),
733+
[proc.returncode] * 10)
734+
735+
self.loop.run_until_complete(main())
736+
737+
def test_subprocess_consistent_callbacks(self):
738+
events = []
739+
class MyProtocol(asyncio.SubprocessProtocol):
740+
def __init__(self, exit_future: asyncio.Future) -> None:
741+
self.exit_future = exit_future
742+
743+
def pipe_data_received(self, fd, data) -> None:
744+
events.append(('pipe_data_received', fd, data))
745+
746+
def pipe_connection_lost(self, fd, exc) -> None:
747+
events.append('pipe_connection_lost')
748+
749+
def process_exited(self) -> None:
750+
events.append('process_exited')
751+
self.exit_future.set_result(True)
752+
753+
async def main() -> None:
754+
loop = asyncio.get_running_loop()
755+
exit_future = asyncio.Future()
756+
code = 'import sys; sys.stdout.write("stdout"); sys.stderr.write("stderr")'
757+
transport, _ = await loop.subprocess_exec(lambda: MyProtocol(exit_future),
758+
sys.executable, '-c', code, stdin=None)
759+
await exit_future
760+
transport.close()
761+
self.assertEqual(events, [
762+
('pipe_data_received', 1, b'stdout'),
763+
('pipe_data_received', 2, b'stderr'),
764+
'pipe_connection_lost',
765+
'pipe_connection_lost',
766+
'process_exited',
767+
])
768+
769+
self.loop.run_until_complete(main())
770+
689771
def test_subprocess_communicate_stdout(self):
690772
# See https://github.com/python/cpython/issues/100133
691773
async def get_command_stdout(cmd, *args):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy