Newer
Older
openstack-caracal-dc-dc / tests / dc-selector / run-tests.sh
#!/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: dc0/dc1 no-op (D-101: DC1 inherits DC0's v4 layout
#    unchanged), dc2 fails loud, unknown token fails loud.
#  - lib_hosts_select_dc: dc0 no-op, dc1 AND dc2 both fail loud (no real
#    per-DC host enrollment exists yet for either -- this is the documented
#    asymmetry vs. lib-net.sh's dc0|dc1 no-op).
#  - 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: dc0/dc1 no-op, dc2 fails loud, unknown fails loud ---
( lib_net_select_dc dc0 ); chk "net dc0 no-op rc"    "$?" 0
( lib_net_select_dc dc1 ); chk "net dc1 no-op rc"    "$?" 0
( lib_net_select_dc dc2 2>/dev/null ); chk "net dc2 fails-loud rc" "$?" 1
NET_ERR="$(lib_net_select_dc dc2 2>&1 1>/dev/null || true)"
grep -q "NetBox" <<<"$NET_ERR" && ok "net dc2 error cites NetBox gap" || no "net dc2 error cites NetBox gap"
( 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

# no-op really means no-op: values identical after selecting either dc0 or dc1
DC0_VAL="$(lib_net_select_dc dc0 >/dev/null 2>&1; echo "${PLANE_CIDRS[0]}")"
DC1_VAL="$(lib_net_select_dc dc1 >/dev/null 2>&1; echo "${PLANE_CIDRS[0]}")"
chk "net dc0/dc1 identical values (D-101)" "$DC0_VAL" "$DC1_VAL"

# --- lib_hosts_select_dc: dc0 no-op, dc1 AND dc2 both fail loud ---
( lib_hosts_select_dc dc0 ); chk "hosts dc0 no-op rc" "$?" 0
( lib_hosts_select_dc dc1 2>/dev/null ); chk "hosts dc1 fails-loud rc" "$?" 1
( lib_hosts_select_dc dc2 2>/dev/null ); chk "hosts dc2 fails-loud rc" "$?" 1
HOSTS_ERR1="$(lib_hosts_select_dc dc1 2>&1 1>/dev/null || true)"
grep -q "no enrolled hosts" <<<"$HOSTS_ERR1" && ok "hosts dc1 error cites no-enrollment" || no "hosts dc1 error cites no-enrollment"
HOSTS_ERR2="$(lib_hosts_select_dc dc2 2>&1 1>/dev/null || true)"
grep -q "no enrolled hosts" <<<"$HOSTS_ERR2" && ok "hosts dc2 error cites no-enrollment" || no "hosts dc2 error cites no-enrollment"
( 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

# --- the documented asymmetry itself: dc1 differs between the two libs ---
( lib_net_select_dc dc1 ); NET_DC1_RC=$?
( lib_hosts_select_dc dc1 2>/dev/null ); HOSTS_DC1_RC=$?
[ "$NET_DC1_RC" = 0 ] && [ "$HOSTS_DC1_RC" = 1 ] && ok "dc1 asymmetry: net no-ops, hosts fails (documented, not a bug)" || no "dc1 asymmetry broken (net=$NET_DC1_RC hosts=$HOSTS_DC1_RC)"

echo; [ "$F" = 0 ] && { echo "ALL PASS ($P checks)"; exit 0; } || { echo "FAILURES: $F"; exit 1; }