#!/usr/bin/env bash
# Regression test for wait-for.sh. Stubs the poll command with sandbox scripts so
# a condition can be made never-true, eventually-true, stuck, or exit-code driven.
# No live network, no real waiting beyond a few seconds.
#
# Covers:
#   1. never-true -> exit 2 (timeout) within the bound, last state reported
#   2. stuck value -> exit 3 before the timeout would fire, value reported
#   3. eventually-true -> exit 0, satisfying state reported
#   4. exit-code mode (no --expect) -> exit 0 when poll flips to rc 0
#   5. usage error (missing --timeout) -> exit 64
#   6. a hung poll cannot block past the timeout (per-poll cap)
#   7. overshoot: a large --interval never overruns --timeout
#   8. --stuck-after without --expect -> exit 64
#   9. --stuck-after 0 -> exit 64
set -u

HELPER="$(cd "$(dirname "$0")/.." && pwd)/wait-for.sh"
[ -x "$HELPER" ] || { echo "FAIL: $HELPER not executable" >&2; exit 1; }

PASS=0; FAIL=0
ok()  { echo "PASS: $1"; PASS=$((PASS+1)); }
bad() { echo "FAIL: $1" >&2; FAIL=$((FAIL+1)); }

SANDBOX=$(mktemp -d)
trap 'rm -rf "$SANDBOX"' EXIT

# Stub: always prints a fixed never-satisfying state.
NEVER="$SANDBOX/never.sh"
cat > "$NEVER" <<'EOF'
#!/usr/bin/env bash
echo "ssl=active http=401"
EOF
chmod +x "$NEVER"

# Stub: prints http=401 for the first 2 reads, http=200 after (counter file).
EVENTUAL="$SANDBOX/eventual.sh"
cat > "$EVENTUAL" <<'EOF'
#!/usr/bin/env bash
C="$1"; n=$(cat "$C" 2>/dev/null || echo 0); n=$((n+1)); echo "$n" > "$C"
if [ "$n" -ge 3 ]; then echo "ssl=active http=200"; else echo "ssl=active http=401"; fi
EOF
chmod +x "$EVENTUAL"

# Stub: exits 1 until a flag file exists, then exits 0 (exit-code mode).
FLIP="$SANDBOX/flip.sh"
cat > "$FLIP" <<'EOF'
#!/usr/bin/env bash
C="$1"; F="$2"; n=$(cat "$C" 2>/dev/null || echo 0); n=$((n+1)); echo "$n" > "$C"
if [ "$n" -ge 2 ]; then : > "$F"; fi
[ -e "$F" ] && exit 0 || exit 1
EOF
chmod +x "$FLIP"

run() {  # $1 label; rest = helper args. Sets OUT/RC/ELAPSED.
  local label="$1"; shift
  local of t0 t1
  of=$(mktemp); t0=$(date +%s)
  bash "$HELPER" "$@" >"$of" 2>/dev/null
  RC=$?; t1=$(date +%s); ELAPSED=$((t1 - t0)); OUT=$(cat "$of"); rm -f "$of"
}

# 1. never-true -> timeout (exit 2), bounded, last state reported
run "never" --timeout 2 --interval 1 --expect 'http=200' -- "$NEVER"
[ "$RC" -eq 2 ] && ok "never exits 2 (timeout)" || bad "never exit=$RC want 2"
echo "$OUT" | grep -q "http=401" && ok "never reports last state" || bad "never out='$OUT'"
[ "$ELAPSED" -le 4 ] && ok "never stays within bound (${ELAPSED}s)" || bad "never ran ${ELAPSED}s"

# 2. stuck -> exit 3 early, value reported
run "stuck" --timeout 30 --interval 1 --expect 'http=200' --stuck-after 3 -- "$NEVER"
[ "$RC" -eq 3 ] && ok "stuck exits 3" || bad "stuck exit=$RC want 3"
echo "$OUT" | grep -q "http=401" && ok "stuck reports value" || bad "stuck out='$OUT'"
[ "$ELAPSED" -lt 10 ] && ok "stuck fires before timeout (${ELAPSED}s)" || bad "stuck ran ${ELAPSED}s"

# 3. eventually-true -> exit 0
run "eventual" --timeout 10 --interval 1 --expect 'http=200' -- "$EVENTUAL" "$SANDBOX/ec"
[ "$RC" -eq 0 ] && ok "eventual exits 0 (met)" || bad "eventual exit=$RC want 0"
echo "$OUT" | grep -q "http=200" && ok "eventual reports met state" || bad "eventual out='$OUT'"

# 4. exit-code mode -> exit 0 on flip
run "flip" --timeout 10 --interval 1 -- "$FLIP" "$SANDBOX/fc" "$SANDBOX/flag"
[ "$RC" -eq 0 ] && ok "flip exits 0 (exit-code mode)" || bad "flip exit=$RC want 0"

# 5. usage error -> exit 64
run "usage" --interval 1 --expect 'x' -- "$NEVER"
[ "$RC" -eq 64 ] && ok "missing --timeout exits 64" || bad "usage exit=$RC want 64"

# 6. a hung poll cannot block past the timeout (per-poll cap)
run "hung" --timeout 2 --interval 1 -- sleep 30
[ "$RC" -eq 2 ] && ok "hung poll exits 2 (timeout)" || bad "hung exit=$RC want 2"
[ "$ELAPSED" -le 4 ] && ok "hung poll bounded (${ELAPSED}s)" || bad "hung blocked ${ELAPSED}s"

# 7. overshoot: a large --interval must not overrun --timeout
run "overshoot" --timeout 2 --interval 30 --expect 'http=200' -- "$NEVER"
[ "$RC" -eq 2 ] && ok "overshoot exits 2" || bad "overshoot exit=$RC want 2"
[ "$ELAPSED" -le 4 ] && ok "interval clamped to deadline (${ELAPSED}s)" || bad "overshoot ran ${ELAPSED}s"

# 8. --stuck-after without --expect -> usage (stuck is value-based)
run "stuck-no-expect" --timeout 5 --interval 1 --stuck-after 3 -- "$NEVER"
[ "$RC" -eq 64 ] && ok "--stuck-after needs --expect (exit 64)" || bad "stuck-no-expect exit=$RC want 64"

# 9. --stuck-after 0 -> usage (invalid threshold)
run "stuck-zero" --timeout 5 --interval 1 --expect 'http=200' --stuck-after 0 -- "$NEVER"
[ "$RC" -eq 64 ] && ok "--stuck-after 0 rejected (exit 64)" || bad "stuck-zero exit=$RC want 64"

echo "----"; echo "PASS=$PASS FAIL=$FAIL"
[ "$FAIL" -eq 0 ]
