diff --git a/behave_utils/proc.py b/behave_utils/proc.py index fc9d08f23d0c580f09f7962614b4db818daf96f7..c29bdeb09bae2828b0a2e69c9b44c1e14a6fe7b5 100644 --- a/behave_utils/proc.py +++ b/behave_utils/proc.py @@ -170,10 +170,11 @@ async def _exec_io( kwargs: dict[str, Any], ) -> trio.Process: async with trio.open_nursery() as nursery: + stdin = kwargs.pop('stdin') if 'stdin' in kwargs else PIPE if data else DEVNULL proc: trio.Process = await nursery.start( partial( trio.run_process, [*coerce_args(cmd)], - stdin=PIPE if data else DEVNULL, + stdin=stdin, stdout=PIPE, stderr=PIPE, check=False, **kwargs, diff --git a/tests/unit/proc/test_async.py b/tests/unit/proc/test_async.py index 43363f93bb2a7cdd4bcc4d9f9d88023a510c5f22..866b568933481d4b896fcb37f7cf8a9a3410e82a 100644 --- a/tests/unit/proc/test_async.py +++ b/tests/unit/proc/test_async.py @@ -71,6 +71,33 @@ class ExecIOTests(TestCase): with self.assertRaises(TypeError): await proc.aexec_io(ECHO_OUTPUT, input=TEST_BYTES, stdin=sys.stdin) + @trio_test() + async def test_stdin(self) -> None: + """ + Check that calling with the "stdin" argument works as expected + + Regression test for #22 + """ + with self.subTest(stdin="IO[bytes]"): + rfd, wfd = os.pipe() + with open(wfd, "wb") as pipe: + pipe.write(TEST_BYTES) + + with open(rfd, "rb") as pipe: + recv = await proc.aexec_io(ECHO_OUTPUT, stdin=pipe, deserialiser=bytes) + + self.assertEqual(recv, TEST_BYTES) + + with self.subTest(stdin="IO[str]"): + rfd, wfd = os.pipe() + with open(wfd, "wb") as pipe: + pipe.write(TEST_BYTES) + + with open(rfd, "r") as pipe: + recv = await proc.aexec_io(ECHO_OUTPUT, stdin=pipe, deserialiser=bytes) + + self.assertEqual(recv, TEST_BYTES) + @trio_test() async def test_stdout(self) -> None: """ @@ -136,6 +163,35 @@ class ExecutorTests(TestCase): self.assertEqual(output, TEST_BYTES) + @trio_test() + async def test_stdin(self) -> None: + """ + Check that calling with the "stdin" argument works as expected + + Regression test for #22 + """ + exe = proc.AsyncExecutor(*FIXTURE_CMD) + + with self.subTest(stdin="IO[bytes]"): + rfd, wfd = os.pipe() + with open(wfd, "wb") as pipe: + pipe.write(TEST_BYTES) + + with open(rfd, "rb") as pipe: + recv = await exe("echo", stdin=pipe, deserialiser=bytes) + + self.assertEqual(recv, TEST_BYTES) + + with self.subTest(stdin="IO[str]"): + rfd, wfd = os.pipe() + with open(wfd, "wb") as pipe: + pipe.write(TEST_BYTES) + + with open(rfd, "r") as pipe: + recv = await exe("echo", stdin=pipe, deserialiser=bytes) + + self.assertEqual(recv, TEST_BYTES) + @trio_test() async def test_stdout(self) -> None: """ diff --git a/tests/unit/proc/test_proc.py b/tests/unit/proc/test_proc.py index e7b486839623376d79deab6753d55c6db529edcf..884849f5a06ec388e3e13928f8630acddf871f75 100644 --- a/tests/unit/proc/test_proc.py +++ b/tests/unit/proc/test_proc.py @@ -88,6 +88,32 @@ class ExecIOTests(TestCase): with self.assertRaises(TypeError): proc.exec_io(ECHO_OUTPUT, input=TEST_BYTES, stdin=sys.stdin) + def test_stdin(self) -> None: + """ + Check that calling with the "stdin" argument works as expected + + Regression test for #22 + """ + with self.subTest(stdin="IO[bytes]"): + rfd, wfd = os.pipe() + with open(wfd, "wb") as pipe: + pipe.write(TEST_BYTES) + + with open(rfd, "rb") as pipe: + recv = proc.exec_io(ECHO_OUTPUT, stdin=pipe, deserialiser=bytes) + + self.assertEqual(recv, TEST_BYTES) + + with self.subTest(stdin="IO[str]"): + rfd, wfd = os.pipe() + with open(wfd, "wb") as pipe: + pipe.write(TEST_BYTES) + + with open(rfd, "r") as pipe: + recv = proc.exec_io(ECHO_OUTPUT, stdin=pipe, deserialiser=bytes) + + self.assertEqual(recv, TEST_BYTES) + def test_stdout(self) -> None: """ Check that calling with the "stdout" argument receives bytes from stdout @@ -158,6 +184,34 @@ class ExecutorTests(TestCase): self.assertEqual(output, TEST_BYTES) + def test_stdin(self) -> None: + """ + Check that calling with the "stdin" argument works as expected + + Regression test for #22 + """ + exe = proc.Executor(*FIXTURE_CMD) + + with self.subTest(stdin="IO[bytes]"): + rfd, wfd = os.pipe() + with open(wfd, "wb") as pipe: + pipe.write(TEST_BYTES) + + with open(rfd, "rb") as pipe: + recv = exe("echo", stdin=pipe, deserialiser=bytes) + + self.assertEqual(recv, TEST_BYTES) + + with self.subTest(stdin="IO[str]"): + rfd, wfd = os.pipe() + with open(wfd, "wb") as pipe: + pipe.write(TEST_BYTES) + + with open(rfd, "r") as pipe: + recv = exe("echo", stdin=pipe, deserialiser=bytes) + + self.assertEqual(recv, TEST_BYTES) + def test_stdout(self) -> None: """ Check that calling with the "stdout" argument receives bytes from stdout