#!/bin/bash # Unit tests for netinfra/dns-cluster-setup/sync-zones.sh [#469] # Verifies reload-on-change behavior: Technitium restart fires only when # rsync actually changed zone files, and never on clean syncs. set -euo pipefail PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" SCRIPT="$PROJECT_ROOT/netinfra/dns-cluster-setup/sync-zones.sh" failed=0 TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT export LOG_FILE="$TMP/sync.log" # Script must exist and source cleanly (main guarded for sourcing) if [[ -f "$SCRIPT" ]] && (source "$SCRIPT"); then echo "✅ script exists + sources cleanly" else echo "❌ script missing or fails to source: $SCRIPT" exit 1 fi # shellcheck disable=SC1091 source "$SCRIPT" # Fake command log: record invocations of rsync / reload / find FAKE_BIN="$TMP/bin" mkdir -p "$FAKE_BIN" export PATH="$FAKE_BIN:$PATH" make_rsync() { # $1 = exit code, $2 = "changed" or "clean" (stdout of rsync) cat > "$FAKE_BIN/rsync" < "$FAKE_BIN/reload" <<'EOF' #!/bin/bash echo "reload-fired" >> "$RELOAD_LOG" EOF chmod +x "$FAKE_BIN/reload" } RELOAD_LOG="$TMP/reload.log" touch "$RELOAD_LOG" export RELOAD_LOG # find: minimal fake so zone counting works mkdir -p "$FAKE_BIN/find-dir" cat > "$FAKE_BIN/find" <<'EOF' #!/bin/bash # report 3 fake zone files regardless of args for i in 1 2 3; do echo "/zones/zone$i"; done EOF chmod +x "$FAKE_BIN/find" test_reload_fires_on_change() { make_rsync 0 "knel.net.zone" make_reload RELOAD_CMD=("$FAKE_BIN/reload") export RELOAD_CMD if sync_and_reload >/dev/null 2>&1 && [[ "$(cat "$RELOAD_LOG")" == "reload-fired" ]]; then echo "✅ reload fires when rsync reports changed zones" else echo "❌ reload did not fire on changed sync" ((++failed)) fi : > "$RELOAD_LOG" } test_no_reload_on_clean_sync() { make_rsync 0 "" make_reload RELOAD_CMD=("$FAKE_BIN/reload") export RELOAD_CMD if sync_and_reload >/dev/null 2>&1 && [[ ! -s "$RELOAD_LOG" ]]; then echo "✅ no reload on clean sync" else echo "❌ reload fired (or errored) on clean sync" ((++failed)) fi } test_rsync_failure_propagates() { make_rsync 23 "" RELOAD_CMD=("$FAKE_BIN/reload") export RELOAD_CMD if ! sync_and_reload >/dev/null 2>&1; then echo "✅ rsync failure propagates non-zero rc" else echo "❌ rsync failure was swallowed" ((++failed)) fi if [[ ! -s "$RELOAD_LOG" ]]; then echo "✅ no reload attempted after rsync failure" else echo "❌ reload fired despite rsync failure" ((++failed)) fi } test_reload_failure_does_not_break_sync() { make_rsync 0 "knel.net.zone" RELOAD_CMD=("/bin/false") export RELOAD_CMD if sync_and_reload >/dev/null 2>&1; then echo "✅ reload failure does not fail the sync run" else echo "❌ reload failure failed the whole sync" ((++failed)) fi } test_reload_fires_on_change test_no_reload_on_clean_sync test_rsync_failure_propagates test_reload_failure_does_not_break_sync if ((failed > 0)); then echo "❌ $failed sync-zones test(s) failed" exit 1 fi echo "✅ all sync-zones tests passed"