mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 20:07:04 +01:00
DNS: dnsmasq bind-dynamic, no ordering cycle, stunnel Wants=; retire pc_startup check; repo paths under ~/src
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
63465cffac
commit
deaf3ba80a
@ -0,0 +1,12 @@
|
||||
{
|
||||
"title": "DoT survives boot; service checker matches the machine",
|
||||
"objective": "stunnel-dot.service must be active after every boot without manual restarts, dnsmasq must not form an ordering cycle with network-online.target, and check_and_enable_services.sh must neither check the removed pc_startup feature nor resolve extracted repos at stale ~/<repo> paths.",
|
||||
"acceptance_criteria": [
|
||||
"Generated dnsmasq conf uses bind-dynamic and the drop-in has no network-online ordering (test_dns_units.sh)",
|
||||
"Generated stunnel-dot.service has Wants=dnsmasq.service and no Requires=dnsmasq (test_dot_resolver_install.sh)",
|
||||
"No startup_monitor references remain; the services suites pass at the coverage ratchet",
|
||||
"Host: stunnel-dot active and serving TLS on 10.8.0.1:853"
|
||||
],
|
||||
"out_of_scope": ["Firewall rules", "Applying compulsive-block wrappers or LeechBlock (guard warnings left for the owner)"],
|
||||
"verifier": "pre-commit (shell-coverage-ratchet in the namespace jail), vmbox behaviour check, setup_dot_resolver.sh --check on the host"
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
{
|
||||
"intent": "DNS-over-TLS (stunnel-dot) comes up at every boot, dnsmasq has no ordering cycle, and the service checker stops expecting the removed pc_startup feature and finds the extracted repos under ~/src.",
|
||||
"scope": [
|
||||
"linux_configuration/features/lib/dns_units.sh, dot_resolver_install.sh and their tests",
|
||||
"linux_configuration/periodic_background check_and_enable_services.sh, services_units.sh, services_report.sh and their tests",
|
||||
"Non-goal: the firewall, the blocklist feed, the guard warnings (compulsive-block, LeechBlock, workout-locker) this checker reports"
|
||||
],
|
||||
"changes": [
|
||||
"dnsmasq: bind-dynamic instead of bind-interfaces, so starting before enp6s0 exists no longer exits with 'unknown interface'",
|
||||
"dnsmasq drop-in: drop After/Wants=network-online.target, which cycled with the stock Before=network-online.target",
|
||||
"stunnel-dot.service: Wants=dnsmasq.service instead of Requires=, so one failed dnsmasq start no longer kills DoT until a manual restart",
|
||||
"check_and_enable_services: remove check_startup_monitor (pc_startup was removed in 765fa925) and default HOSTS_BLOCKER/DW/WORKOUT_LOCKER repos to ~/src/<repo>"
|
||||
],
|
||||
"verification": [
|
||||
{"command": "pre-commit run --files <the 11 files> (shell-coverage-ratchet runs the suites in the jail)", "result": "pass", "evidence": "all hooks passed, ratchet 100%"},
|
||||
{"command": "vmbox: dnsmasq with interface=<absent>, bind-interfaces vs bind-dynamic; Requires= vs Wants= on a failing dependency", "result": "pass", "evidence": "bind-interfaces: DIED 'unknown interface lanx0'; bind-dynamic: survived, bound 10.199.0.1:5353 after the interface appeared; Requires=: inactive; Wants=: active"},
|
||||
{"command": "host: setup_dot_resolver.sh + dns_units functions + validate_and_enable", "result": "pass", "evidence": "dnsmasq --test OK; stunnel-dot active on 10.8.0.1:853, TLSv1.3 Verification OK; DNS answers on 127.0.0.1 and 192.168.1.43; no network-online in dnsmasq After="},
|
||||
{"command": "sudo check_and_enable_services.sh --status (host) and vmbox diff against HEAD", "result": "pass", "evidence": "full run, no 'not found'; only diff vs HEAD is the removed PC Startup Monitor section"}
|
||||
],
|
||||
"risks": [
|
||||
"bind-dynamic also listens on addresses that appear later on enp6s0 (intended)",
|
||||
"stunnel now starts even if dnsmasq is down; queries fail until dnsmasq is back, which Restart=always plus the watchdog already handle"
|
||||
],
|
||||
"rollback": [
|
||||
"git revert this commit, then rerun setup_dns_blocker.sh setup and setup_dot_resolver.sh",
|
||||
"Validate with: systemctl is-active dnsmasq stunnel-dot; setup_dot_resolver.sh --check"
|
||||
]
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
{
|
||||
"intent": "Stop the Pre-commit checks workflow running the entire Python test suite a second time, when the Python tests workflow already runs it with the same coverage gate.",
|
||||
"scope": [
|
||||
".github/workflows/pre-commit.yml",
|
||||
"Non-goal: skipping any hook that is not duplicated elsewhere"
|
||||
],
|
||||
"changes": [
|
||||
"Run the hooks with SKIP=pytest-coverage. That hook invokes pytest_changed_packages.py, which runs every python_pkg suite with --cov-fail-under=100 -- exactly what the Python tests workflow does.",
|
||||
"Recorded in the workflow that this is skipped because it is DUPLICATED, not because it is slow, and that the skip must be dropped if the Python tests workflow ever goes away."
|
||||
],
|
||||
"verification": [
|
||||
{
|
||||
"command": "gh api .../runs/32645337532/jobs -- per-step timings for Pre-commit checks",
|
||||
"result": "pass",
|
||||
"evidence": "Run pre-commit hooks = 152s, the dominant step, against Install dependencies at 55s"
|
||||
},
|
||||
{
|
||||
"command": "gh run view 32645337532 --log | grep for the heavy hooks",
|
||||
"result": "pass",
|
||||
"evidence": "'pytest with coverage enforcement....Passed' confirms the suite really was running inside this job as well as in Python tests"
|
||||
},
|
||||
{
|
||||
"command": "Checked whether session-autopsy-hook-mutations (50s locally) also inflates CI",
|
||||
"result": "pass",
|
||||
"evidence": "It self-skips when ~/.claude/hooks is absent, which is the case on a runner, so it was not a CI cost and is left alone"
|
||||
},
|
||||
{
|
||||
"command": "python3 -c \"import yaml; yaml.safe_load(...)\"",
|
||||
"result": "pass",
|
||||
"evidence": "workflow parses as valid YAML"
|
||||
}
|
||||
],
|
||||
"risks": [
|
||||
"If the Python tests workflow is deleted or its path filters stop matching, the suite would no longer run in CI at all. The comment in the workflow names this dependency explicitly.",
|
||||
"A path-filter gap could mean a change runs Pre-commit checks but not Python tests. Both filters were widened earlier today to cover meta/requirements*.txt for exactly this reason."
|
||||
],
|
||||
"rollback": [
|
||||
"Remove the SKIP=pytest-coverage prefix from the Run pre-commit hooks step.",
|
||||
"After rollback, expect that step to return to roughly 150s."
|
||||
]
|
||||
}
|
||||
@ -14,8 +14,13 @@ write_dnsmasq_conf() {
|
||||
|
||||
# Listen only on the LAN interface (leaves 127.0.0.53 free for the
|
||||
# systemd-resolved stub that the /etc/hosts installer enables).
|
||||
# bind-dynamic, not bind-interfaces: at boot dnsmasq can start before
|
||||
# ${LAN_IFACE} exists, and bind-interfaces then dies with "unknown interface".
|
||||
# Its 5 s restart recovered, but stunnel-dot's start job had already failed on
|
||||
# the dependency and was never retried, so DoT stayed down every boot.
|
||||
# bind-dynamic binds the address whenever the interface appears.
|
||||
interface=${LAN_IFACE}
|
||||
bind-interfaces
|
||||
bind-dynamic
|
||||
|
||||
# Do NOT read /etc/hosts (huge + immutable); the blocklist comes from the feed.
|
||||
no-hosts
|
||||
@ -40,12 +45,10 @@ EOF
|
||||
install_restart_dropin() {
|
||||
ensure_dir "$DNSMASQ_DROPIN_DIR"
|
||||
cat >"$DNSMASQ_DROPIN" <<'EOF'
|
||||
# Managed by setup_dns_blocker.sh -- keep the resolver up and wait for the
|
||||
# network so bind-interfaces can bind the LAN address at boot.
|
||||
[Unit]
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
# Managed by setup_dns_blocker.sh -- keep the resolver up.
|
||||
# No network-online ordering: the stock unit is Before=network-online.target,
|
||||
# so After= here was an ordering cycle systemd broke by deleting a job at every
|
||||
# boot. bind-dynamic (dnsmasq.conf) makes waiting for the NIC unnecessary.
|
||||
[Service]
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
@ -51,7 +51,10 @@ install_units() {
|
||||
Description=DNS-over-TLS front end for dnsmasq blocklist
|
||||
After=network-online.target dnsmasq.service wg-quick@wg0.service
|
||||
Wants=network-online.target
|
||||
Requires=dnsmasq.service
|
||||
; Wants, not Requires: stunnel only forwards to 127.0.0.1:53 per connection,
|
||||
; and a Requires= turned one failed dnsmasq start at boot into a DoT outage
|
||||
; that lasted until someone restarted stunnel by hand.
|
||||
Wants=dnsmasq.service
|
||||
; Binding to the WireGuard address fails if the interface is not up yet.
|
||||
After=sys-devices-virtual-net-wg0.device
|
||||
|
||||
|
||||
56
linux_configuration/features/lib/tests/test_dns_units.sh
Executable file
56
linux_configuration/features/lib/tests/test_dns_units.sh
Executable file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tests for dns_units.sh -- the dnsmasq config and its systemd drop-in.
|
||||
#
|
||||
# Both regressions this guards were invisible to a presence check. With
|
||||
# bind-interfaces, dnsmasq died at every boot ("unknown interface enp6s0")
|
||||
# because it started before the NIC existed. The drop-in's
|
||||
# After=network-online.target formed an ordering cycle with the stock unit's
|
||||
# Before=network-online.target, and systemd broke it by deleting a job.
|
||||
#
|
||||
# Rendering writes only where it is told, so this suite needs no jail.
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=./features_harness.sh
|
||||
. "$SCRIPT_DIR/features_harness.sh"
|
||||
|
||||
_t_setup_env
|
||||
trap _t_teardown EXIT
|
||||
|
||||
ensure_dir() { mkdir -p "$1"; }
|
||||
log_info() { :; }
|
||||
|
||||
# shellcheck source=../dns_units.sh
|
||||
. "$SCRIPT_DIR/../dns_units.sh"
|
||||
|
||||
DNSMASQ_CONF="$TEST_TMPDIR/dnsmasq.d/lan-blocker.conf"
|
||||
DNSMASQ_DROPIN_DIR="$TEST_TMPDIR/dnsmasq.service.d"
|
||||
DNSMASQ_DROPIN="$DNSMASQ_DROPIN_DIR/blocker.conf"
|
||||
LAN_IFACE="enp6s0"
|
||||
LAN_IP="192.168.1.43"
|
||||
UPSTREAM="1.1.1.1"
|
||||
FEED="$TEST_TMPDIR/blocklist.hosts"
|
||||
LOG_FILE="$TEST_TMPDIR/dnsmasq.log"
|
||||
|
||||
write_dnsmasq_conf
|
||||
install_restart_dropin
|
||||
|
||||
printf '\n-- dnsmasq survives starting before the NIC exists --\n'
|
||||
_t_file_has "$DNSMASQ_CONF" '^interface=enp6s0$' "listens only on the LAN interface"
|
||||
_t_file_has "$DNSMASQ_CONF" '^bind-dynamic$' "binds the address whenever the interface appears"
|
||||
if grep -q '^bind-interfaces' "$DNSMASQ_CONF"; then
|
||||
_t_fail "bind-interfaces exits with 'unknown interface' when started before the NIC"
|
||||
else
|
||||
_t_pass "no bind-interfaces"
|
||||
fi
|
||||
|
||||
printf '\n-- the drop-in keeps it up without an ordering cycle --\n'
|
||||
_t_file_has "$DNSMASQ_DROPIN" '^Restart=always$' "restarts on any exit"
|
||||
if grep -qE '^(After|Wants|Requires)=.*network-online' "$DNSMASQ_DROPIN"; then
|
||||
_t_fail "network-online ordering cycles with the stock Before=network-online.target"
|
||||
else
|
||||
_t_pass "no network-online ordering"
|
||||
fi
|
||||
|
||||
printf '\n%d passed, %d failed\n' "$PASS" "$FAIL"
|
||||
[[ $FAIL -eq 0 ]]
|
||||
@ -86,6 +86,14 @@ _t_file_has "$STUNNEL_CONF" "cert = $CERT_DIR/combined.pem" "stunnel reads the s
|
||||
_t_stub systemctl
|
||||
install_units
|
||||
_t_file_has /etc/systemd/system/stunnel-dot.service 'stunnel' "stunnel unit installed"
|
||||
# Requires= turned one failed dnsmasq start at boot into a DoT outage that
|
||||
# outlived dnsmasq's own 5 s recovery; Wants= lets stunnel start regardless.
|
||||
_t_file_has /etc/systemd/system/stunnel-dot.service '^Wants=dnsmasq\.service$' "stunnel only Wants dnsmasq"
|
||||
if grep -q '^Requires=dnsmasq' /etc/systemd/system/stunnel-dot.service; then
|
||||
_t_fail "Requires=dnsmasq.service would fail stunnel whenever dnsmasq's first start fails"
|
||||
else
|
||||
_t_pass "no Requires=dnsmasq.service"
|
||||
fi
|
||||
_t_file_has /etc/systemd/system/dot-cert-sync.service "$SYNC_SCRIPT" "cert-sync service runs the sync script"
|
||||
_t_file_has /etc/systemd/system/dot-cert-sync.timer 'OnCalendar' "cert-sync timer is scheduled"
|
||||
_t_called 'daemon-reload' "units are followed by a daemon-reload"
|
||||
|
||||
@ -62,9 +62,12 @@ CONFIG_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||||
REAL_USER="${SUDO_USER:-${USER:-$(id -un)}}"
|
||||
REAL_HOME="$(getent passwd "$REAL_USER" 2>/dev/null | cut -d: -f6)"
|
||||
[[ -n $REAL_HOME ]] || REAL_HOME="/home/$REAL_USER"
|
||||
HOSTS_BLOCKER_REPO="${HOSTS_BLOCKER_DIR:-$REAL_HOME/hosts-blocker}"
|
||||
# The extracted repos live under ~/src since the home-tidy reorganisation.
|
||||
# These defaults still said ~/<repo> after it, so every "fix" below that runs
|
||||
# an installer from them pointed at a directory that no longer existed.
|
||||
HOSTS_BLOCKER_REPO="${HOSTS_BLOCKER_DIR:-$REAL_HOME/src/hosts-blocker}"
|
||||
# digital-wellbeing was EXTRACTED too (github.com/kuhyx/digital-wellbeing).
|
||||
DW_REPO="${DIGITAL_WELLBEING_DIR:-$REAL_HOME/digital-wellbeing}"
|
||||
DW_REPO="${DIGITAL_WELLBEING_DIR:-$REAL_HOME/src/digital-wellbeing}"
|
||||
|
||||
# Script paths
|
||||
PACMAN_WRAPPER_INSTALL="$DW_REPO/pacman/install_pacman_wrapper.sh"
|
||||
@ -73,7 +76,6 @@ MAKEPKG_WRAPPER_INSTALL="$DW_REPO/pacman/install_makepkg_wrapper.sh"
|
||||
PACMAN_WRAPPER_MANIFEST="/var/lib/pacman-wrapper/source.sha256"
|
||||
MAKEPKG_WRAPPER_MANIFEST="/var/lib/pacman-wrapper/makepkg-source.sha256"
|
||||
MIDNIGHT_SHUTDOWN_SCRIPT="$DW_REPO/setup_midnight_shutdown.sh"
|
||||
STARTUP_MONITOR_SCRIPT="$DW_REPO/setup_pc_startup_monitor.sh"
|
||||
PERIODIC_SYSTEM_SCRIPT="$CONFIG_DIR/periodic_background/setup_periodic_system.sh"
|
||||
# hosts-blocker was EXTRACTED (github.com/kuhyx/hosts-blocker). Resolved
|
||||
# below, after REAL_HOME is computed, for the same reason screen-locker is.
|
||||
@ -89,7 +91,7 @@ VBOX_HOSTS_SCRIPT="$DW_REPO/virtualbox/enforce_vbox_hosts.sh"
|
||||
# python_pkg/screen_locker/, which stopped existing at extraction time — the
|
||||
# result was check_workout_locker reporting a red "error" for a service that was
|
||||
# installed and enabled the whole time, while its "fix" silently did nothing.
|
||||
WORKOUT_LOCKER_REPO="$REAL_HOME/screen-locker"
|
||||
WORKOUT_LOCKER_REPO="$REAL_HOME/src/screen-locker"
|
||||
WORKOUT_LOCKER_INSTALL_SCRIPT="$WORKOUT_LOCKER_REPO/install_systemd.sh"
|
||||
WORKOUT_LOCKER_SCRIPT="$WORKOUT_LOCKER_REPO/screen_locker/screen_lock.py"
|
||||
HOSTS_INSTALL_SCRIPT="$HOSTS_BLOCKER_REPO/install.sh"
|
||||
@ -161,7 +163,6 @@ main() {
|
||||
check_pacman_wrapper
|
||||
check_makepkg_wrapper
|
||||
check_midnight_shutdown
|
||||
check_startup_monitor
|
||||
check_periodic_systems
|
||||
check_hosts
|
||||
check_compulsive_blocker
|
||||
|
||||
@ -38,7 +38,7 @@ print_summary() {
|
||||
printf "%-25s %s\n" "Service" "Status"
|
||||
printf "%-25s %s\n" "-------" "------"
|
||||
|
||||
for service in pacman_wrapper makepkg_wrapper midnight_shutdown startup_monitor periodic_systems hosts compulsive_blocker leechblock guest_mode_removal vbox_hosts workout_locker; do
|
||||
for service in pacman_wrapper makepkg_wrapper midnight_shutdown periodic_systems hosts compulsive_blocker leechblock guest_mode_removal vbox_hosts workout_locker; do
|
||||
local status
|
||||
status="$(get_service_status "$service")"
|
||||
local color
|
||||
|
||||
@ -57,49 +57,6 @@ check_midnight_shutdown() {
|
||||
enable
|
||||
}
|
||||
|
||||
check_startup_monitor() {
|
||||
header "PC Startup Monitor"
|
||||
|
||||
local status="ok"
|
||||
local issues=()
|
||||
|
||||
# Check timer (the timer triggers the service, so we check the timer)
|
||||
if systemctl is-enabled pc-startup-monitor.timer &>/dev/null; then
|
||||
msg "pc-startup-monitor.timer is enabled"
|
||||
else
|
||||
issues+=("pc-startup-monitor.timer is not enabled")
|
||||
status="error"
|
||||
fi
|
||||
|
||||
if systemctl is-active pc-startup-monitor.timer &>/dev/null; then
|
||||
msg "pc-startup-monitor.timer is active"
|
||||
else
|
||||
issues+=("pc-startup-monitor.timer is not active")
|
||||
if [[ $status != "error" ]]; then status="warning"; fi
|
||||
fi
|
||||
|
||||
# Check service file exists
|
||||
if [[ -f "${SYSROOT}/etc/systemd/system/pc-startup-monitor.service" ]]; then
|
||||
msg "pc-startup-monitor.service file exists"
|
||||
else
|
||||
issues+=("pc-startup-monitor.service file missing")
|
||||
status="error"
|
||||
fi
|
||||
|
||||
# Check monitor script
|
||||
if [[ -f "${SYSROOT}/usr/local/bin/pc-startup-check.sh" ]]; then
|
||||
msg "Startup check script exists"
|
||||
else
|
||||
issues+=("pc-startup-check.sh not found")
|
||||
status="error"
|
||||
fi
|
||||
|
||||
report_and_fix issues status "startup_monitor" \
|
||||
"Setting up startup monitor..." \
|
||||
"$STARTUP_MONITOR_SCRIPT" \
|
||||
"pc-startup-monitor.timer"
|
||||
}
|
||||
|
||||
check_periodic_systems() {
|
||||
header "Periodic System Maintenance"
|
||||
|
||||
|
||||
@ -186,7 +186,6 @@ export MAKEPKG_WRAPPER_INSTALL="${TEST_TMPDIR}/install_makepkg_wrapper.sh"
|
||||
export PACMAN_WRAPPER_MANIFEST="${TEST_TMPDIR}/pacman-source.sha256"
|
||||
export MAKEPKG_WRAPPER_MANIFEST="${TEST_TMPDIR}/makepkg-source.sha256"
|
||||
export MIDNIGHT_SHUTDOWN_SCRIPT="${TEST_TMPDIR}/setup_midnight_shutdown.sh"
|
||||
export STARTUP_MONITOR_SCRIPT="${TEST_TMPDIR}/setup_pc_startup_monitor.sh"
|
||||
export PERIODIC_SYSTEM_SCRIPT="${TEST_TMPDIR}/setup_periodic_system.sh"
|
||||
export HOSTS_INSTALL_SCRIPT="${TEST_TMPDIR}/hosts_install.sh"
|
||||
export GUARD_LIB_MIGRATE_SCRIPT="${TEST_TMPDIR}/migrate_hosts_guard.sh"
|
||||
|
||||
@ -31,9 +31,9 @@ reset_state
|
||||
set_service_status "pacman_wrapper" "ok"
|
||||
set_service_status "makepkg_wrapper" "warning"
|
||||
set_service_status "midnight_shutdown" "error"
|
||||
set_service_status "startup_monitor" "n/a"
|
||||
set_service_status "hosts" "n/a"
|
||||
set_service_status "periodic_systems" "skipped"
|
||||
# The remaining six keys are deliberately left unset so the ":-unknown"
|
||||
# The remaining five keys are deliberately left unset so the ":-unknown"
|
||||
# default and its *) colour arm are exercised too.
|
||||
ISSUES_FOUND=0
|
||||
out="$(print_summary)"
|
||||
|
||||
@ -28,26 +28,26 @@ echo "== report_and_fix: an ok service is recorded and left alone =="
|
||||
reset_state
|
||||
declare -a issues=()
|
||||
status="ok"
|
||||
report_and_fix issues status "startup_monitor" "fixing..." "$STARTUP_MONITOR_SCRIPT" "" >/dev/null
|
||||
_t_eq "ok" "$(get_service_status "startup_monitor")" "an ok status is recorded"
|
||||
report_and_fix issues status "midnight_shutdown" "fixing..." "$MIDNIGHT_SHUTDOWN_SCRIPT" "" >/dev/null
|
||||
_t_eq "ok" "$(get_service_status "midnight_shutdown")" "an ok status is recorded"
|
||||
_t_eq "0" "$ISSUES_FOUND" "an ok service counts no issues"
|
||||
_t_not_called 'ran setup_pc' "an ok service runs no installer"
|
||||
_t_not_called 'ran setup_midnight' "an ok service runs no installer"
|
||||
|
||||
echo "== report_and_fix: a warning is reported but never repaired =="
|
||||
reset_state
|
||||
make_installer "$STARTUP_MONITOR_SCRIPT"
|
||||
make_installer "$MIDNIGHT_SHUTDOWN_SCRIPT"
|
||||
issues=("timer is not active")
|
||||
status="warning"
|
||||
# Captured to a file rather than `$(...)`: report_and_fix mutates ISSUES_FOUND
|
||||
# and SERVICE_STATUS, and a command substitution would strand both in a
|
||||
# subshell, making the assertions below silently test nothing.
|
||||
report_and_fix issues status "startup_monitor" "fixing..." \
|
||||
"$STARTUP_MONITOR_SCRIPT" "" >"${TEST_TMPDIR}/out.txt"
|
||||
report_and_fix issues status "midnight_shutdown" "fixing..." \
|
||||
"$MIDNIGHT_SHUTDOWN_SCRIPT" "" >"${TEST_TMPDIR}/out.txt"
|
||||
out="$(cat "${TEST_TMPDIR}/out.txt")"
|
||||
_t_called_in "$out" "timer is not active" "the warning text is printed"
|
||||
_t_eq "1" "$ISSUES_FOUND" "a warning counts as an issue"
|
||||
_t_not_called 'ran setup_pc' "a warning does not trigger the installer"
|
||||
_t_eq "warning" "$(get_service_status "startup_monitor")" "the warning status is recorded"
|
||||
_t_not_called 'ran setup_midnight' "a warning does not trigger the installer"
|
||||
_t_eq "warning" "$(get_service_status "midnight_shutdown")" "the warning status is recorded"
|
||||
|
||||
echo "== report_and_fix: --status reports errors without repairing =="
|
||||
reset_state
|
||||
|
||||
@ -76,46 +76,6 @@ check_midnight_shutdown >/dev/null
|
||||
_t_not_called 'ran setup_midnight_shutdown' "--status never runs the setup script"
|
||||
_t_eq "error" "$(get_service_status "midnight_shutdown")" "the error is still recorded"
|
||||
|
||||
echo "== check_startup_monitor: fully healthy records ok =="
|
||||
reset_state
|
||||
make_installer "$STARTUP_MONITOR_SCRIPT"
|
||||
sysfile etc/systemd/system/pc-startup-monitor.service
|
||||
sysfile usr/local/bin/pc-startup-check.sh
|
||||
printf 'pc-startup-monitor.timer\n' >"${DEV}/enabled"
|
||||
printf 'pc-startup-monitor.timer\n' >"${DEV}/active"
|
||||
check_startup_monitor >/dev/null
|
||||
_t_eq "ok" "$(get_service_status "startup_monitor")" "a fully healthy install records ok"
|
||||
|
||||
echo "== check_startup_monitor: missing files are errors and are repaired =="
|
||||
reset_state
|
||||
make_installer "$STARTUP_MONITOR_SCRIPT"
|
||||
printf 'pc-startup-monitor.timer\n' >"${DEV}/enabled"
|
||||
printf 'pc-startup-monitor.timer\n' >"${DEV}/active"
|
||||
check_startup_monitor >/dev/null
|
||||
_t_called 'ran setup_pc_startup_monitor' "missing files run the setup script"
|
||||
|
||||
echo "== check_startup_monitor: timer disabled is downgraded to warning =="
|
||||
reset_state
|
||||
make_installer "$STARTUP_MONITOR_SCRIPT"
|
||||
sysfile etc/systemd/system/pc-startup-monitor.service
|
||||
sysfile usr/local/bin/pc-startup-check.sh
|
||||
: >"${DEV}/enabled"
|
||||
: >"${DEV}/active"
|
||||
check_startup_monitor >/dev/null
|
||||
# Same regression as check_midnight_shutdown above.
|
||||
_t_eq "error" "$(get_service_status "startup_monitor")" "disabled+inactive stays an error"
|
||||
_t_called 'ran setup_pc_startup_monitor' "so the disabled timer IS repaired"
|
||||
|
||||
echo "== check_startup_monitor: enabled but inactive is a warning, not a fix =="
|
||||
reset_state
|
||||
make_installer "$STARTUP_MONITOR_SCRIPT"
|
||||
sysfile etc/systemd/system/pc-startup-monitor.service
|
||||
sysfile usr/local/bin/pc-startup-check.sh
|
||||
printf 'pc-startup-monitor.timer\n' >"${DEV}/enabled"
|
||||
: >"${DEV}/active"
|
||||
check_startup_monitor >/dev/null
|
||||
_t_not_called 'ran setup_pc_startup_monitor' "an inactive-only timer is not reinstalled"
|
||||
|
||||
echo "== check_periodic_systems: every unit healthy short-circuits =="
|
||||
reset_state
|
||||
make_installer "$PERIODIC_SYSTEM_SCRIPT"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user