|
8 | 8 | import types
|
9 | 9 | from io import StringIO
|
10 | 10 | from io import BytesIO
|
| 11 | +from io import TextIOBase |
11 | 12 | from itertools import chain, repeat
|
12 | 13 |
|
13 | 14 | from pytest import raises, skip
|
@@ -1098,16 +1099,51 @@ def subclasses_can_override_input_sleep(self):
|
1098 | 1099 | class MyRunner(_Dummy):
|
1099 | 1100 | input_sleep = 0.007
|
1100 | 1101 |
|
| 1102 | + def fake_stdin_stream(): |
| 1103 | + # The value "foo" is eventually returned. |
| 1104 | + yield "f" |
| 1105 | + # None values simulate waiting for input on stdin. |
| 1106 | + yield None |
| 1107 | + yield "o" |
| 1108 | + yield None |
| 1109 | + yield "o" |
| 1110 | + yield None |
| 1111 | + # Once the stream is closed, stdin continues to return empty strings. |
| 1112 | + while True: |
| 1113 | + yield '' |
| 1114 | + |
| 1115 | + class FakeStdin(TextIOBase): |
| 1116 | + def __init__(self, stdin): |
| 1117 | + self.stream = stdin |
| 1118 | + |
| 1119 | + def read(self, size): |
| 1120 | + return next(self.stream) |
| 1121 | + |
1101 | 1122 | with patch("invoke.runners.time") as mock_time:
|
1102 | 1123 | MyRunner(Context()).run(
|
1103 | 1124 | _,
|
1104 |
| - in_stream=StringIO("foo"), |
| 1125 | + in_stream=FakeStdin(fake_stdin_stream()), |
1105 | 1126 | out_stream=StringIO(), # null output to not pollute tests
|
1106 | 1127 | )
|
1107 |
| - # Just make sure the first few sleeps all look good. Can't know |
1108 |
| - # exact length of list due to stdin worker hanging out til end of |
1109 |
| - # process. Still worth testing more than the first tho. |
1110 |
| - assert mock_time.sleep.call_args_list[:3] == [call(0.007)] * 3 |
| 1128 | + # Just make sure the sleeps all look good. |
| 1129 | + # There are three here because we return three "None" in fake_stdin_stream. |
| 1130 | + assert mock_time.sleep.call_args_list == [call(0.007)] * 3 |
| 1131 | + |
| 1132 | + @mock_subprocess() |
| 1133 | + def populated_streams_do_not_sleep(self): |
| 1134 | + class MyRunner(_Dummy): |
| 1135 | + read_chunk_size = 1 |
| 1136 | + |
| 1137 | + runner = MyRunner(Context()) |
| 1138 | + with patch("invoke.runners.time") as mock_time: |
| 1139 | + with patch.object(runner, "wait"): |
| 1140 | + runner.run( |
| 1141 | + _, |
| 1142 | + in_stream=StringIO("lots of bytes to read"), |
| 1143 | + out_stream=StringIO(), # null output to not pollute tests |
| 1144 | + ) |
| 1145 | + # Sleep should not be called before we break. |
| 1146 | + assert len(mock_time.sleep.call_args_list) == 0 |
1111 | 1147 |
|
1112 | 1148 | class stdin_mirroring:
|
1113 | 1149 | def _test_mirroring(self, expect_mirroring, **kwargs):
|
|
0 commit comments