tests: start the journalctl tail before it is needed

iter_output() waited until its caller's first next() call to spawn
the journalctl tail, which could lead to log traffic being missed,
hanging next() forever: start the tail right away instead.
This commit is contained in:
j4n
2026-08-27 15:14:07 +02:00
parent 82ff8e86ef
commit b9fc3ef550
3 changed files with 41 additions and 1 deletions
@@ -13,7 +13,8 @@ from cmdeploy.cmdeploy import get_sshexec
class TestSSHExecutor:
@pytest.fixture(scope="class")
def sshexec(self, sshdomain):
@classmethod
def sshexec(cls, sshdomain):
return get_sshexec(sshdomain)
def test_ls(self, sshexec):
+5
View File
@@ -411,6 +411,7 @@ class Remote:
self._procs = []
def iter_output(self, logcmd="", ready=None):
# run popen run here so the tail is live before caller triggers
getjournal = "journalctl -f" if not logcmd else logcmd
print(self.sshdomain)
if self.sshdomain in ("@local", "localhost"):
@@ -425,6 +426,10 @@ class Remote:
stderr=subprocess.DEVNULL,
)
self._procs.append(popen)
return self._read_lines(popen, ready)
@staticmethod
def _read_lines(popen, ready):
try:
while 1:
line = popen.stdout.readline()
@@ -0,0 +1,34 @@
from cmdeploy.tests.plugin import Remote
def _script(tmp_path, name, body):
# iter_output splits its command string on whitespace, so any command
# with embedded spaces has to live in a file, not an inline string.
path = tmp_path / name
path.write_text(f"#!/bin/sh\n{body}\n")
path.chmod(0o755)
return str(path)
def test_iter_output_spawns_before_first_next(tmp_path):
"""The tail process must be live before the caller triggers or fast-moving logs can be missed"""
script = _script(tmp_path, "late.sh", "sleep 0.2\necho late-line")
remote = Remote("@local")
lineproducer = remote.iter_output(script)
assert remote._procs, "Popen must run on iter_output() itself, not on first next()"
assert remote._procs[0].poll() is None
assert next(lineproducer) == "late-line"
remote.close()
def test_iter_output_ready_fires_after_first_line(tmp_path):
"""ready() must wait for the first real line, not fire at spawn time"""
script = _script(tmp_path, "trigger.sh", "echo backlog\nsleep 0.2\necho trigger-fired")
remote = Remote("@local")
calls = []
lineproducer = remote.iter_output(script, ready=lambda: calls.append(1))
assert calls == []
assert next(lineproducer) == "backlog"
assert calls == [1]
assert next(lineproducer) == "trigger-fired"
remote.close()