Skip to content

Commit 53ea049

Browse files
committed
first_stage_test: Add more tests
+ test_stdin_non_blocking + test_stdin_blocking Signed-off-by: Marc Hartmayer <[email protected]>
1 parent 21a06ae commit 53ea049

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

tests/first_stage_test.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,117 @@
1+
import fcntl
2+
import functools
3+
import operator
4+
15
import mitogen.core
26
import mitogen.parent
37
from mitogen.core import b
48

59
import testlib
610

11+
def own_create_child(args, blocking, pipe_size=None, preexec_fn=None):
12+
"""
13+
Create a child process whose stdin/stdout is connected to a pipe.
14+
15+
:param list args:
16+
Program argument vector.
17+
:param bool blocking:
18+
If :data:`True`, the pipes use blocking IO, otherwise non-blocking.
19+
:param function preexec_fn:
20+
If not :data:`None`, a function to run within the post-fork child
21+
before executing the target program.
22+
:returns:
23+
:class:`Process` instance.
24+
"""
25+
parent_rfp, child_wfp = mitogen.core.pipe(blocking=blocking)
26+
child_rfp, parent_wfp = mitogen.core.pipe(blocking=blocking)
27+
if pipe_size is not None:
28+
fcntl.fcntl(parent_rfp.fileno(), fcntl.F_SETPIPE_SZ, pipe_size)
29+
fcntl.fcntl(child_rfp.fileno(), fcntl.F_SETPIPE_SZ, pipe_size)
30+
assert fcntl.fcntl(parent_rfp.fileno(), fcntl.F_GETPIPE_SZ) == pipe_size
31+
assert fcntl.fcntl(child_rfp.fileno(), fcntl.F_GETPIPE_SZ) == pipe_size
32+
33+
stderr_r, stderr = None, None
34+
try:
35+
proc = testlib.subprocess.Popen(
36+
args=args,
37+
stdin=child_rfp,
38+
stdout=child_wfp,
39+
stderr=stderr,
40+
close_fds=True,
41+
preexec_fn=preexec_fn,
42+
)
43+
except Exception:
44+
child_rfp.close()
45+
child_wfp.close()
46+
parent_rfp.close()
47+
parent_wfp.close()
48+
raise
49+
50+
child_rfp.close()
51+
child_wfp.close()
52+
return mitogen.parent.PopenProcess(
53+
proc=proc,
54+
stdin=parent_wfp,
55+
stdout=parent_rfp,
56+
stderr=stderr_r,
57+
)
58+
59+
60+
class DummyConnectionBlocking(mitogen.parent.Connection):
61+
"""Dummy blocking IO connection"""
62+
63+
pipe_size = 4096 if getattr(fcntl, 'F_SETPIPE_SZ', None) else None
64+
create_child = staticmethod(functools.partial(own_create_child, blocking=True, pipe_size=pipe_size))
65+
name_prefix = u'dummy_blocking'
66+
67+
68+
class DummyConnectionNonBlocking(mitogen.parent.Connection):
69+
"""Dummy non-blocking IO connection"""
70+
71+
pipe_size = 4096 if getattr(fcntl, 'F_SETPIPE_SZ', None) else None
72+
create_child = staticmethod(functools.partial(own_create_child, blocking=False, pipe_size=pipe_size))
73+
name_prefix = u'dummy_non_blocking'
74+
75+
76+
class ConnectionTest(testlib.RouterMixin, testlib.TestCase):
77+
def test_stdin_non_blocking(self):
78+
"""Test that first stage works with non-blocking STDIN
79+
80+
The boot command should read the preamble from STDIN, write all ECO
81+
markers to STDOUT, and then execute the preamble.
82+
83+
This test writes the complete preamble to non-blocking STDIN.
84+
85+
1. Fork child reads from non-blocking STDIN
86+
2. Fork child writes all data as expected by the protocol.
87+
3. A context call works as expected.
88+
89+
"""
90+
log = testlib.LogCapturer()
91+
log.start()
92+
ctx = self.router._connect(DummyConnectionNonBlocking, connect_timeout=0.5)
93+
self.assertEqual(3, ctx.call(operator.add, 1, 2))
94+
logs = log.stop()
95+
96+
def test_stdin_blocking(self):
97+
"""Test that first stage works with blocking STDIN
98+
99+
The boot command should read the preamble from STDIN, write all ECO
100+
markers to STDOUT, and then execute the preamble.
101+
102+
This test writes the complete preamble to blocking STDIN.
103+
104+
1. Fork child reads from blocking STDIN
105+
2. Fork child writes all data as expected by the protocol.
106+
3. A context call works as expected.
107+
108+
"""
109+
log = testlib.LogCapturer()
110+
log.start()
111+
ctx = self.router._connect(DummyConnectionBlocking, connect_timeout=0.5)
112+
self.assertEqual(3, ctx.call(operator.add, 1, 2))
113+
logs = log.stop()
114+
7115

8116
class CommandLineTest(testlib.RouterMixin, testlib.TestCase):
9117
# Ensure this version of Python produces a command line that is sufficient

0 commit comments

Comments
 (0)