From e33d3f16ebf3c19670057fd3b6a3870fe94afc25 Mon Sep 17 00:00:00 2001 From: OPNA2608 Date: Thu, 11 Dec 2025 19:41:20 +0100 Subject: [PATCH 1/2] nixosTests.lomiri: Reduce flakiness Looking for the clock indicator's text has gotten too flaky. We have working launcher button customisation now, so look for its colour instead. --- nixos/tests/lomiri.nix | 93 +++++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 24 deletions(-) diff --git a/nixos/tests/lomiri.nix b/nixos/tests/lomiri.nix index f018cf269458..7364e6046c67 100644 --- a/nixos/tests/lomiri.nix +++ b/nixos/tests/lomiri.nix @@ -76,6 +76,71 @@ let }; sharedTestFunctions = '' + from collections.abc import Callable + import tempfile + import subprocess + + # Based on terminal-emulators.nix' check_for_pink + def check_for_color(color: str) -> Callable[[bool], bool]: + def check_for_color_retry(final=False) -> bool: + with tempfile.NamedTemporaryFile() as tmpin: + machine.send_monitor_command("screendump {}".format(tmpin.name)) + + cmd = 'convert {} -define histogram:unique-colors=true -format "%c" histogram:info:'.format( + tmpin.name + ) + ret = subprocess.run(cmd, shell=True, capture_output=True) + if ret.returncode != 0: + raise Exception( + "image analysis failed with exit code {}".format(ret.returncode) + ) + + text = ret.stdout.decode("utf-8") + return color in text + + return check_for_color_retry + + def check_for_color_continued_presence(color: str) -> Callable[[bool], bool]: + colorFunc: Callable[[bool], bool] = check_for_color(color) + def check_for_color_continued_presence_retry(final=False) -> bool: + colorPresent: bool = colorFunc(final) + + if final: + # If it fails now, retry handles the exception raising. + # Otherwise, we passed. + return colorPresent + else: + if colorPresent: + # We want retry to continue running us until the timeout, so signal failure. + return False + else: + # Color disappeared + raise Exception( + "color {} has disappeared from the screen!".format(color) + ) + return check_for_color_continued_presence_retry + + def ensure_lomiri_running(): + """ + Ensure that Lomiri has finished starting up. + """ + + # Process runs + machine.wait_until_succeeds("pgrep -u ${user} -f 'lomiri --mode=full-shell'") + + # Output rendering from Lomiri has started when it starts printing performance diagnostics + machine.wait_for_console_text("Last frame took") + + # One of the last UI elements that loads is the clock. In the past, we could OCR for AM/PM to ensure it's there. That is now flaky. + # The next best thing is to look for the launcher button, and ensure it stays around for awhile (DE doesn't crash). + launcherColor: str = "#5277C3" + with machine.nested("Waiting for the screen to have launcherColor {} on it:".format(launcherColor)): + retry(check_for_color(launcherColor)) + with machine.nested("Ensuring launcherColor {} stays present on the screen:".format(launcherColor)): + retry(fn=check_for_color_continued_presence(launcherColor), timeout=30) + + machine.screenshot("lomiri_launched") + def wait_for_text(text): """ Wait for on-screen text, and try to optimise retry count for slow hardware. @@ -179,12 +244,7 @@ let # The session should start, and not be stuck in i.e. a crash loop with subtest("lomiri starts"): - machine.wait_until_succeeds("pgrep -u ${user} -f 'lomiri --mode=full-shell'") - # Output rendering from Lomiri has started when it starts printing performance diagnostics - machine.wait_for_console_text("Last frame took") - # Look for datetime's clock, one of the last elements to load - wait_for_text(r"(AM|PM)") - machine.screenshot("lomiri_launched") + ensure_lomiri_running() # The ayatana indicators are an important part of the experience, and they hold the only graphical way of exiting the session. # There's a test app we could use that also displays their contents, but it's abit inconsistent. @@ -398,12 +458,7 @@ in # The session should start, and not be stuck in i.e. a crash loop with subtest("lomiri starts"): - machine.wait_until_succeeds("pgrep -u ${user} -f 'lomiri --mode=full-shell'") - # Output rendering from Lomiri has started when it starts printing performance diagnostics - machine.wait_for_console_text("Last frame took") - # Look for datetime's clock, one of the last elements to load - wait_for_text(r"(AM|PM)") - machine.screenshot("lomiri_launched") + ensure_lomiri_running() # Working terminal keybind is good with subtest("terminal keybind works"): @@ -550,12 +605,7 @@ in # The session should start, and not be stuck in i.e. a crash loop with subtest("lomiri starts"): - machine.wait_until_succeeds("pgrep -u ${user} -f 'lomiri --mode=full-shell'") - # Output rendering from Lomiri has started when it starts printing performance diagnostics - machine.wait_for_console_text("Last frame took") - # Look for datetime's clock, one of the last elements to load - wait_for_text(r"(AM|PM)") - machine.screenshot("lomiri_launched") + ensure_lomiri_running() # Working terminal keybind is good with subtest("terminal keybind works"): @@ -716,14 +766,9 @@ in # Login machine.send_chars("${pwInput}\n") - machine.wait_until_succeeds("pgrep -u ${user} -f 'lomiri --mode=full-shell'") - # Output rendering from Lomiri has started when it starts printing performance diagnostics - machine.wait_for_console_text("Last frame took") # And the desktop doesn't render the wallpaper anymore. Grumble grumble... - # Look for datetime's clock, one of the last elements to load - wait_for_text(r"(AM|PM)") - machine.screenshot("lomiri_launched") + ensure_lomiri_running() # Lomiri in desktop mode should use the correct keymap with subtest("lomiri session keymap works"): From f992d9085cef3e2fdd94670ce77b26264bb51b72 Mon Sep 17 00:00:00 2001 From: OPNA2608 Date: Thu, 11 Dec 2025 19:46:14 +0100 Subject: [PATCH 2/2] nixosTests.lomiri: Add None return to functions that return nothing Stops the warning message: > By default the bodies of untyped functions are not checked, consider using --check-untyped-defs [annotation-unchecked] --- nixos/tests/lomiri.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nixos/tests/lomiri.nix b/nixos/tests/lomiri.nix index 7364e6046c67..cb24a77618fe 100644 --- a/nixos/tests/lomiri.nix +++ b/nixos/tests/lomiri.nix @@ -120,7 +120,7 @@ let ) return check_for_color_continued_presence_retry - def ensure_lomiri_running(): + def ensure_lomiri_running() -> None: """ Ensure that Lomiri has finished starting up. """ @@ -141,7 +141,7 @@ let machine.screenshot("lomiri_launched") - def wait_for_text(text): + def wait_for_text(text) -> None: """ Wait for on-screen text, and try to optimise retry count for slow hardware. """ @@ -149,7 +149,7 @@ let machine.sleep(30) machine.wait_for_text(text) - def toggle_maximise(): + def toggle_maximise() -> None: """ Maximise the current window. """ @@ -163,7 +163,7 @@ let machine.send_key("esc") machine.sleep(5) - def mouse_click(xpos, ypos): + def mouse_click(xpos, ypos) -> None: """ Move the mouse to a screen location and hit left-click. """ @@ -176,7 +176,7 @@ let machine.execute("ydotool click 0xC0") machine.sleep(2) - def open_starter(): + def open_starter() -> None: """ Open the starter, and ensure it's opened. """