#!/usr/bin/env bash
# test-sc-watchdog — exercise tools/sc-watchdog.sh against a FAKE unit and a FAKE
# audio server. Touches nothing real: no scsynth, no sclang, no sound, no MIDI.
#
# It exists because the first version of the watchdog was only testable by killing
# the real audio server on PLN's desk, five days before a gig. It flapped, and the
# flap was discovered by a human hearing four notifications rather than by a test.
#
# The fake reproduces the exact topology that made the bug possible:
#   fake-lang  (the unit's MainPID, stays alive)
#     └── fake-server  (the child that actually dies)
# — which is why systemd reports the unit healthy while the "audio" is gone.
#
#   tools/tests/test-sc-watchdog.sh        # ~90s

set -uo pipefail
cd "$(dirname "$0")/../.." || exit 1

TMP=$(mktemp -d); trap 'cleanup' EXIT
UNIT="scwd-test-$$.service"
PROC="scwdfake$$"
STATE="$TMP/restarts"
WD_PID=""

PASS=0; FAIL=0
ok()   { printf '  \033[32mok\033[0m   %s\n' "$1"; PASS=$((PASS+1)); }
bad()  { printf '  \033[31mFAIL\033[0m %s\n' "$1"; FAIL=$((FAIL+1)); }

cleanup() {
  [ -n "$WD_PID" ] && kill "$WD_PID" 2>/dev/null
  systemctl --user stop "$UNIT" 2>/dev/null
  systemctl --user reset-failed "$UNIT" 2>/dev/null
  pkill -x "$PROC" 2>/dev/null
  rm -rf "$TMP"
}

# --- the fake server: a distinctly-named binary so pgrep -x can find it ----------
cp "$(command -v sleep)" "$TMP/$PROC"

# --- the fake sclang: spawns the server as a CHILD and outlives it ---------------
cat > "$TMP/fake-lang.sh" <<EOF
#!/usr/bin/env bash
"$TMP/$PROC" infinity &
# Deliberately does NOT exit when the child dies — this is the whole point.
while true; do sleep 1; done
EOF
chmod +x "$TMP/fake-lang.sh"

echo "test-sc-watchdog: fake unit=$UNIT fake server=$PROC"

systemd-run --user --unit="$UNIT" --quiet \
  --property=Restart=no --property=Type=simple \
  "$TMP/fake-lang.sh" || { echo "could not create transient unit"; exit 1; }
sleep 2

pgrep -x "$PROC" >/dev/null && ok "fake server running under fake unit" \
                            || bad "fake server did not start"

# --- 1. THE CORE CLAIM: unit stays 'active' while its audio child is dead --------
pkill -x "$PROC"; sleep 1
if systemctl --user is-active --quiet "$UNIT" && ! pgrep -x "$PROC" >/dev/null; then
  ok "unit reports active while the server is DEAD (the bug this all exists for)"
else
  bad "could not reproduce the green-unit-no-sound state"
fi

# --- 2. the watchdog notices and restarts ---------------------------------------
# SCWD_NO_NOTIFY=1: a test must never page a human about a fake unit. The first run
# fired real STICKY notifications naming scwd-test-<pid>.service, which reached PLN
# after the test had exited and after that unit had ceased to exist.
SCWD_UNIT="$UNIT" SCWD_PROC="$PROC" SCWD_STATE="$STATE" SCWD_NO_NOTIFY=1 \
  ./tools/sc-watchdog.sh >"$TMP/wd.log" 2>&1 &
WD_PID=$!

for i in $(seq 1 20); do sleep 2; pgrep -x "$PROC" >/dev/null && break; done
if pgrep -x "$PROC" >/dev/null; then ok "watchdog restarted the unit; server is back"
else bad "watchdog did not recover the server"; fi

# --- 3. THE REGRESSION: the watchdog must SURVIVE the restart it issues ----------
# The first version had PartOf= in its unit, so restarting the supervisee killed the
# supervisor and zeroed its rate-limit counter, making MAX_RESTARTS unreachable.
if kill -0 "$WD_PID" 2>/dev/null; then
  ok "watchdog survived issuing the restart (no PartOf self-kill)"
else
  bad "watchdog DIED issuing the restart — the PartOf flap bug is back"
fi

# --- 4. the rate limiter actually bites -----------------------------------------
# Kill repeatedly; after MAX_RESTARTS (3) in the window it must give up and STOP
# restarting, rather than looping forever.
for i in 1 2 3 4; do pkill -x "$PROC" 2>/dev/null; sleep 12; done
sleep 5
n=$(grep -c 'restarting' "$TMP/wd.log" 2>/dev/null || echo 0)
if [ "$n" -le 3 ]; then ok "rate limiter held: $n restart(s), max 3"
else bad "rate limiter did NOT hold: $n restarts (unbounded flap)"; fi

if grep -q 'GIVING UP' "$TMP/wd.log" 2>/dev/null; then
  ok "gave up loudly instead of flapping"
else
  bad "never logged GIVING UP (expected after exceeding the limit)"
fi

# --- 5. a deliberate stop must NOT be resurrected --------------------------------
systemctl --user stop "$UNIT" 2>/dev/null; sleep 8
if ! systemctl --user is-active --quiet "$UNIT"; then
  ok "respected a deliberate stop (did not resurrect it)"
else
  bad "resurrected a unit PLN stopped on purpose"
fi

echo
echo "--- watchdog log ---"; sed 's/^/  /' "$TMP/wd.log"
echo
printf 'test-sc-watchdog: %d passed, %d failed\n' "$PASS" "$FAIL"
[ "$FAIL" -eq 0 ]
