Unverified Commit fc6c3008 authored by Cosima Neidahl's avatar Cosima Neidahl Committed by GitHub
Browse files

nixosTests.lomiri: Reduce flakiness (#469943)

parents 3f87a5c5 f992d908
Loading
Loading
Loading
Loading
+73 −28
Original line number Diff line number Diff line
@@ -76,7 +76,72 @@ let
  };

  sharedTestFunctions = ''
    def wait_for_text(text):
    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() -> None:
      """
      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) -> None:
      """
      Wait for on-screen text, and try to optimise retry count for slow hardware.
      """
@@ -84,7 +149,7 @@ let
      machine.sleep(30)
      machine.wait_for_text(text)

    def toggle_maximise():
    def toggle_maximise() -> None:
      """
      Maximise the current window.
      """
@@ -98,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.
      """
@@ -111,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.
      """
@@ -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"):