From 3becfac66dc569e71d0f6085fb56e92cfa6d626a Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Fri, 24 Jul 2026 12:19:04 -0500 Subject: fix(installer): eight fixes from an overnight bug-hunt and its review I squashed these because the per-bug reasoning lives in todo.org, which this commit carries. Two could cost a machine. configure_initramfs_hook swapped the udev hook for systemd on a LUKS root, leaving a standalone encrypt hook under an init that never runs it. The rebuild succeeds and the installer exits clean, then the root won't unlock at the next boot. trim_firmware ran pacman -Rdd against twelve firmware packages behind a DMI gate reading product_name, where "Framework" never appears. That left it dead on the hardware it targets, and dangerous to fix the obvious way: this machine is a Framework Desktop whose Ryzen iGPU needs the amdgpu firmware. It refuses on PCI modalias evidence now. wipedisk discarded before it checked. blkdiscard ran with -f, which disables the exclusive open, so picking the wrong disk destroyed a live filesystem and then reported that nothing had happened. Four more are smaller. The NVIDIA preflight aborted dwm and headless installs over a driver floor they never need. zfs-replicate exited 0 after every dataset failed. Unattended installs blocked on two prompts, and the first fix for that inherited a [Y/n] default into passwordless console login. A fresh install left the dotfiles repo permanently dirty. The review found a pattern worth more than any single fix. Helpers had thorough tests and none proved they were called. Deleting the call left five suites green, including the guard on that pacman -Rdd. CALL_SITES now pins nine caller/callee pairs. The suite runs 341 tests at exit 0, with no new shellcheck findings. I proved every guard by deleting it and watching the intended test go red. --- tests/installer-steps/test_orchestrators.py | 58 +++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'tests/installer-steps/test_orchestrators.py') diff --git a/tests/installer-steps/test_orchestrators.py b/tests/installer-steps/test_orchestrators.py index 2a771ba..8de75cc 100644 --- a/tests/installer-steps/test_orchestrators.py +++ b/tests/installer-steps/test_orchestrators.py @@ -147,3 +147,61 @@ class MaintenanceConfigDispatch(unittest.TestCase): if __name__ == "__main__": unittest.main() + + +# Helper -> the function that must call it. Every one of these helpers has its +# own suite proving it behaves correctly; none of those suites proves it is +# wired in. Deleting the call left every test green in five separate suites, +# including the one guarding a `pacman -Rdd` of twelve firmware packages. +# +# This is a static check on purpose. The behavioural harness above stubs only +# the names it is given and runs the rest of the body for real, which is safe +# for an orchestrator whose body is nothing but calls, and emphatically not +# safe for a leaf like trim_firmware. Cheaper and machine-independent too: the +# alternative depends on what /proc/cpuinfo says on the box running the tests. +CALL_SITES = { + "trim_firmware": ["detect_gpu_vendors", "is_framework_intel_laptop"], + "finalize_dotfiles": ["mark_volatile_configs"], + "preflight_checks": ["select_locale", "nvidia_preflight", "check_disk_space"], + "configure_encrypted_autologin": ["configure_autologin"], + "configure_initramfs_hook": ["switch_udev_hook_to_systemd"], + "add_nvme_early_module": ["ensure_nvme_early_module"], + "configure_snapshots": ["configure_zfs_snapshots", "configure_btrfs_snapshots"], + "configure_zfs_snapshots": ["zfs_scrub_timer_units"], + "install_maintenance_config": ["install_maintenance_thresholds"], +} + + +def function_body(name): + """The body of `name` from archsetup, comments and blank lines stripped, so + a match is a real invocation rather than a mention in a comment.""" + with open(ARCHSETUP) as f: + src = f.read() + start = src.index(f"\n{name}() {{\n") + end = src.index("\n}\n", start) + lines = src[start:end].splitlines()[1:] + keep = [] + for line in lines: + stripped = line.strip() + if not stripped or stripped.startswith("#"): + continue + keep.append(line.split(" #", 1)[0]) + return "\n".join(keep) + + +class CallSiteWiring(unittest.TestCase): + def test_every_guarded_helper_is_actually_called(self): + for caller, callees in CALL_SITES.items(): + body = function_body(caller) + for callee in callees: + with self.subTest(caller=caller, callee=callee): + self.assertRegex( + body, rf"(^|[\s;&|(]){callee}\b", + f"{caller} no longer calls {callee}; its own suite " + f"cannot see this") + + def test_the_check_would_notice_a_missing_call(self): + # The check is only worth having if it fails when the call goes away. + body = function_body("trim_firmware").replace("detect_gpu_vendors", "") + with self.assertRaises(AssertionError): + self.assertRegex(body, r"(^|[\s;&|(])detect_gpu_vendors\b") -- cgit v1.2.3