#!/usr/bin/env bash
# tests/dc-selector/run-tests.sh -- unit tests for the $DC selector
# convention (2026-07-09, tooling gap register #1): lib_net_select_dc() in
# scripts/lib-net.sh and lib_hosts_select_dc() in scripts/lib-hosts.sh.
#
# Asserts:
# - sourcing either file with no further action is unaffected (backward
# compatible by construction -- the flat vars populate exactly as before).
# - lib_net_select_dc: vr0-dc0/vr1-dc0 no-op (D-101 inheritance); vr1-dc1
# OVERRIDES to the D-124-amendment literals (2026-07-21: contiguous /22s in
# 10.12.64.0/19) and UNSETS the not-yet-ruled OpenStack-layer values;
# unknown/retired tokens fail loud; one selection per shell (the guard
# added with the diverging dc1 arm).
# - lib_hosts_select_dc: vr0-dc0 no-op, VR1 arms POPULATED 2026-07-23 (was: fail loud -- no real
# per-DC host enrollment exists yet for either -- this is the documented
# asymmetry vs. lib-net.sh).
# - Neither function ever silently invents/reuses a value across DCs.
set -uo pipefail
SD="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
NET="$SD/../../scripts/lib-net.sh"
HOSTSLIB="$SD/../../scripts/lib-hosts.sh"
P=0; F=0
ok(){ echo "PASS: $1"; P=$((P+1)); }
no(){ echo "FAIL: $1"; F=$((F+1)); }
chk(){ [ "$2" = "$3" ] && ok "$1" || no "$1 (got '$2' want '$3')"; }
# guard: both libs still refuse direct execution (unchanged by this addition)
( bash "$NET" >/dev/null 2>&1 ); chk "lib-net direct-exec-refused" "$?" 2
( bash "$HOSTSLIB" >/dev/null 2>&1 ); chk "lib-hosts direct-exec-refused" "$?" 2
# shellcheck source=/dev/null
. "$NET"
# shellcheck source=/dev/null
. "$HOSTSLIB"
# --- backward compatibility: sourcing alone still populates the flat vars ---
chk "PLANE_CIDRS unaffected" "${PLANE_CIDRS[0]}" "10.12.4.0/22"
chk "KEYSTONE_VIP_DEFAULT unaffected" "$KEYSTONE_VIP_DEFAULT" "10.12.4.50"
chk "HOSTS array unaffected" "${HOSTS[0]}" "openstack0"
chk "HOST_OCTET unaffected" "${HOST_OCTET[openstack0]}" "40"
# --- lib_net_select_dc (D-119 region-qualified): vr0-dc0/vr1-dc0 no-op,
# vr1-dc1 OVERRIDES (D-124 amendment 2026-07-21), RETIRED bare dcN fails
# loud, unknown fails loud ---
( lib_net_select_dc vr0-dc0 ); chk "net vr0-dc0 no-op rc" "$?" 0
( lib_net_select_dc vr1-dc0 ); chk "net vr1-dc0 no-op rc" "$?" 0
( lib_net_select_dc vr1-dc1 ); chk "net vr1-dc1 selects rc" "$?" 0
( lib_net_select_dc bogus 2>/dev/null ); chk "net unknown-token fails-loud rc" "$?" 1
( lib_net_select_dc 2>/dev/null ); chk "net missing-arg fails-loud rc" "$?" 1
# vr1-dc1 arm: the D-124-amendment literals land (apex-verified 2026-07-21).
DC1_P0="$(lib_net_select_dc vr1-dc1 >/dev/null 2>&1; echo "${PLANE_CIDRS[0]}")"
chk "net vr1-dc1 provider-public is 10.12.64.0/22" "$DC1_P0" "10.12.64.0/22"
DC1_P5="$(lib_net_select_dc vr1-dc1 >/dev/null 2>&1; echo "${PLANE_CIDRS[5]}")"
chk "net vr1-dc1 replication is 10.12.84.0/22" "$DC1_P5" "10.12.84.0/22"
DC1_MA="$(lib_net_select_dc vr1-dc1 >/dev/null 2>&1; echo "${PLANE_NAME[10.12.68.0/22]}")"
chk "net vr1-dc1 10.12.68.0/22 is metal-admin" "$DC1_MA" "metal-admin"
DC1_GW="$(lib_net_select_dc vr1-dc1 >/dev/null 2>&1; echo "${PLANE_GW[10.12.64.0/22]}")"
chk "net vr1-dc1 provider-public gw is 10.12.64.1 (ruled edge LAN gw)" "$DC1_GW" "10.12.64.1"
DC1_MI="$(lib_net_select_dc vr1-dc1 >/dev/null 2>&1; echo "$METAL_INTERNAL_CIDR")"
chk "net vr1-dc1 metal-internal CIDR is 10.12.72.0/22" "$DC1_MI" "10.12.72.0/22"
# not-yet-ruled OpenStack-layer values are UNSET (fail loud under set -u, never
# silently another DC's addresses).
DC1_KV="$(lib_net_select_dc vr1-dc1 >/dev/null 2>&1; echo "${KEYSTONE_VIP_DEFAULT+still-set}")"
chk "net vr1-dc1 unsets KEYSTONE_VIP_DEFAULT" "$DC1_KV" ""
DC1_VP="$(lib_net_select_dc vr1-dc1 >/dev/null 2>&1; echo "${VIP_PREFIX_PROVIDER+still-set}")"
chk "net vr1-dc1 unsets VIP_PREFIX_PROVIDER" "$DC1_VP" ""
DC1_FP="$(lib_net_select_dc vr1-dc1 >/dev/null 2>&1; echo "${FIP_POOL_START+still-set}")"
chk "net vr1-dc1 unsets FIP_POOL_START" "$DC1_FP" ""
# ONE SELECTION PER SHELL (guard added with the diverging dc1 arm): changing
# selection after dc1 is REFUSED; re-selecting the SAME DC stays a no-op.
( lib_net_select_dc vr1-dc1 >/dev/null 2>&1; lib_net_select_dc vr0-dc0 2>/dev/null ); \
chk "net dc1->vr0-dc0 re-select REFUSED (stale cross-DC values)" "$?" 1
SWITCH_ERR="$(lib_net_select_dc vr1-dc1 >/dev/null 2>&1; lib_net_select_dc vr0-dc0 2>&1 1>/dev/null || true)"
grep -q "already selected" <<<"$SWITCH_ERR" && ok "net re-select error says already selected" || no "net re-select error says already selected"
( lib_net_select_dc vr1-dc0 >/dev/null 2>&1; lib_net_select_dc vr1-dc0 ); \
chk "net same-DC re-select stays a no-op rc" "$?" 0
# D-119 REGRESSION GUARD: the bare dcN tokens are RETIRED and must be REJECTED.
# Accepting them "for compatibility" would preserve the exact cross-region
# ambiguity D-119 deletes -- 'dc0' meant VR0's LIVE cloud in lib-net.sh but VR1's
# FIRST DC in the NetBox importer. Silence here is how the off-by-one comes back.
for retired in dc0 dc1 dc2; do
( lib_net_select_dc "$retired" 2>/dev/null ); chk "net RETIRED '$retired' rejected (D-119)" "$?" 1
R_ERR="$(lib_net_select_dc "$retired" 2>&1 1>/dev/null || true)"
grep -q "RETIRED" <<<"$R_ERR" && ok "net '$retired' error says RETIRED" || no "net '$retired' error says RETIRED"
done
# no-op really means no-op: values identical after selecting vr0-dc0 or vr1-dc0.
# They match by INHERITANCE (D-101: VR1's first DC inherits VR0 DC0's v4 layout),
# not by coincidence -- and they are separate case arms so they can diverge later.
VR0_VAL="$(lib_net_select_dc vr0-dc0 >/dev/null 2>&1; echo "${PLANE_CIDRS[0]}")"
VR1_VAL="$(lib_net_select_dc vr1-dc0 >/dev/null 2>&1; echo "${PLANE_CIDRS[0]}")"
chk "net vr0-dc0/vr1-dc0 identical values (D-101 inheritance)" "$VR0_VAL" "$VR1_VAL"
# --- lib_hosts_select_dc: vr0-dc0 no-op; VR1 arms POPULATED 2026-07-23 ---
# (Stage 4 carve session: both fleets enrolled+Ready, identities measured --
# the historical fail-loud behavior and its asymmetry test are history.)
( lib_hosts_select_dc vr0-dc0 ); chk "hosts vr0-dc0 no-op rc" "$?" 0
( lib_hosts_select_dc vr1-dc0 ); chk "hosts vr1-dc0 selects rc" "$?" 0
( lib_hosts_select_dc vr1-dc1 ); chk "hosts vr1-dc1 selects rc" "$?" 0
( lib_hosts_select_dc bogus 2>/dev/null ); chk "hosts unknown-token fails-loud rc" "$?" 1
( lib_hosts_select_dc 2>/dev/null ); chk "hosts missing-arg fails-loud rc" "$?" 1
for retired in dc0 dc1 dc2; do
( lib_hosts_select_dc "$retired" 2>/dev/null ); chk "hosts RETIRED '$retired' rejected (D-119)" "$?" 1
done
# --- VR1 arms carry the MEASURED identity + D-134-amended octets ---
H0_OCT="$(lib_hosts_select_dc vr1-dc0 >/dev/null 2>&1; echo "${HOST_OCTET[vr1-dc0-control-01]}")"
chk "hosts vr1-dc0 control-01 octet .100 (D-134 amendment)" "$H0_OCT" "100"
H0_ST="$(lib_hosts_select_dc vr1-dc0 >/dev/null 2>&1; echo "${HOST_OCTET[vr1-dc0-storage-04]}")"
chk "hosts vr1-dc0 storage-04 octet .153" "$H0_ST" "153"
H0_MAC="$(lib_hosts_select_dc vr1-dc0 >/dev/null 2>&1; echo "${HOST_BOOT_MAC[vr1-dc0-compute-02]}")"
chk "hosts vr1-dc0 compute-02 pinned boot MAC" "$H0_MAC" "52:54:00:18:ab:b4"
H1_MAC="$(lib_hosts_select_dc vr1-dc1 >/dev/null 2>&1; echo "${HOST_BOOT_MAC[vr1-dc1-storage-04]}")"
chk "hosts vr1-dc1 storage-04 pinned boot MAC (index-encoded)" "$H1_MAC" "52:54:01:d1:09:01"
H0_TAG="$(lib_hosts_select_dc vr1-dc0 >/dev/null 2>&1; echo "$HOST_TAG")"
chk "hosts vr1-dc0 tag openstack-vr1-dc0 (ruled 2026-07-23)" "$H0_TAG" "openstack-vr1-dc0"
H1_PWR="$(lib_hosts_select_dc vr1-dc1 >/dev/null 2>&1; echo "$VIRSH_POWER_ADDRESS")"
chk "hosts vr1-dc1 power addr rack transit .6" "$H1_PWR" "qemu+ssh://jessea123@172.31.0.6/system"
H0_N="$(lib_hosts_select_dc vr1-dc0 >/dev/null 2>&1; echo "${#HOSTS[@]}")"
chk "hosts vr1-dc0 fleet count 9 (D-121 Option C)" "$H0_N" "9"
# --- ONE SELECTION PER SHELL (stale cross-DC guard, lib-net precedent) ---
( lib_hosts_select_dc vr1-dc0 >/dev/null 2>&1; lib_hosts_select_dc vr1-dc1 2>/dev/null ); \
chk "hosts dc0->dc1 re-select REFUSED (stale cross-DC values)" "$?" 1
HSW_ERR="$(lib_hosts_select_dc vr1-dc0 >/dev/null 2>&1; lib_hosts_select_dc vr1-dc1 2>&1 1>/dev/null || true)"
grep -q "already selected" <<<"$HSW_ERR" && ok "hosts re-select error says already selected" || no "hosts re-select error says already selected"
( lib_hosts_select_dc vr1-dc1 >/dev/null 2>&1; lib_hosts_select_dc vr1-dc1 ); \
chk "hosts same-DC re-select stays a no-op rc" "$?" 0
# --- the VR1 resolver exists: system_id by pinned boot MAC, never hostname ---
type host_sysid_by_bootmac >/dev/null 2>&1 && ok "host_sysid_by_bootmac defined (VR1 resolver)" || no "host_sysid_by_bootmac defined (VR1 resolver)"
echo; [ "$F" = 0 ] && { echo "ALL PASS ($P checks)"; exit 0; } || { echo "FAILURES: $F"; exit 1; }