From 702e05986367e9988be479e9e8843c91421de614 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Fri, 23 Oct 2026 23:49:52 +0200 Subject: [PATCH] fix: make two installer tests runner-proof The old-card test read the screen without reading what the key just drew, and pressed Enter twelve rows past its folder on a slow runner. The launcher device now has a sudo that refuses, as a runner's passwordless sudo ran the fake mapper as root and recorded nothing. --- tests/test_handheld_launchers.py | 4 ++++ tests/test_install_tui.py | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/test_handheld_launchers.py b/tests/test_handheld_launchers.py index 5101c9cd8..7f3d71c2a 100644 --- a/tests/test_handheld_launchers.py +++ b/tests/test_handheld_launchers.py @@ -677,6 +677,10 @@ class Device: # A probe that cannot connect is offline (curl exit 7). self.tool("curl", '#!/bin/sh\nexit "${FAKE_CURL:-0}"\n') self.tool("pgrep", '#!/bin/sh\nexit "${FAKE_PGREP:-1}"\n') + # A runner's real sudo needs no password: the Tools entry then ran + # the fake mapper as root, with a reset environment, and recorded + # nothing. A device has no sudo unless a test gives it one. + self.tool("sudo", "#!/bin/sh\nexit 1\n") fonts = self.root / "fonts" fonts.mkdir() for name in ("Lat7-TerminusBold32x16", "Lat7-TerminusBold22x11", diff --git a/tests/test_install_tui.py b/tests/test_install_tui.py index cccddfa2e..93363b04f 100644 --- a/tests/test_install_tui.py +++ b/tests/test_install_tui.py @@ -2818,6 +2818,21 @@ class Pty: def text(self) -> str: return "\n".join(line.rstrip() for line in self.screen.display) + def settle(self, quiet: float = 0.3, timeout: float = 10.0) -> str: + """The screen once nothing more arrives for `quiet` seconds. + + text() shows only what was read: a loop that sent a key and looked + again saw the screen before the key, and on a slow runner pressed + Enter twelve rows past the folder it was looking for. + """ + end = time.monotonic() + timeout + while time.monotonic() < end: + if not select.select([self.fd], [], [], quiet)[0]: + break + if not self._pump(0): + break + return self.text() + def wait(self, needle: str, timeout: float = 20.0) -> str: end = time.monotonic() + timeout while time.monotonic() < end: @@ -3124,9 +3139,10 @@ class EndToEnd(unittest.TestCase): term.send(DOWN, DOWN, "\r") term.wait("Choose the old card") for _ in range(12): - if "> oldcard/" in term.text(): + if "> oldcard/" in term.settle(): break term.send(DOWN) + self.assertIn("> oldcard/", term.settle()) term.send("\r") term.wait("> Use this folder") term.send("\r")