From 2d54765f6fb06acca736e2e80eff316b63b5fdaa Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Mon, 14 Sep 2026 21:53:54 +0200 Subject: [PATCH] Read the load average through LOADAVG_FILE so the probe tests are host-independent The "flags nothing on a quiet machine" case read the real /proc/loadavg and went red whenever a game was running on the host (22/16 during a BeamNG session), and the "flags a load at/above thread count" case had to SKIP whenever the host was idle. Same override pattern as JOURNALD_CONF_DIR: the harness writes a fixture, both cases now assert deterministically, and a missing file degrades to 0 as before. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01SS8M5wk88nJTXxDWz61KKk --- ...erf-probes-loadavg-fixture-2026-09-14.json | 29 +++++++++++++++++++ .../fixes/lib/arch_perf_probes.sh | 4 ++- .../fixes/lib/tests/arch_perf_harness.sh | 4 +++ .../fixes/lib/tests/test_arch_perf_probes.sh | 23 +++++++++------ 4 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 docs/superpowers/evidence/perf-probes-loadavg-fixture-2026-09-14.json diff --git a/docs/superpowers/evidence/perf-probes-loadavg-fixture-2026-09-14.json b/docs/superpowers/evidence/perf-probes-loadavg-fixture-2026-09-14.json new file mode 100644 index 00000000..f8edd39b --- /dev/null +++ b/docs/superpowers/evidence/perf-probes-loadavg-fixture-2026-09-14.json @@ -0,0 +1,29 @@ +{ + "intent": "Make the arch_perf_probes lib tests independent of the host's real load average so the pre-push ci-mirror gate is not red whenever a game is running.", + "scope": [ + "linux_configuration/fixes/lib/arch_perf_probes.sh (LOADAVG_FILE override, default /proc/loadavg)", + "linux_configuration/fixes/lib/tests/arch_perf_harness.sh (fixture written by arch_reset)", + "linux_configuration/fixes/lib/tests/test_arch_perf_probes.sh (deterministic load cases)" + ], + "changes": [ + "collect_basics reads the 1-minute load from ${LOADAVG_FILE:-/proc/loadavg}; behaviour on the host is unchanged", + "The harness exports LOADAVG_FILE into TEST_TMPDIR and arch_reset writes a quiet fixture (0.10)", + "The load test now asserts the (16/16) finding from a 16.50 fixture instead of SKIPping when the host is idle; a missing file case asserts no finding" + ], + "verification": [ + { + "command": "./linux_configuration/fixes/lib/tests/test_arch_perf_probes.sh", + "result": "pass", + "evidence": "arch_perf_probes (basics/governor): 17 passed, 0 failed (was 16 with one SKIP, and 1 failed at host load 22/16)" + }, + { + "command": "./linux_configuration/fixes/lib/tests/run_all.sh (host load ~19/16, BeamNG running)", + "result": "pass", + "evidence": "All fixes lib test files passed." + } + ], + "risks": ["None on the host: the default path is the real /proc/loadavg"], + "rollback": [ + "git revert the commit; the tests return to reading the real load and go red under host load" + ] +} diff --git a/linux_configuration/fixes/lib/arch_perf_probes.sh b/linux_configuration/fixes/lib/arch_perf_probes.sh index 1dd84001..302901ce 100755 --- a/linux_configuration/fixes/lib/arch_perf_probes.sh +++ b/linux_configuration/fixes/lib/arch_perf_probes.sh @@ -19,7 +19,9 @@ collect_basics() { local cpu_count cpu_count=$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1) local load1 - load1=$(awk '{print int($1)}' /proc/loadavg 2>/dev/null || echo 0) + # Overridable so the tests do not depend on the host being idle: the + # "quiet machine" case went red whenever a game was running on the host. + load1=$(awk '{print int($1)}' "${LOADAVG_FILE:-/proc/loadavg}" 2>/dev/null || echo 0) if [[ ${load1:-0} -ge ${cpu_count:-1} ]]; then add_finding "1-minute load average is at/above CPU thread count (${load1}/${cpu_count}); background tasks may be saturating the system." fi diff --git a/linux_configuration/fixes/lib/tests/arch_perf_harness.sh b/linux_configuration/fixes/lib/tests/arch_perf_harness.sh index ca9e7e8a..1d31fab9 100755 --- a/linux_configuration/fixes/lib/tests/arch_perf_harness.sh +++ b/linux_configuration/fixes/lib/tests/arch_perf_harness.sh @@ -37,6 +37,9 @@ export REPORT_FILE="${TEST_TMPDIR}/report.log" export JOURNALD_CONF_DIR="${TEST_TMPDIR}/journald.conf.d" export SYSTEMD_UNIT_DIR="${TEST_TMPDIR}/systemd_units" export ORGANIZE_SCRIPT_CANDIDATES="${TEST_TMPDIR}/organize_downloads.sh" +# collect_basics reads the 1-minute load from here; a fixture, not the real +# /proc/loadavg, or the "quiet machine" case depends on nothing else running. +export LOADAVG_FILE="${TEST_TMPDIR}/loadavg" export APPLY_SAFE_FIXES="false" export INSTALL_TOOLS="false" declare -a FINDINGS=() @@ -85,6 +88,7 @@ arch_reset() { rm -rf "${JOURNALD_CONF_DIR}" "${SYSTEMD_UNIT_DIR}" mkdir -p "${JOURNALD_CONF_DIR}" "${SYSTEMD_UNIT_DIR}" rm -f "${ORGANIZE_SCRIPT_CANDIDATES}" + echo "0.10 0.20 0.30 1/100 1" >"${LOADAVG_FILE}" _t_full_path _arch_default_stubs } diff --git a/linux_configuration/fixes/lib/tests/test_arch_perf_probes.sh b/linux_configuration/fixes/lib/tests/test_arch_perf_probes.sh index c9968332..842c0d03 100755 --- a/linux_configuration/fixes/lib/tests/test_arch_perf_probes.sh +++ b/linux_configuration/fixes/lib/tests/test_arch_perf_probes.sh @@ -67,20 +67,25 @@ _t_contains "$findings" "ACPI errors detected" \ _t_contains "$findings" "Xorg is using high CPU (45%)" \ "collect_basics: flags a CPU-hungry Xorg" -# A load average at or above the thread count is flagged. /proc/loadavg is -# read directly by the lib, so the case is driven by a low CPU count instead. +# A load average at or above the thread count is flagged. arch_reset -_t_stub getconf 'echo 1' +_t_stub getconf 'echo 16' _t_stub systemctl 'exit 0' _t_stub journalctl 'exit 0' _t_stub ps 'echo none' +echo "16.50 12.00 9.00 3/900 1" >"${LOADAVG_FILE}" collect_basics -if [[ $(awk '{print int($1)}' /proc/loadavg) -ge 1 ]]; then - _t_contains "$(_t_findings)" "load average is at/above CPU thread count" \ - "collect_basics: flags a load average at or above the thread count" -else - _t_pass "collect_basics: SKIP load case (this host's 1-minute load is below 1)" -fi +_t_contains "$(_t_findings)" "load average is at/above CPU thread count (16/16)" \ + "collect_basics: flags a load average at or above the thread count" + +# An unreadable load file degrades to 0 rather than aborting the probe. +arch_reset +_t_stub systemctl 'exit 0' +_t_stub journalctl 'exit 0' +_t_stub ps 'echo none' +rm -f "${LOADAVG_FILE}" +collect_basics +_t_eq "" "$(_t_findings)" "collect_basics: missing load file is not a finding" # --- check_cpu_governor -----------------------------------------------------