mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 19:27:03 +01:00
Test arch_hardware.sh to 100%, fix its dead journal vacuum (90 -> 89)
94/94 lines through run_all.sh at --min 100, exit 0. 42 assertions over 26 cases across all five functions, including both boot-loader flavours and the no-boot-loader path. PRODUCTION BUG, found by writing the tests and confirmed against this host: tweak_journal's regex required a space before the unit, but journalctl prints "305.5M in the file system" with no separator. The size check never matched, so the vacuum was unreachable and a multi-gigabyte journal would never have been trimmed. This is the third instance of the same defect -- arch_perf_report.sh:36,65 carried it too -- so the fix is identical: the separator is now optional. One case asserts the spaced form still matches, making this a widening. The mitigation tweak edits the boot loader, so /boot/loader/entries, /etc/default/grub and grub.cfg are now behind overrides defaulting to the real paths. This machine's boot configuration is never touched. _t_hide gets a cache: it symlinks every executable on PATH (13.5k here) and was rebuilding that farm on every call, which took the suite to 92s and pushed a jail case past its 120s timeout. Now 77s, and arch_cpu.sh re-measures at 57/57 so the shared change cost nothing. The cases are split across two files because a single one was 307 lines and file-length-cap rejected the first commit attempt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b4b6908d69
commit
88ba911641
@ -0,0 +1,18 @@
|
||||
{
|
||||
"title": "Clear arch_hardware.sh and fix its unreachable journal vacuum",
|
||||
"objective": "Bring arch_hardware.sh to 100% measured line coverage, repair the size regex that made its journal vacuum unreachable, and remove its allowlist exemption, finishing the optimize_arch_desktop.sh family's measurable libs.",
|
||||
"acceptance_criteria": [
|
||||
"The jail reports arch_hardware.sh at 100.00% through tests/run_all.sh, at --min 100, exiting 0 with no case timeout.",
|
||||
"check_shell_coverage.sh passes on arch_hardware.sh with its allowlist line removed.",
|
||||
"tweak_journal vacuums a journal reported as '4.2G' (no space, the form journalctl actually prints) AND one reported as '4.2 G', and leaves '305.5M' alone -- so the fix is a widening, not a swap.",
|
||||
"All five functions are covered, including both boot-loader flavours, the no-boot-loader case, and an empty loader-entries directory.",
|
||||
"arch_cpu.sh still measures 100.00%, proving the shared _t_hide change did not regress the previously cleared lib.",
|
||||
"The suite stays green and shellcheck reports nothing, with zero suppressions."
|
||||
],
|
||||
"out_of_scope": [
|
||||
"arch_sysctl.sh's kcov registration failure, which stays on the allowlist.",
|
||||
"Changing the coverage instrument or the jail's default case timeout.",
|
||||
"The identical journal regex in any lib other than arch_hardware.sh; arch_perf_report.sh was fixed in an earlier session."
|
||||
],
|
||||
"verifier": "timeout 900s bash meta/scripts/shell_coverage_jail.sh --subject linux_configuration/scripts/single_use/fixes/lib/tests/run_all.sh --measure arch_hardware.sh --min 100 --fail-on-case-error -- \"\" (expects 94/94 = 100.00%, exit 0), then the same for arch_cpu.sh, then check_shell_coverage.sh on arch_hardware.sh."
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
{
|
||||
"intent": "Test arch_hardware.sh to 100% line coverage, fix an unreachable journal-vacuum branch found while writing those tests, and take the lib off the shell coverage allowlist.",
|
||||
"scope": [
|
||||
"linux_configuration/scripts/single_use/fixes/lib/arch_hardware.sh (one bug fix plus test seams)",
|
||||
"linux_configuration/scripts/single_use/fixes/lib/tests/test_arch_hardware.sh and test_arch_hardware_boot.sh (new, split to stay under the 250-line cap)",
|
||||
"linux_configuration/scripts/single_use/fixes/lib/tests/arch_desktop_harness.sh (boot-loader overrides)",
|
||||
"linux_configuration/scripts/single_use/fixes/lib/tests/lib_test_core.sh (_t_hide caching)",
|
||||
"meta/shell-coverage-allowlist.txt (one line removed)"
|
||||
],
|
||||
"changes": [
|
||||
"PRODUCTION BUG FIX: tweak_journal's size regex required a space before the unit, but journalctl prints '305.5M' and '4.2G' with no separator, so the vacuum branch was unreachable and a multi-gigabyte journal would never have been vacuumed. The unit separator is now optional, the same defect and the same fix as arch_perf_report.sh:36,65 already carried. Verified against this host's real output.",
|
||||
"Added SYSTEMD_UNIT_DIR, JOURNALD_CONF_DIR, LOADER_ENTRIES_DIR, GRUB_DEFAULT_FILE and GRUB_CFG_FILE overrides, each defaulting to the real path, so the mitigation tweak can be tested without touching this machine's boot configuration",
|
||||
"Added the arch_hardware tests: 42 assertions over 26 cases across all five functions, split across test_arch_hardware.sh (fstrim/nvidia, 16) and test_arch_hardware_boot.sh (mitigations/nm/journal/ananicy, 26) because a single file was 307 lines and the file-length-cap hook rejected the commit",
|
||||
"Cached _t_hide's shim farm in lib_test_core.sh: it symlinks every executable on PATH (~13.5k on this host) and was rebuilt on every call, which pushed a jail case past its 120s timeout"
|
||||
],
|
||||
"verification": [
|
||||
{
|
||||
"command": "journalctl --disk-usage",
|
||||
"result": "pass",
|
||||
"evidence": "'Archived and active journals take up 305.5M in the file system.' -- no space before the unit, which is what proved the old regex could never match."
|
||||
},
|
||||
{
|
||||
"command": "bash -c 'u=\"...4.2G...\"; [[ $u =~ ([0-9]+\\.?[0-9]*)\\ ?G ]]'",
|
||||
"result": "pass",
|
||||
"evidence": "The fixed regex matches 4.2G; case 19 asserts the spaced form still matches, so the change is a widening and not a swap."
|
||||
},
|
||||
{
|
||||
"command": "shell_coverage_jail.sh --subject .../tests/run_all.sh --measure arch_hardware.sh --min 100 --fail-on-case-error",
|
||||
"result": "pass",
|
||||
"evidence": "arch_hardware.sh: 94/94 lines = 100.00%, exit 0, no case timeout, re-confirmed after the file split."
|
||||
},
|
||||
{
|
||||
"command": "shell_coverage_jail.sh ... --measure arch_cpu.sh --min 100 --fail-on-case-error",
|
||||
"result": "pass",
|
||||
"evidence": "arch_cpu.sh: 57/57 = 100.00% still, so the _t_hide change did not regress the lib cleared in the previous commit."
|
||||
},
|
||||
{
|
||||
"command": "bash meta/scripts/check_shell_coverage.sh .../fixes/lib/arch_hardware.sh (allowlist line removed)",
|
||||
"result": "pass",
|
||||
"evidence": "check_shell_coverage.sh: every checked shell library meets the coverage bar. Allowlist 90 -> 89."
|
||||
},
|
||||
{
|
||||
"command": "bash linux_configuration/scripts/single_use/fixes/lib/tests/run_all.sh",
|
||||
"result": "pass",
|
||||
"evidence": "All fixes lib test files passed; arch_hardware: 42 passed, 0 failed. Suite runtime 92s -> 77s after the caching."
|
||||
},
|
||||
{
|
||||
"command": "bash meta/scripts/check_file_length.sh equivalent via pre-commit file-length-cap",
|
||||
"result": "pass",
|
||||
"evidence": "test_arch_hardware.sh 121 lines and test_arch_hardware_boot.sh 212 lines, both under the 250-line cap; the 307-line single file had aborted the first commit attempt."
|
||||
}
|
||||
],
|
||||
"risks": [
|
||||
"The journal fix changes production behaviour by design: a machine with a multi-gigabyte journal will now actually be vacuumed to 300M on the next run, which is what the code always intended",
|
||||
"Two assertions initially passed for the wrong reason because a pacman stub tested $3 when `pacman -Qi <pkg>` puts the package in $2; both now fail if that indexing is wrong",
|
||||
"_t_hide's cache is keyed by the tool list, so a caller that expects a rebuilt farm within one test file gets the cached one; the farm's contents depend only on that key",
|
||||
"lib_test_core.sh is now 240 lines, close to the 250-line cap; the next addition to it needs a split."
|
||||
],
|
||||
"rollback": [
|
||||
"git revert the commit, then re-add the arch_hardware.sh line to meta/shell-coverage-allowlist.txt",
|
||||
"Note that reverting restores the unreachable journal-vacuum branch; re-run check_shell_coverage.sh to confirm the gate passes with the exemption back"
|
||||
]
|
||||
}
|
||||
@ -42,7 +42,7 @@ tweak_nvidia_gpu() {
|
||||
nvidia-smi -gps 0 >/dev/null 2>&1 || true
|
||||
|
||||
# Persist via systemd service
|
||||
local service_file="/etc/systemd/system/nvidia-performance.service"
|
||||
local service_file="${SYSTEMD_UNIT_DIR:-/etc/systemd/system}/nvidia-performance.service"
|
||||
if [[ ! -f $service_file ]]; then
|
||||
cat >"$service_file" <<'NVSVC'
|
||||
[Unit]
|
||||
@ -83,9 +83,14 @@ tweak_mitigations() {
|
||||
|
||||
# Detect boot loader
|
||||
local boot_method=""
|
||||
if [[ -d /boot/loader/entries ]]; then
|
||||
# Both boot-loader locations are behind overrides defaulting to the real
|
||||
# paths, so a test can present a systemd-boot or a GRUB machine without
|
||||
# touching this host's boot configuration.
|
||||
local entries_dir="${LOADER_ENTRIES_DIR:-/boot/loader/entries}"
|
||||
local grub_default="${GRUB_DEFAULT_FILE:-/etc/default/grub}"
|
||||
if [[ -d $entries_dir ]]; then
|
||||
boot_method="systemd-boot"
|
||||
elif [[ -f /etc/default/grub ]]; then
|
||||
elif [[ -f $grub_default ]]; then
|
||||
boot_method="grub"
|
||||
else
|
||||
log_warn "Could not detect boot loader — skipping mitigation tweak."
|
||||
@ -95,7 +100,7 @@ tweak_mitigations() {
|
||||
|
||||
if [[ $boot_method == "systemd-boot" ]]; then
|
||||
local entry
|
||||
entry=$(find /boot/loader/entries -name '*.conf' -print -quit 2>/dev/null || true)
|
||||
entry=$(find "$entries_dir" -name '*.conf' -print -quit 2>/dev/null || true)
|
||||
if [[ -n $entry ]]; then
|
||||
if grep -q 'mitigations=off' "$entry" 2>/dev/null; then
|
||||
log_ok "mitigations=off already set in systemd-boot — skipping."
|
||||
@ -107,12 +112,12 @@ tweak_mitigations() {
|
||||
log_warn "This trades security for ~5-15% performance. Only for isolated desktops."
|
||||
fi
|
||||
elif [[ $boot_method == "grub" ]]; then
|
||||
if grep -q 'mitigations=off' /etc/default/grub 2>/dev/null; then
|
||||
if grep -q 'mitigations=off' "$grub_default" 2>/dev/null; then
|
||||
log_ok "mitigations=off already set in GRUB — skipping."
|
||||
return 0
|
||||
fi
|
||||
sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 mitigations=off"/' /etc/default/grub
|
||||
grub-mkconfig -o /boot/grub/grub.cfg
|
||||
sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 mitigations=off"/' "$grub_default"
|
||||
grub-mkconfig -o "${GRUB_CFG_FILE:-/boot/grub/grub.cfg}"
|
||||
log_warn "Added mitigations=off to GRUB config. REBOOT REQUIRED."
|
||||
fi
|
||||
|
||||
@ -140,7 +145,11 @@ tweak_journal() {
|
||||
usage_line=$(journalctl --disk-usage 2>/dev/null || true)
|
||||
|
||||
local needs_vacuum=false
|
||||
if [[ $usage_line =~ ([0-9]+\.?[0-9]*)\ G ]]; then
|
||||
# The space before the unit is OPTIONAL: journalctl prints "305.5M in the
|
||||
# file system", with no separator, so requiring one made this check --
|
||||
# and the vacuum below it -- unreachable. Same defect as
|
||||
# arch_perf_report.sh carried before it was fixed.
|
||||
if [[ $usage_line =~ ([0-9]+\.?[0-9]*)\ ?G ]]; then
|
||||
needs_vacuum=true
|
||||
fi
|
||||
|
||||
@ -150,7 +159,7 @@ tweak_journal() {
|
||||
log_ok "Journal already under 1GiB."
|
||||
fi
|
||||
|
||||
local dropin_dir="/etc/systemd/journald.conf.d"
|
||||
local dropin_dir="${JOURNALD_CONF_DIR:-/etc/systemd/journald.conf.d}"
|
||||
local dropin_file="$dropin_dir/size-limit.conf"
|
||||
|
||||
if [[ -f $dropin_file ]] && grep -q 'SystemMaxUse=300M' "$dropin_file"; then
|
||||
|
||||
@ -43,6 +43,11 @@ export CPUPOWER_CONF_FILE="${TEST_TMPDIR}/cpupower"
|
||||
# not have (a rotational disk, a core not on the performance governor).
|
||||
export CPU_SYSFS_ROOT="${TEST_TMPDIR}/sys_cpu"
|
||||
export BLOCK_SYSFS_ROOT="${TEST_TMPDIR}/sys_block"
|
||||
# arch_hardware.sh's mitigation tweak edits the boot loader configuration;
|
||||
# these keep a test off this machine's real /boot and /etc/default/grub.
|
||||
export LOADER_ENTRIES_DIR="${TEST_TMPDIR}/loader_entries"
|
||||
export GRUB_DEFAULT_FILE="${TEST_TMPDIR}/grub_default"
|
||||
export GRUB_CFG_FILE="${TEST_TMPDIR}/grub.cfg"
|
||||
export SYSTEMD_UNIT_DIR="${TEST_TMPDIR}/systemd_units"
|
||||
export JOURNALD_CONF_DIR="${TEST_TMPDIR}/journald.conf.d"
|
||||
export DRY_RUN="false"
|
||||
@ -85,7 +90,7 @@ apply_tweak() {
|
||||
_arch_desktop_default_stubs() {
|
||||
local tool
|
||||
for tool in sysctl modprobe udevadm cpupower systemctl nvidia-smi \
|
||||
lsblk lscpu journalctl pacman; do
|
||||
lsblk lscpu journalctl pacman grub-mkconfig nvidia-persistenced; do
|
||||
_t_stub "$tool" 'exit 0'
|
||||
done
|
||||
}
|
||||
@ -103,7 +108,8 @@ arch_desktop_reset() {
|
||||
"${JOURNALD_CONF_DIR}" "${CPU_SYSFS_ROOT}" "${BLOCK_SYSFS_ROOT}"
|
||||
mkdir -p "${SYSCTL_DROPIN_DIR}" "${UDEV_RULES_DIR}" "${SYSTEMD_UNIT_DIR}" \
|
||||
"${JOURNALD_CONF_DIR}" "${CPU_SYSFS_ROOT}" "${BLOCK_SYSFS_ROOT}"
|
||||
rm -f "${CPUPOWER_CONF_FILE}"
|
||||
rm -f "${CPUPOWER_CONF_FILE}" "${GRUB_DEFAULT_FILE}" "${GRUB_CFG_FILE}"
|
||||
rm -rf "${LOADER_ENTRIES_DIR}"
|
||||
_t_full_path
|
||||
_arch_desktop_default_stubs
|
||||
}
|
||||
|
||||
@ -160,8 +160,18 @@ _t_unstub() {
|
||||
# Instead a shim dir is built containing a symlink to every real executable
|
||||
# on PATH EXCEPT the hidden ones, and PATH is pointed at it.
|
||||
_t_hide() {
|
||||
local hide_dir="${TEST_TMPDIR}/hidden_path"
|
||||
rm -rf "$hide_dir"
|
||||
# Keyed by the tool list and reused: the farm holds a symlink per
|
||||
# executable on PATH (~13.5k on this host), so rebuilding it on every
|
||||
# call dominated the suite's runtime and pushed a jail case past its
|
||||
# 120s timeout. The same hidden set always yields the same farm, so the
|
||||
# second and later calls are a PATH assignment.
|
||||
local key="${*}"
|
||||
local hide_dir="${TEST_TMPDIR}/hidden_path/${key// /_}"
|
||||
if [[ -d "$hide_dir" ]]; then
|
||||
PATH="${FAKE_BIN}:${hide_dir}"
|
||||
hash -r
|
||||
return 0
|
||||
fi
|
||||
mkdir -p "$hide_dir"
|
||||
|
||||
local -A hidden=()
|
||||
|
||||
120
linux_configuration/scripts/single_use/fixes/lib/tests/test_arch_hardware.sh
Executable file
120
linux_configuration/scripts/single_use/fixes/lib/tests/test_arch_hardware.sh
Executable file
@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env bash
|
||||
# lib/tests/test_arch_hardware.sh — arch_hardware (fstrim/nvidia) — tests for tweak_fstrim and tweak_nvidia_gpu.
|
||||
#
|
||||
# Split from the mitigation/journal/ananicy cases in
|
||||
# test_arch_hardware_boot.sh to hold every file under the 250-line cap.
|
||||
# fstrim.timer, an NVIDIA card, a boot loader, a journal size. Every case
|
||||
# therefore stubs the probe and, where the lib writes, points it at the
|
||||
# throwaway tmpdir through the harness's overrides.
|
||||
#
|
||||
# Calls go through _t_run rather than `out="$(...)"`: command substitution
|
||||
# forks a subshell, and kcov does not register a lib whose first execution
|
||||
# happens inside one.
|
||||
set -uo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# shellcheck source=arch_desktop_harness.sh
|
||||
. "${SCRIPT_DIR}/arch_desktop_harness.sh"
|
||||
|
||||
# shellcheck source=../arch_hardware.sh
|
||||
. "${FIXES_DIR}/lib/arch_hardware.sh"
|
||||
|
||||
printf '\n-- tweak_fstrim --\n'
|
||||
|
||||
# Case 1: already enabled -> skip.
|
||||
arch_desktop_reset
|
||||
_t_stub systemctl 'exit 0'
|
||||
_t_run tweak_fstrim
|
||||
_t_eq "0" "$?" "tweak_fstrim: returns 0 when already enabled"
|
||||
_t_contains "$out" "already enabled" "tweak_fstrim: reports the skip"
|
||||
_t_lacks "$(_t_calls)" "systemctl enable --now fstrim.timer" \
|
||||
"tweak_fstrim: does not re-enable"
|
||||
|
||||
# Case 2: not enabled -> enable it.
|
||||
arch_desktop_reset
|
||||
_t_stub_stdin systemctl <<'STUB'
|
||||
[[ $1 == is-enabled ]] && exit 1
|
||||
exit 0
|
||||
STUB
|
||||
_t_run tweak_fstrim
|
||||
_t_contains "$(_t_calls)" "systemctl enable --now fstrim.timer" \
|
||||
"tweak_fstrim: enables the timer when it is off"
|
||||
|
||||
printf '\n-- tweak_nvidia_gpu --\n'
|
||||
|
||||
# Case 3: no NVIDIA card at all.
|
||||
arch_desktop_reset
|
||||
_t_unstub nvidia-smi
|
||||
_t_hide nvidia-smi
|
||||
_t_run tweak_nvidia_gpu
|
||||
_t_eq "0" "$?" "tweak_nvidia_gpu: returns 0 without nvidia-smi"
|
||||
_t_contains "$out" "nvidia-smi not found" "tweak_nvidia_gpu: reports the skip"
|
||||
_t_full_path
|
||||
|
||||
# Case 4: persistence mode already on -> not re-enabled, but the unit is
|
||||
# still installed.
|
||||
arch_desktop_reset
|
||||
_t_stub_stdin nvidia-smi <<'STUB'
|
||||
[[ $1 == --query-gpu=persistence_mode ]] && { echo "Enabled"; exit 0; }
|
||||
exit 0
|
||||
STUB
|
||||
_t_unstub nvidia-persistenced
|
||||
_t_hide nvidia-persistenced
|
||||
_t_run tweak_nvidia_gpu
|
||||
_t_contains "$out" "already enabled" "tweak_nvidia_gpu: reports persistence already on"
|
||||
_t_lacks "$(_t_calls)" "nvidia-smi -pm 1" "tweak_nvidia_gpu: does not re-enable persistence"
|
||||
_t_contains "$(cat "${SYSTEMD_UNIT_DIR}/nvidia-performance.service")" \
|
||||
"ExecStart=/usr/bin/nvidia-smi -pm 1" "tweak_nvidia_gpu: writes the unit"
|
||||
_t_contains "$(_t_calls)" "systemctl daemon-reload" "tweak_nvidia_gpu: reloads systemd"
|
||||
_t_full_path
|
||||
|
||||
# Case 5: persistence mode off -> turned on.
|
||||
arch_desktop_reset
|
||||
_t_stub_stdin nvidia-smi <<'STUB'
|
||||
[[ $1 == --query-gpu=persistence_mode ]] && { echo "Disabled"; exit 0; }
|
||||
exit 0
|
||||
STUB
|
||||
_t_unstub nvidia-persistenced
|
||||
_t_hide nvidia-persistenced
|
||||
_t_run tweak_nvidia_gpu
|
||||
_t_contains "$(_t_calls)" "nvidia-smi -pm 1" "tweak_nvidia_gpu: enables persistence mode"
|
||||
_t_contains "$out" "persistence mode enabled" "tweak_nvidia_gpu: logs the change"
|
||||
_t_full_path
|
||||
|
||||
# Case 6: an existing unit file is not rewritten.
|
||||
arch_desktop_reset
|
||||
_t_stub nvidia-smi 'exit 0'
|
||||
printf 'CUSTOM UNIT\n' >"${SYSTEMD_UNIT_DIR}/nvidia-performance.service"
|
||||
_t_unstub nvidia-persistenced
|
||||
_t_hide nvidia-persistenced
|
||||
_t_run tweak_nvidia_gpu
|
||||
_t_eq "CUSTOM UNIT" "$(cat "${SYSTEMD_UNIT_DIR}/nvidia-performance.service")" \
|
||||
"tweak_nvidia_gpu: leaves an existing unit alone"
|
||||
_t_full_path
|
||||
|
||||
# Case 7: nvidia-persistenced present but inactive -> enabled AND started.
|
||||
arch_desktop_reset
|
||||
_t_stub nvidia-smi 'exit 0'
|
||||
_t_stub nvidia-persistenced 'exit 0'
|
||||
_t_stub_stdin systemctl <<'STUB'
|
||||
[[ $1 == is-active ]] && exit 1
|
||||
exit 0
|
||||
STUB
|
||||
_t_run tweak_nvidia_gpu
|
||||
_t_contains "$(_t_calls)" "systemctl enable nvidia-persistenced.service" \
|
||||
"tweak_nvidia_gpu: enables nvidia-persistenced"
|
||||
_t_contains "$(_t_calls)" "systemctl start nvidia-persistenced.service" \
|
||||
"tweak_nvidia_gpu: starts an inactive nvidia-persistenced"
|
||||
|
||||
# Case 8: nvidia-persistenced already active -> enabled but NOT started.
|
||||
arch_desktop_reset
|
||||
_t_stub nvidia-smi 'exit 0'
|
||||
_t_stub nvidia-persistenced 'exit 0'
|
||||
_t_stub systemctl 'exit 0'
|
||||
_t_run tweak_nvidia_gpu
|
||||
_t_lacks "$(_t_calls)" "systemctl start nvidia-persistenced.service" \
|
||||
"tweak_nvidia_gpu: does not start an already-active persistenced"
|
||||
|
||||
printf '\narch_hardware (fstrim/nvidia): %d passed, %d failed\n' "$PASS" "$FAIL"
|
||||
[[ $FAIL -eq 0 ]]
|
||||
@ -0,0 +1,211 @@
|
||||
#!/usr/bin/env bash
|
||||
# lib/tests/test_arch_hardware_boot.sh — arch_hardware (boot/journal) — tweak_mitigations, tweak_nm_wait_online, tweak_journal and tweak_ananicy.
|
||||
#
|
||||
# Split from test_arch_hardware.sh to hold every file under the 250-line cap.
|
||||
# fstrim.timer, an NVIDIA card, a boot loader, a journal size. Every case
|
||||
# therefore stubs the probe and, where the lib writes, points it at the
|
||||
# throwaway tmpdir through the harness's overrides.
|
||||
#
|
||||
# Calls go through _t_run rather than `out="$(...)"`: command substitution
|
||||
# forks a subshell, and kcov does not register a lib whose first execution
|
||||
# happens inside one.
|
||||
set -uo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# shellcheck source=arch_desktop_harness.sh
|
||||
. "${SCRIPT_DIR}/arch_desktop_harness.sh"
|
||||
|
||||
# shellcheck source=../arch_hardware.sh
|
||||
. "${FIXES_DIR}/lib/arch_hardware.sh"
|
||||
|
||||
printf '\n-- tweak_mitigations --\n'
|
||||
|
||||
# Case 9: not aggressive -> nothing happens.
|
||||
arch_desktop_reset
|
||||
_t_run tweak_mitigations
|
||||
_t_eq "0" "$?" "tweak_mitigations: returns 0 without --aggressive"
|
||||
_t_contains "$out" "use --aggressive" "tweak_mitigations: explains how to opt in"
|
||||
|
||||
# Case 10: aggressive, but no boot loader found.
|
||||
arch_desktop_reset
|
||||
AGGRESSIVE="true"
|
||||
_t_run tweak_mitigations
|
||||
_t_contains "$out" "Could not detect boot loader" \
|
||||
"tweak_mitigations: warns when no boot loader is present"
|
||||
|
||||
# Case 11: systemd-boot, mitigations not yet set -> appended to the options line.
|
||||
arch_desktop_reset
|
||||
AGGRESSIVE="true"
|
||||
mkdir -p "${LOADER_ENTRIES_DIR}"
|
||||
printf 'title Arch\noptions root=/dev/sda2 rw\n' >"${LOADER_ENTRIES_DIR}/arch.conf"
|
||||
_t_run tweak_mitigations
|
||||
_t_contains "$(cat "${LOADER_ENTRIES_DIR}/arch.conf")" "rw mitigations=off" \
|
||||
"tweak_mitigations: appends to the systemd-boot options line"
|
||||
_t_contains "$out" "REBOOT REQUIRED" "tweak_mitigations: warns a reboot is needed"
|
||||
|
||||
# Case 12: systemd-boot, already set -> left alone.
|
||||
arch_desktop_reset
|
||||
AGGRESSIVE="true"
|
||||
mkdir -p "${LOADER_ENTRIES_DIR}"
|
||||
printf 'options root=/dev/sda2 rw mitigations=off\n' >"${LOADER_ENTRIES_DIR}/arch.conf"
|
||||
_t_run tweak_mitigations
|
||||
_t_contains "$out" "already set in systemd-boot" \
|
||||
"tweak_mitigations: reports systemd-boot already configured"
|
||||
|
||||
# Case 13: systemd-boot directory present but EMPTY -> no entry, no crash.
|
||||
arch_desktop_reset
|
||||
AGGRESSIVE="true"
|
||||
mkdir -p "${LOADER_ENTRIES_DIR}"
|
||||
_t_run tweak_mitigations
|
||||
_t_eq "0" "$?" "tweak_mitigations: survives an empty loader entries dir"
|
||||
|
||||
# Case 14: GRUB, not yet set -> cmdline rewritten and grub-mkconfig run.
|
||||
arch_desktop_reset
|
||||
AGGRESSIVE="true"
|
||||
printf 'GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"\n' >"${GRUB_DEFAULT_FILE}"
|
||||
_t_run tweak_mitigations
|
||||
_t_contains "$(cat "${GRUB_DEFAULT_FILE}")" 'quiet splash mitigations=off' \
|
||||
"tweak_mitigations: appends to the GRUB cmdline"
|
||||
_t_contains "$(_t_calls)" "grub-mkconfig" "tweak_mitigations: regenerates the GRUB config"
|
||||
|
||||
# Case 15: GRUB, already set -> left alone.
|
||||
arch_desktop_reset
|
||||
AGGRESSIVE="true"
|
||||
printf 'GRUB_CMDLINE_LINUX_DEFAULT="quiet mitigations=off"\n' >"${GRUB_DEFAULT_FILE}"
|
||||
_t_run tweak_mitigations
|
||||
_t_contains "$out" "already set in GRUB" "tweak_mitigations: reports GRUB already configured"
|
||||
_t_lacks "$(_t_calls)" "grub-mkconfig" "tweak_mitigations: does not regenerate when unchanged"
|
||||
|
||||
printf '\n-- tweak_nm_wait_online --\n'
|
||||
|
||||
# Case 16: already disabled -> skip.
|
||||
arch_desktop_reset
|
||||
_t_stub systemctl 'exit 1'
|
||||
_t_run tweak_nm_wait_online
|
||||
_t_contains "$out" "already disabled" "tweak_nm_wait_online: reports the skip"
|
||||
|
||||
# Case 17: enabled -> disabled.
|
||||
arch_desktop_reset
|
||||
_t_stub systemctl 'exit 0'
|
||||
_t_run tweak_nm_wait_online
|
||||
_t_contains "$(_t_calls)" "systemctl disable NetworkManager-wait-online.service" \
|
||||
"tweak_nm_wait_online: disables the service"
|
||||
|
||||
printf '\n-- tweak_journal --\n'
|
||||
|
||||
# Case 18: a multi-gigabyte journal IS vacuumed. journalctl prints "4.2G"
|
||||
# with NO space before the unit, which is exactly what the old regex missed:
|
||||
# it required one, so this branch could never run on a real machine.
|
||||
arch_desktop_reset
|
||||
_t_stub_stdin journalctl <<'STUB'
|
||||
[[ $1 == --disk-usage ]] && {
|
||||
echo "Archived and active journals take up 4.2G in the file system."
|
||||
exit 0
|
||||
}
|
||||
exit 0
|
||||
STUB
|
||||
_t_run tweak_journal
|
||||
_t_contains "$(_t_calls)" "journalctl --vacuum-size=300M" \
|
||||
"tweak_journal: vacuums a 4.2G journal printed without a space"
|
||||
|
||||
# Case 19: the spaced form still matches, so the fix is a widening.
|
||||
arch_desktop_reset
|
||||
_t_stub_stdin journalctl <<'STUB'
|
||||
[[ $1 == --disk-usage ]] && {
|
||||
echo "Archived and active journals take up 4.2 G in the file system."
|
||||
exit 0
|
||||
}
|
||||
exit 0
|
||||
STUB
|
||||
_t_run tweak_journal
|
||||
_t_contains "$(_t_calls)" "journalctl --vacuum-size=300M" \
|
||||
"tweak_journal: still vacuums when the unit is spaced"
|
||||
|
||||
# Case 20: a megabyte-sized journal is left alone.
|
||||
arch_desktop_reset
|
||||
_t_stub_stdin journalctl <<'STUB'
|
||||
[[ $1 == --disk-usage ]] && {
|
||||
echo "Archived and active journals take up 305.5M in the file system."
|
||||
exit 0
|
||||
}
|
||||
exit 0
|
||||
STUB
|
||||
_t_run tweak_journal
|
||||
_t_lacks "$(_t_calls)" "journalctl --vacuum-size=300M" \
|
||||
"tweak_journal: does not vacuum a 305.5M journal"
|
||||
_t_contains "$out" "already under 1GiB" "tweak_journal: reports the journal is small"
|
||||
_t_contains "$(cat "${JOURNALD_CONF_DIR}/size-limit.conf")" "SystemMaxUse=300M" \
|
||||
"tweak_journal: writes the size cap drop-in"
|
||||
_t_contains "$(_t_calls)" "systemctl restart systemd-journald" \
|
||||
"tweak_journal: restarts journald after writing the cap"
|
||||
|
||||
# Case 21: the cap is already configured -> not rewritten, journald not restarted.
|
||||
arch_desktop_reset
|
||||
_t_stub journalctl 'exit 0'
|
||||
printf '[Journal]\nSystemMaxUse=300M\n' >"${JOURNALD_CONF_DIR}/size-limit.conf"
|
||||
_t_run tweak_journal
|
||||
_t_contains "$out" "size cap already configured" \
|
||||
"tweak_journal: reports the cap is already in place"
|
||||
_t_lacks "$(_t_calls)" "systemctl restart systemd-journald" \
|
||||
"tweak_journal: does not restart journald when nothing changed"
|
||||
|
||||
printf '\n-- tweak_ananicy --\n'
|
||||
|
||||
# Case 22: ananicy-cpp already enabled -> skip.
|
||||
arch_desktop_reset
|
||||
_t_stub systemctl 'exit 0'
|
||||
_t_run tweak_ananicy
|
||||
_t_contains "$out" "ananicy-cpp is already enabled" "tweak_ananicy: reports the skip"
|
||||
|
||||
# Case 23: ananicy-cpp installed but not enabled -> enabled.
|
||||
arch_desktop_reset
|
||||
_t_stub_stdin systemctl <<'STUB'
|
||||
[[ $1 == is-enabled ]] && exit 1
|
||||
exit 0
|
||||
STUB
|
||||
_t_stub pacman 'exit 0'
|
||||
_t_run tweak_ananicy
|
||||
_t_contains "$(_t_calls)" "systemctl enable --now ananicy-cpp.service" \
|
||||
"tweak_ananicy: enables ananicy-cpp when the package is installed"
|
||||
|
||||
# Case 24: only the original ananicy is installed, and it is not enabled.
|
||||
arch_desktop_reset
|
||||
_t_stub_stdin systemctl <<'STUB'
|
||||
[[ $1 == is-enabled ]] && exit 1
|
||||
exit 0
|
||||
STUB
|
||||
_t_stub_stdin pacman <<'STUB'
|
||||
[[ $2 == ananicy-cpp ]] && exit 1
|
||||
exit 0
|
||||
STUB
|
||||
_t_run tweak_ananicy
|
||||
_t_contains "$(_t_calls)" "systemctl enable --now ananicy.service" \
|
||||
"tweak_ananicy: falls back to the original ananicy"
|
||||
|
||||
# Case 25: the original ananicy is installed AND already enabled.
|
||||
arch_desktop_reset
|
||||
_t_stub_stdin systemctl <<'STUB'
|
||||
[[ $1 == is-enabled && $2 == ananicy-cpp.service ]] && exit 1
|
||||
exit 0
|
||||
STUB
|
||||
_t_stub_stdin pacman <<'STUB'
|
||||
[[ $2 == ananicy-cpp ]] && exit 1
|
||||
exit 0
|
||||
STUB
|
||||
_t_run tweak_ananicy
|
||||
_t_contains "$out" "ananicy is already enabled" \
|
||||
"tweak_ananicy: reports the original ananicy already enabled"
|
||||
|
||||
# Case 26: neither package installed -> the AUR hint.
|
||||
arch_desktop_reset
|
||||
_t_stub_stdin systemctl <<'STUB'
|
||||
[[ $1 == is-enabled ]] && exit 1
|
||||
exit 0
|
||||
STUB
|
||||
_t_stub pacman 'exit 1'
|
||||
_t_run tweak_ananicy
|
||||
_t_contains "$out" "yay -S ananicy-cpp" "tweak_ananicy: prints the AUR install hint"
|
||||
|
||||
printf '\narch_hardware (boot/journal): %d passed, %d failed\n' "$PASS" "$FAIL"
|
||||
[[ $FAIL -eq 0 ]]
|
||||
@ -73,7 +73,6 @@ linux_configuration/scripts/single_use/features/lib/website_build.sh
|
||||
linux_configuration/scripts/single_use/features/lib/wg_firewall.sh
|
||||
linux_configuration/scripts/single_use/features/lib/wg_keys.sh
|
||||
linux_configuration/scripts/single_use/features/lib/wg_sshd.sh
|
||||
linux_configuration/scripts/single_use/fixes/lib/arch_hardware.sh
|
||||
linux_configuration/scripts/single_use/fixes/lib/arch_sysctl.sh
|
||||
linux_configuration/scripts/single_use/fixes/lib/bt_adapter.sh
|
||||
linux_configuration/scripts/single_use/fixes/lib/hosts_guard_migrate.sh
|
||||
|
||||
Loading…
Reference in New Issue
Block a user