#!/usr/bin/env bash
# tests/geneve-encap-assert/run-tests.sh -- offline harness for
# scripts/geneve-encap-assert.sh. Self-contained: fixtures are written to a
# temp dir; the pure assertion logic (C1 family consistency, C2 tunnel ofport
# health) runs for real against them. Every check is proven in its FAILING
# direction (a checker that cannot fail is not a gate). Exit: 0 all pass | 1 any
# case failed. ASCII + LF.
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPT="$HERE/../../scripts/geneve-encap-assert.sh"
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
PASS=0; FAIL=0
run() { # run <want_rc> <regex> <label> -- args...
local want="$1" rx="$2" label="$3"; shift 3
local out rc
out="$(bash "$SCRIPT" "$@" 2>&1)"; rc=$?
if [[ "$rc" == "$want" ]] && grep -qE "$rx" <<<"$out"; then
echo " PASS $label"; PASS=$((PASS+1))
else
echo " FAIL $label (rc=$rc want=$want)"; echo "$out" | sed 's/^/ /'; FAIL=$((FAIL+1))
fi
}
# --- fixtures ----------------------------------------------------------------
printf '%s\n' '2602:f3e2:f02:30::100' '2602:f3e2:f02:30::120' '2602:f3e2:f02:30::121' > "$TMP/encap_v6.txt"
printf '%s\n' '10.12.16.1' '10.12.16.2' '10.12.16.3' > "$TMP/encap_v4.txt"
# the real 2026-08-08 split: control LXD v4 + compute metal v6
printf '%s\n' '10.12.16.1' '10.12.16.2' '2602:f3e2:f02:30::120' '2602:f3e2:f02:30::121' > "$TMP/encap_split.txt"
# bracketed v6 (as ovn-chassis 24.03 emits) -- still parses as v6 for C1
printf '%s\n' '[2602:f3e2:f02:30::120]' '[2602:f3e2:f02:30::121]' > "$TMP/encap_v6_brk.txt"
: > "$TMP/encap_empty.txt"
printf '%s\n' '14' '15' '16' '17' '18' > "$TMP/of_ok.txt" # all valid
printf '%s\n' '14' '-1' '16' > "$TMP/of_bad.txt" # one invalid (bracket-bug signature)
: > "$TMP/of_empty.txt"
E6="--encap-ips $TMP/encap_v6.txt"; OK="--tunnel-ofports $TMP/of_ok.txt"
# --- C1/C2 clean PASS --------------------------------------------------------
run 0 'geneve-encap-assert: PASS' "T1 uniform-v6 encap + valid ofports PASS" $E6 $OK
run 0 'C1: all 3 chassis .* single-family \(v6\)' "T2 C1 reports single-family v6" $E6 $OK
run 0 'C2: all 5 .* ofport >= 0' "T3 C2 reports all ofports valid" $E6 $OK
run 0 'geneve-encap-assert: PASS' "T4 uniform-v4 encap also PASSes (consistency, not v6-hardcoded)" --encap-ips "$TMP/encap_v4.txt" $OK
# --- C1 FAILING direction: family split -------------------------------------
run 1 'C1: geneve encap SPLIT across families' "T5 split encap FAILS C1 (the 2026-08-08 root cause)" --encap-ips "$TMP/encap_split.txt" $OK
# --- C2 FAILING direction: ofport -1 (bracket bug) --------------------------
run 1 'C2: 1 of 3 geneve tunnels have ofport -1' "T6 ofport -1 FAILS C2 (the 2026-08-09 bracket bug)" $E6 --tunnel-ofports "$TMP/of_bad.txt"
# bracketed encap is single-family (C1 ok) but the bug shows as C2 ofport -1
run 1 'geneve-encap-assert: FAIL' "T7 bracketed-v6 encap + ofport -1 FAILS (C1 passes, C2 catches)" --encap-ips "$TMP/encap_v6_brk.txt" --tunnel-ofports "$TMP/of_bad.txt"
run 0 'C1: all 2 chassis .* single-family \(v6\)' "T8 bracketed v6 still parses as single-family v6 for C1" --encap-ips "$TMP/encap_v6_brk.txt" $OK
# --- --expect-family (ruled family) ------------------------------------------
run 0 'geneve-encap-assert: PASS' "T9 --expect-family v6 on v6 PASSes" $E6 $OK --expect-family v6
run 1 'C1: encap family is .v4. but --expect-family=v6' "T10 --expect-family v6 on v4 FAILS" --encap-ips "$TMP/encap_v4.txt" $OK --expect-family v6
# --- refuse-not-pass on empty inputs ----------------------------------------
run 1 'C1: no chassis Encap.ip found' "T11 empty encap REFUSES (not pass)" --encap-ips "$TMP/encap_empty.txt" $OK
run 1 'C2: no geneve tunnel interfaces found' "T12 empty ofports REFUSES (not pass)" $E6 --tunnel-ofports "$TMP/of_empty.txt"
# --- usage/precondition (rc 2) ----------------------------------------------
run 2 'need --encap-ips' "T13 missing --encap-ips is usage (rc 2)" $OK
run 2 'need --tunnel-ofports' "T14 missing --tunnel-ofports is usage (rc 2)" $E6
run 2 'must be v6 or v4' "T15 bad --expect-family is usage (rc 2)" $E6 $OK --expect-family v5
run 2 'unknown arg' "T16 unknown arg is usage (rc 2)" $E6 $OK --bogus
echo "-----"
echo "geneve-encap-assert harness: $PASS passed, $FAIL failed"
[ "$FAIL" -eq 0 ]