From 49c49cc2fb4013e8044795e821062e3cba3c1507 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 4 Jun 2026 07:24:01 +0000 Subject: [PATCH] feat: add test cases from upstream bluefin issue triage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 4 P1 test cases from upstream ublue-os/bluefin issue triage (#12): 1. bluefin#4471 — gnome-software high CPU after close: opens Bazaar, closes it, waits 30s, asserts CPU usage < 5%. Added to tests/software/features/flatpak.feature with a custom step that parses ps CPU output against a named threshold constant. 2. bluefin#4655 — btrfs compression not enabled on root: new tests/system/features/filesystem.feature checks findmnt mount options for 'compress' when root is btrfs. Skips gracefully on non-btrfs filesystems. 3. bluefin#4209 — ujust devmode prompts when already enabled: new tests/developer/features/devmode.feature runs ujust devmode and asserts the output does not contain re-enable prompts. Falls back to plain 'just' if ujust is not on PATH. 4. bluefin#4403 — flatpak repair after Fedora upgrade: new tests/smoke/features/flatpak_health.feature verifies both 'flatpak repair --user' and '--system' exit cleanly. Ref: #12 Signed-off-by: unknown --- tests/developer/features/devmode.feature | 11 +++++ tests/developer/features/steps/steps.py | 48 +++++++++++++++++++ tests/smoke/features/flatpak_health.feature | 14 ++++++ tests/software/features/flatpak.feature | 9 ++++ tests/software/features/steps/steps.py | 16 +++++++ tests/system/features/filesystem.feature | 7 +++ .../system/features/steps/filesystem_steps.py | 28 +++++++++++ 7 files changed, 133 insertions(+) create mode 100644 tests/developer/features/devmode.feature create mode 100644 tests/smoke/features/flatpak_health.feature create mode 100644 tests/system/features/filesystem.feature create mode 100644 tests/system/features/steps/filesystem_steps.py diff --git a/tests/developer/features/devmode.feature b/tests/developer/features/devmode.feature new file mode 100644 index 000000000..7253aa090 --- /dev/null +++ b/tests/developer/features/devmode.feature @@ -0,0 +1,11 @@ +@developer_suite +Feature: ujust devmode toggle + Validates that `ujust devmode` behaves correctly and does not prompt + to enable developer mode when it is already active. + Regression for bluefin#4209. + + @devmode @regression @bluefin_4209 + Scenario: ujust devmode does not prompt to enable when already enabled (bluefin#4209) + * ujust is available on PATH + * Run ujust devmode and capture output + * ujust devmode output does not prompt to re-enable diff --git a/tests/developer/features/steps/steps.py b/tests/developer/features/steps/steps.py index 82ef104b8..d0528e729 100644 --- a/tests/developer/features/steps/steps.py +++ b/tests/developer/features/steps/steps.py @@ -61,6 +61,54 @@ def _quadlet_files_in(directory: Path) -> list[Path]: ] +@step("ujust is available on PATH") +def ujust_is_available_on_path(context) -> None: + result = _run_command(["which", "ujust"]) + if result.returncode != 0: + just_result = _run_command(["which", "just"]) + assert just_result.returncode == 0, ( + "Neither ujust nor just found on PATH" + ) + + +@step("Run ujust devmode and capture output") +def run_ujust_devmode(context) -> None: + result = subprocess.run( + ["ujust", "devmode"], + capture_output=True, + text=True, + timeout=30, + env={**os.environ, "TERM": "dumb"}, + ) + if result.returncode != 0: + result = subprocess.run( + ["just", "devmode"], + capture_output=True, + text=True, + timeout=30, + env={**os.environ, "TERM": "dumb"}, + ) + context.devmode_output = f"{result.stdout}\n{result.stderr}".strip() + context.devmode_rc = result.returncode + + +@step("ujust devmode output does not prompt to re-enable") +def ujust_devmode_no_re_enable_prompt(context) -> None: + output = getattr(context, "devmode_output", "") + re_enable_phrases = [ + "would you like to enable", + "do you want to enable", + "enable developer mode", + ] + output_lower = output.lower() + for phrase in re_enable_phrases: + assert phrase not in output_lower, ( + f"ujust devmode prompted to re-enable when already enabled (bluefin#4209).\n" + f"Found: {phrase!r}\n" + f"Output:\n{output[:500]}" + ) + + @step("Make sure window is focused for wayland testing") def make_sure_window_is_focused(context) -> None: # Pattern from GNOMETerminalAutomation steps.py — prevents input race on Wayland diff --git a/tests/smoke/features/flatpak_health.feature b/tests/smoke/features/flatpak_health.feature new file mode 100644 index 000000000..f518ca2f5 --- /dev/null +++ b/tests/smoke/features/flatpak_health.feature @@ -0,0 +1,14 @@ +@smoke_suite +Feature: Flatpak runtime health + Validates the Flatpak substrate is healthy at the system level. + Regression for bluefin#4403 (flatpak repair should succeed after upgrades). + + @flatpak @health @regression @bluefin_4403 + Scenario: flatpak repair --user exits cleanly (bluefin#4403) + * Run and save command output: "flatpak repair --user 2>&1; echo exit:$?" + * Last command output stripped contains "exit:0" + + @flatpak @health + Scenario: flatpak repair --system exits cleanly + * Run and save command output: "flatpak repair --system 2>&1; echo exit:$?" + * Last command output stripped contains "exit:0" diff --git a/tests/software/features/flatpak.feature b/tests/software/features/flatpak.feature index 1eb0356a7..a984d75a1 100644 --- a/tests/software/features/flatpak.feature +++ b/tests/software/features/flatpak.feature @@ -59,6 +59,15 @@ Feature: gnome-software (Bazaar) smoke tests * Run and save command output: "coredumpctl list gnome-software --no-pager 2>&1 | grep -c 'gnome-software' || echo 0" * Last command output "is" "0" + @software @regression @bluefin_4471 @cpu + Scenario: gnome-software does not consume high CPU after close (bluefin#4471) + * Application "software" is running + * Close application "software" via "shortcut" + * Application "software" is no longer running + * Wait 30 seconds before action + * Run and save command output: "sh -c 'CPU=$(ps -C gnome-software -o %cpu= 2>/dev/null | tr -d \" \" | head -1); [ -z \"$CPU\" ] && echo 0 || echo \"$CPU\"'" + * gnome-software CPU usage is below threshold + @software @close Scenario: Bazaar closes cleanly via shortcut * Close application "software" via "shortcut" diff --git a/tests/software/features/steps/steps.py b/tests/software/features/steps/steps.py index 23b60c712..08a005f97 100644 --- a/tests/software/features/steps/steps.py +++ b/tests/software/features/steps/steps.py @@ -29,6 +29,22 @@ def last_command_output_contains(context, text) -> None: assert text in output, f"Expected {text!r} in output:\n{output[:500]}" +GNOME_SOFTWARE_CPU_THRESHOLD_PCT = 5.0 + + +@step("gnome-software CPU usage is below threshold") +def gnome_software_cpu_below_threshold(context) -> None: + output = _last_output(context) + try: + cpu = float(output) + except ValueError: + cpu = 0.0 + assert cpu < GNOME_SOFTWARE_CPU_THRESHOLD_PCT, ( + f"gnome-software CPU usage {cpu}% exceeds " + f"{GNOME_SOFTWARE_CPU_THRESHOLD_PCT}% threshold (bluefin#4471)" + ) + + @step('Start "{app_id}" via shell') def start_app_via_shell(context, app_id) -> None: _require_bazaar(app_id) diff --git a/tests/system/features/filesystem.feature b/tests/system/features/filesystem.feature new file mode 100644 index 000000000..6bbdc4f9d --- /dev/null +++ b/tests/system/features/filesystem.feature @@ -0,0 +1,7 @@ +@system_suite @filesystem +Feature: filesystem configuration + Validates filesystem-level expectations for Bluefin installations. + + @btrfs @regression @bluefin_4655 + Scenario: btrfs root has compression enabled (bluefin#4655) + * root filesystem compression is enabled if btrfs diff --git a/tests/system/features/steps/filesystem_steps.py b/tests/system/features/steps/filesystem_steps.py new file mode 100644 index 000000000..f0cfe3c5d --- /dev/null +++ b/tests/system/features/steps/filesystem_steps.py @@ -0,0 +1,28 @@ +import subprocess + +from behave import step + + +def run(cmd, **kwargs): + return subprocess.run(cmd, shell=True, capture_output=True, text=True, **kwargs) + + +@step("root filesystem compression is enabled if btrfs") +def step_btrfs_compression(context): + fstype = run("findmnt / -o FSTYPE -n") + assert fstype.returncode == 0, f"findmnt / failed: {fstype.stderr}" + fs = fstype.stdout.strip() + + if fs != "btrfs": + context.scenario.skip(f"root filesystem is {fs}, not btrfs — skipping compression check") + return + + opts = run("findmnt / -o OPTIONS -n") + assert opts.returncode == 0, f"findmnt / -o OPTIONS failed: {opts.stderr}" + mount_options = opts.stdout.strip() + + assert "compress" in mount_options, ( + f"btrfs root mount is missing compression option (bluefin#4655).\n" + f"Mount options: {mount_options}\n" + f"Expected 'compress=zstd' or similar in mount options." + )