Skip to content

Commit 783882d

Browse files
committed
pexpect-style wait for output in test_kernelapp
wait for the expected output to appear, instead of assuming 1 second is enough this should be both faster (where sleep(1) was enough) and more reliable
1 parent a212f90 commit 783882d

File tree

1 file changed

+49
-39
lines changed

1 file changed

+49
-39
lines changed
Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import os
2-
import shutil
2+
import selectors
33
import sys
44
import time
55
from subprocess import PIPE
66
from subprocess import Popen
7-
from tempfile import mkdtemp
87

98

109
def _launch(extra_env):
@@ -21,44 +20,55 @@ def _launch(extra_env):
2120
POLL_FREQ = 10
2221

2322

24-
def test_kernelapp_lifecycle():
23+
def test_kernelapp_lifecycle(request, tmpdir):
2524
# Check that 'jupyter kernel' starts and terminates OK.
26-
runtime_dir = mkdtemp()
27-
startup_dir = mkdtemp()
25+
runtime_dir = str(tmpdir.join("runtime").mkdir())
26+
startup_dir = str(tmpdir.join("startup").mkdir())
2827
started = os.path.join(startup_dir, "started")
29-
try:
30-
p = _launch(
31-
{
32-
"JUPYTER_RUNTIME_DIR": runtime_dir,
33-
"JUPYTER_CLIENT_TEST_RECORD_STARTUP_PRIVATE": started,
34-
}
35-
)
36-
# Wait for start
37-
for _ in range(WAIT_TIME * POLL_FREQ):
38-
if os.path.isfile(started):
39-
break
40-
time.sleep(1 / POLL_FREQ)
41-
else:
42-
raise AssertionError("No started file created in {} seconds".format(WAIT_TIME))
28+
p = _launch(
29+
{
30+
"JUPYTER_RUNTIME_DIR": runtime_dir,
31+
"JUPYTER_CLIENT_TEST_RECORD_STARTUP_PRIVATE": started,
32+
}
33+
)
34+
request.addfinalizer(p.terminate)
35+
36+
# Wait for start
37+
for _ in range(WAIT_TIME * POLL_FREQ):
38+
if os.path.isfile(started):
39+
break
40+
time.sleep(1 / POLL_FREQ)
41+
else:
42+
raise AssertionError("No started file created in {} seconds".format(WAIT_TIME))
43+
44+
# Connection file should be there by now
45+
for _ in range(WAIT_TIME * POLL_FREQ):
46+
files = os.listdir(runtime_dir)
47+
if files:
48+
break
49+
time.sleep(1 / POLL_FREQ)
50+
else:
51+
raise AssertionError("No connection file created in {} seconds".format(WAIT_TIME))
52+
53+
assert len(files) == 1
54+
cf = files[0]
55+
assert cf.startswith("kernel")
56+
assert cf.endswith(".json")
4357

44-
# Connection file should be there by now
45-
for _ in range(WAIT_TIME * POLL_FREQ):
46-
files = os.listdir(runtime_dir)
47-
if files:
48-
break
49-
time.sleep(1 / POLL_FREQ)
50-
else:
51-
raise AssertionError("No connection file created in {} seconds".format(WAIT_TIME))
52-
assert len(files) == 1
53-
cf = files[0]
54-
assert cf.startswith("kernel")
55-
assert cf.endswith(".json")
58+
# pexpect-style wait-for-text with timeout
59+
t = time.perf_counter()
60+
deadline = t + WAIT_TIME
61+
remaining = WAIT_TIME
5662

57-
# Send SIGTERM to shut down
58-
time.sleep(1)
59-
p.terminate()
60-
_, stderr = p.communicate(timeout=WAIT_TIME)
61-
assert cf in stderr.decode("utf-8", "replace")
62-
finally:
63-
shutil.rmtree(runtime_dir)
64-
shutil.rmtree(startup_dir)
63+
selector = selectors.DefaultSelector()
64+
selector.register(p.stderr, selectors.EVENT_READ)
65+
stderr = ""
66+
while remaining >= 0 and p.poll() is None:
67+
events = selector.select(remaining)
68+
if events:
69+
stderr += p.stderr.readline().decode("utf8", "replace")
70+
if cf in stderr:
71+
break
72+
remaining = deadline - time.perf_counter()
73+
selector.close()
74+
assert cf in stderr

0 commit comments

Comments
 (0)