Skip to content

Commit acc229a

Browse files
committed
first_stage_test: Add test_timeout_error
Signed-off-by: Marc Hartmayer <[email protected]>
1 parent a9e21fd commit acc229a

File tree

1 file changed

+40
-0
lines changed

1 file changed

+40
-0
lines changed

tests/first_stage_test.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33
import select
44
import subprocess
5+
import sys
56

67
try:
78
from io import StringIO
@@ -339,3 +340,42 @@ def test_eof_too_early(self):
339340
finally:
340341
proc.stdout.close()
341342
proc.stderr.close()
343+
344+
def test_timeout_error(self):
345+
"""
346+
The boot command should write an ECO marker to stdout, read the
347+
preamble from stdin, then execute it.
348+
349+
This test attaches closes stdin to create a specific failure
350+
1. Fork child tries to read from STDIN, but fails as it is closed
351+
2. Fork child raises TimeoutError
352+
3. Fork child's file descriptors (write pipes) are closed by the OS
353+
4. Fork parent does `dup(<read pipe>, <stdin>)` and `exec(<python>)`
354+
5. Python reads `b''` (i.e. EOF) from stdin (a closed pipe)
355+
6. Python runs `''` (a valid script) and exits with success
356+
"""
357+
358+
# We do not want to wait the default of 10s, change it to 0.3s
359+
self.conn._first_stage_timeout = 0.3
360+
args = self.conn.get_boot_command()
361+
362+
proc = subprocess.Popen(
363+
args=args,
364+
stdout=subprocess.PIPE,
365+
stderr=subprocess.PIPE,
366+
preexec_fn=sys.stdin.close,
367+
)
368+
try:
369+
try:
370+
stdout, stderr = proc.communicate(timeout=12)
371+
except TypeError:
372+
stdout, stderr = proc.communicate()
373+
except:
374+
proc.kill()
375+
self.fail("Timeout situation was not recognized")
376+
self.assertEqual(0, proc.returncode)
377+
self.assertEqual(stdout, mitogen.parent.BootstrapProtocol.EC0_MARKER + b("\n"))
378+
self.assertIn(
379+
b("TimeoutError"),
380+
stderr,
381+
)

0 commit comments

Comments
 (0)