Files
omarchy/test/shell.d/fprintd-resume-migration-test.sh
T
72c152a288 Retry systemd reload in the fingerprint recovery migration (#14260)
* Retry systemd reload after installing fingerprint recovery

A failed reload leaves the migration pending with the drop-in already installed. Reload existing configuration on retry so completion means systemd has applied the stop timeout, while preserving administrator changes.

Co-Authored-By: Codex Medium <317366263+omarchybot@users.noreply.github.com>

* Avoid sudo for an already-applied fingerprint repair

Migration completion belongs to each user, while the systemd repair is machine-wide. Query systemd reload state without elevation and reload only stale configuration, so interrupted repairs still retry and later users can complete without sudo. A failed state query remains a migration failure.

Co-Authored-By: Greptile <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: Omarchybot <317366263+omarchybot@users.noreply.github.com>
Co-authored-by: Greptile <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-10-04 13:29:38 -04:00

151 lines
6.3 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
source "$(dirname "${BASH_SOURCE[0]}")/base-test.sh"
migration=$(grep -rl 'Install the fingerprint resume hook on existing fingerprint setups' "$ROOT/migrations" | head -n 1 || true)
[[ -n $migration ]] || fail "fprintd resume hook migration exists"
TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT
# The migration installs to a system path via sudo; stub it so the test writes
# into a temp tree instead of /usr.
stub_bin="$TMPDIR/bin"
mkdir -p "$stub_bin"
cat >"$stub_bin/sudo" <<'STUB'
#!/bin/bash
[[ ${REFUSE_SUDO:-0} != 1 ]] || exit 1
exec "$@"
STUB
chmod +x "$stub_bin/sudo"
reload_log="$TMPDIR/systemctl-calls"
dropin_dst="$TMPDIR/fprintd.service.d/10-stop-timeout.conf"
applied_dropin="$TMPDIR/applied-drop-in"
cat >"$stub_bin/systemctl" <<STUB
#!/bin/bash
printf '%s\n' "\$*" >>"$reload_log"
case "\$*" in
'show fprintd.service --property=NeedDaemonReload --value')
[[ \${FAIL_QUERY:-0} == 0 ]] || exit 1
if cmp -s "$dropin_dst" "$applied_dropin"; then
echo no
else
echo yes
fi
;;
daemon-reload)
[[ \${FAIL_RELOAD:-0} == 0 ]] || exit 1
cp "$dropin_dst" "$applied_dropin"
;;
*) exit 99 ;;
esac
STUB
chmod +x "$stub_bin/systemctl"
src="$TMPDIR/fprintd-resume"
printf '#!/bin/bash\n' >"$src"
chmod +x "$src"
dst="$TMPDIR/system-sleep/fprintd-resume"
dropin_src="$TMPDIR/10-stop-timeout.conf"
printf '[Service]\nTimeoutStopSec=3s\n' >"$dropin_src"
lock_pam="$TMPDIR/omarchy-lock-fingerprint"
# omarchy-migrate runs each migration with `bash -euo pipefail`; match it.
run_migration() {
PATH="$stub_bin:$PATH" \
OMARCHY_FPRINTD_RESUME_SRC="$src" \
OMARCHY_FPRINTD_RESUME_DST="$dst" \
OMARCHY_FPRINTD_STOP_TIMEOUT_SRC="$dropin_src" \
OMARCHY_FPRINTD_STOP_TIMEOUT_DST="$dropin_dst" \
OMARCHY_LOCK_FINGERPRINT_PAM="$lock_pam" \
bash -euo pipefail "$migration" >/dev/null
}
# The migration exits clean when its source is missing, so a hook moved
# without updating it would silently install nothing and mark itself done.
# Run once against the real default source under the repo to pin that path.
rm -rf "$TMPDIR/system-sleep" "$TMPDIR/fprintd.service.d"
: >"$lock_pam"
PATH="$stub_bin:$PATH" \
OMARCHY_PATH="$ROOT" \
OMARCHY_FPRINTD_RESUME_DST="$dst" \
OMARCHY_FPRINTD_STOP_TIMEOUT_DST="$dropin_dst" \
OMARCHY_LOCK_FINGERPRINT_PAM="$lock_pam" \
bash -euo pipefail "$migration" >/dev/null ||
fail "migration exits clean from its default sources"
[[ -x $dst ]] || fail "migration finds the hook at its default source path" "dst: $(stat -c '%A' "$dst" 2>/dev/null || echo missing)"
cmp -s "$dst" "$ROOT/default/systemd/system-sleep/fprintd-resume" || fail "migration installs the shipped hook from its default source"
cmp -s "$dropin_dst" "$ROOT/default/systemd/system/fprintd.service.d/10-stop-timeout.conf" || fail "migration installs the shipped drop-in from its default source"
pass "migration installs the shipped hook and drop-in from their default sources"
# A machine with fingerprint configured but no hook yet gets it, executable,
# plus the stop-timeout drop-in, and systemd is told about the drop-in.
: >"$lock_pam"
rm -rf "$TMPDIR/system-sleep" "$TMPDIR/fprintd.service.d"
: >"$reload_log"
run_migration
[[ -x $dst ]] || fail "migration installs the hook, executable" "dst: $(stat -c '%A' "$dst" 2>/dev/null || echo missing)"
pass "migration installs the hook, executable"
[[ $(stat -c '%a' "$dropin_dst" 2>/dev/null) == "644" ]] || fail "migration installs the stop-timeout drop-in" "dst: $(stat -c '%A' "$dropin_dst" 2>/dev/null || echo missing)"
grep -qx "daemon-reload" "$reload_log" || fail "migration reloads systemd after installing the drop-in" "calls: $(<"$reload_log")"
pass "migration installs the stop-timeout drop-in and reloads systemd"
rm -f "$dropin_dst"
rm -f "$applied_dropin"
: >"$reload_log"
if FAIL_RELOAD=1 run_migration; then
fail "migration remains pending when daemon-reload fails"
fi
[[ -f $dropin_dst ]] || fail "reload failure occurs after the drop-in is installed"
run_migration
[[ $(grep -c '^daemon-reload$' "$reload_log") == 2 ]] || fail "migration retries reload even when the drop-in already exists"
pass "migration retries a failed reload after installing the drop-in"
# Existing files may precede an interrupted reload; preserve them and reload.
printf 'sentinel\n' >>"$dst"
printf '# sentinel\n' >>"$dropin_dst"
: >"$reload_log"
run_migration
grep -q sentinel "$dst" || fail "migration leaves an existing hook alone"
grep -q sentinel "$dropin_dst" || fail "migration leaves an existing drop-in alone"
grep -qx "daemon-reload" "$reload_log" || fail "migration reloads existing configuration before completing" "calls: $(<"$reload_log")"
pass "migration leaves existing files alone"
: >"$reload_log"
REFUSE_SUDO=1 run_migration || fail "later users finish an applied repair without sudo"
if grep -qx "daemon-reload" "$reload_log"; then
fail "later users finish an applied repair without sudo"
fi
pass "later users finish an applied repair without sudo"
if FAIL_QUERY=1 run_migration; then
fail "migration remains pending when reload state cannot be queried"
fi
pass "migration propagates reload-state query failure"
# An unnumbered drop-in may belong to the administrator; never replace it.
legacy="$TMPDIR/fprintd.service.d/stop-timeout.conf"
rm -f "$dropin_dst"; printf '[Service]\nTimeoutStopSec=15s\n' >"$legacy"
cp "$legacy" "$TMPDIR/saved-admin-timeout"
: >"$reload_log"
run_migration
cmp -s "$legacy" "$TMPDIR/saved-admin-timeout" || fail "migration preserves the administrator's unnumbered drop-in"
[[ -f $dropin_dst ]] || fail "migration installs the numbered drop-in alongside the administrator's file"
grep -qx "daemon-reload" "$reload_log" || fail "migration reloads systemd after installing the numbered drop-in"
pass "migration preserves the administrator's unnumbered drop-in"
# The drop-in is installed on its own where only the hook is already present.
rm -rf "$TMPDIR/fprintd.service.d"
run_migration
[[ -f $dropin_dst ]] || fail "migration adds the drop-in beside an existing hook"
pass "migration adds the drop-in beside an existing hook"
# No fingerprint configured -> nothing to fix, so nothing is installed.
rm -f "$lock_pam"
rm -rf "$TMPDIR/system-sleep" "$TMPDIR/fprintd.service.d"
run_migration
[[ ! -e $dst && ! -e $dropin_dst ]] || fail "migration skips machines without fingerprint configured"
pass "migration skips machines without fingerprint configured"