#!/usr/bin/env bash # Verifies adr-reserve.sh against a local file:// origin (no network/keys). # Exercises: number computation, dry-run, real reserve+push, sequential # allocation, idempotence, hard-rejection abort (vs infinite loop), and the # race-vs-abort discriminator. set -euo pipefail SCRIPT="$(cd "$(dirname "$0")" && pwd)/adr-reserve.sh" PASS=0 FAIL=0 check() { # if [ "$2" = "$3" ]; then echo "PASS: $1 ($3)"; PASS=$((PASS+1)); else echo "FAIL: $1 — expected '$2' got '$3'"; FAIL=$((FAIL+1)); fi } T="$(mktemp -d)" trap 'rm -rf "$T"' EXIT # ---- seed a bare origin with ADRs up to 0057 ------------------------------- git init -q --bare "$T/origin.git" git clone -q "$T/origin.git" "$T/seed" git -C "$T/seed" config user.email t@t.io git -C "$T/seed" config user.name tester mkdir -p "$T/seed/docs/adr" echo "# legacy" > "$T/seed/docs/adr/0056-alpha.md" echo "# legacy" > "$T/seed/docs/adr/0057-beta.md" git -C "$T/seed" add -A git -C "$T/seed" commit -qm "seed: ADRs through 0057" git -C "$T/seed" branch -M main git -C "$T/seed" push -q origin main # the repo the script runs inside (origin = our bare repo) git clone -q "$T/origin.git" "$T/work" git -C "$T/work" config user.email t@t.io git -C "$T/work" config user.name tester run() { ( cd "$T/work" && "$@" ); } echo "--- Test 1: dry-run computes 0058 (no push) ---" out="$(run env ADR_RESERVE_DRY_RUN=1 bash "$SCRIPT" feature-one "Feature One" 2>/dev/null)" check "dry-run number" "0058" "$out" git -C "$T/seed" pull -q origin main check "dry-run pushed nothing" "no" "$( [ -f "$T/seed/docs/adr/RESERVATIONS.log" ] && echo yes || echo no )" echo "--- Test 2: real reserve → 0058, pushed to origin ---" out="$(run bash "$SCRIPT" feature-one "Feature One" 2>/dev/null)" check "first reserve number" "0058" "$out" git -C "$T/seed" pull -q origin main check "ledger landed on origin" "0058 feature-one" "$(awk 'NR==1{print $1" "$2}' "$T/seed/docs/adr/RESERVATIONS.log")" echo "--- Test 3: second slug → 0059 (sequential) ---" out="$(run bash "$SCRIPT" feature-two 2>/dev/null)" check "second reserve number" "0059" "$out" echo "--- Test 4: idempotence — re-reserving feature-one returns 0058 ---" out="$(run bash "$SCRIPT" feature-one 2>/dev/null)" check "idempotent re-reserve" "0058" "$out" git -C "$T/seed" pull -q origin main check "no duplicate ledger line" "1" "$(grep -c ' feature-one ' "$T/seed/docs/adr/RESERVATIONS.log")" echo "--- Test 5: hard rejection (branch protection) aborts, does NOT loop ---" cat > "$T/origin.git/hooks/pre-receive" <<'HOOK' #!/bin/sh echo "protected branch: push declined" >&2 exit 1 HOOK chmod +x "$T/origin.git/hooks/pre-receive" set +e run bash "$SCRIPT" feature-three >/dev/null 2>"$T/err"; rc=$? set -e check "abort exit code nonzero" "yes" "$( [ "$rc" -ne 0 ] && echo yes || echo no )" check "abort cites protection, not a loop" "yes" "$(grep -qi 'not a race\|protection' "$T/err" && echo yes || echo no)" rm -f "$T/origin.git/hooks/pre-receive" echo "--- Test 6: race discriminator matches a real non-ff message ---" ff_msg=" ! [rejected] main -> main (non-fast-forward) error: failed to push some refs" check "non-ff treated as race" "yes" \ "$(grep -qiE 'non-fast-forward|fetch first|tip of your .* is behind|stale info' <<<"$ff_msg" && echo yes || echo no)" echo echo "==== $PASS passed, $FAIL failed ====" [ "$FAIL" -eq 0 ]