nixos/test-driver: rework timeout for wait_for_console_text

Before this commit, `wait_for_console_text` would read one line every
900ms before trying again to read the next line.

This commit fixes that behavior by greedily reading all buffer that is
available for match trying to find a match rather than reading one per
retry iteration.

In effect this moves the loop inside the `console_matches` helper and
makes the behavior of `wait_for_console_text` with timeout behave the
same way as with timeout.

This also provides a test that showcases the problem.
This commit is contained in:
Arthur Gautier 2026-06-01 18:46:47 -07:00
commit 4e5b779a75
3 changed files with 38 additions and 10 deletions

View file

@ -1164,24 +1164,25 @@ class QemuMachine(BaseMachine):
# to match multiline regexes.
console = io.StringIO()
def console_matches(_last_try: bool) -> bool:
def console_matches(_last_try: bool, block: bool = False) -> bool:
nonlocal console
try:
# This will return as soon as possible and
# sleep 1 second.
console.write(self.last_lines.get(block=False))
while True:
# This will return as soon as possible and
# sleep 1 second.
console.write(self.last_lines.get(block=block))
console.seek(0)
matches = re.search(regex, console.read())
if matches is not None:
return True
except queue.Empty:
pass
console.seek(0)
matches = re.search(regex, console.read())
return matches is not None
return False
with self.nested(f"waiting for {regex} to appear on console"):
if timeout is not None:
retry(console_matches, timeout)
else:
while not console_matches(False):
pass
console_matches(False, block=True)
def get_console_log(self) -> str:
"""

View file

@ -153,6 +153,7 @@ in
console-log = runTest ./nixos-test-driver/console-log.nix;
containers = runTest ./nixos-test-driver/containers.nix;
skip-typecheck = runTest ./nixos-test-driver/skip-typecheck.nix;
console-timeout = runTest ./nixos-test-driver/console-timeout.nix;
options-doc-regression = import ./nixos-test-driver/options-doc-regression.nix { inherit pkgs; };
driver-timeout =
pkgs.runCommand "ensure-timeout-induced-failure"

View file

@ -0,0 +1,26 @@
{ pkgs, lib, ... }:
{
name = "console-timeout";
nodes.machine = {
systemd.services.generate-output.script = ''
echo "match that"
sleep 1
for i in $(seq 15); do
echo "line $i"
done
echo "match this"
'';
};
testScript = ''
machine.start()
machine.wait_for_unit("multi-user.target")
machine.systemctl("start generate-output")
machine.wait_for_console_text("match that")
machine.wait_for_console_text("match this", timeout=10)
'';
}