#!/bin/sh # deploy/tests.sh — packaging tests for the 9-account deploy (Redmine # 494). Pure POSIX shell, no docker, no network, no root: # # T1 accounts.tsv: 9 rows, spec-exact account/host lists, 8 columns, # unique accounts, port scheme events=4100+idx / serve=8090+idx, # (host,port) uniqueness across the fleet # T2 render: installer runs for ALL 9 accounts against a stub binary # in fake HOMEs; harness.toml has no unsubstituted @PLACEHOLDER@s # and carries the row's vertical/ports/project; env is 0600; # start/stop helpers exist, executable, correct ports # T3 idempotence: re-run exits 0, harness.toml + env byte-identical # T4 refuse-to-overwrite: hand-edited harness.toml marker survives # T5 unknown account -> non-zero exit # T6 binary lookup order (../bin/harness-linux-amd64 staging layout) # T7 generated TOML actually loads: `once --dry-run --demo` via the # dev binary when bin/harness exists (skipped otherwise) # # Usage: ./deploy/tests.sh (or: make deploy-test) set -u ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) TSV="$ROOT/deploy/accounts.tsv" INSTALL="$ROOT/deploy/install-account.sh" TEMPLATE="$ROOT/deploy/harness.toml.in" PASS=0 FAIL=0 ok() { PASS=$((PASS + 1)); echo "ok $1"; } bad() { FAIL=$((FAIL + 1)); echo "FAIL $1"; } check() { # desc condition-already-evaluated-by-caller if [ "$2" = 0 ]; then ok "$1"; else bad "$1"; fi } # ---------------------------------------------------------------- T1 t1() { # 9 data rows n=$(awk -F'\t' '$1 !~ /^#/ && NF >= 8 {c++} END {print c + 0}' "$TSV") check "T1 accounts.tsv has 9 account rows" "$([ "$n" -eq 9 ]; echo $?)" # exact account/host sets from the spec spec_streaming="reachableceo TSGBOD TSGCOO TSGCTO TSGCCO" spec_offstage="reachableceo-offstage COSRCEO-Personal COSRCEO-Biz COSWFO" got_streaming=$(awk -F'\t' '$1 !~ /^#/ && $2 == "ultix-streaming" {print $1}' "$TSV" | sort | tr '\n' ' ') got_offstage=$(awk -F'\t' '$1 !~ /^#/ && $2 == "ultix-offstage" {print $1}' "$TSV" | sort | tr '\n' ' ') want_streaming=$(printf '%s\n' $spec_streaming | sort | tr '\n' ' ') want_offstage=$(printf '%s\n' $spec_offstage | sort | tr '\n' ' ') check "T1 ultix-streaming accounts match the spec" "$([ "$got_streaming" = "$want_streaming" ]; echo $?)" check "T1 ultix-offstage accounts match the spec" "$([ "$got_offstage" = "$want_offstage" ]; echo $?)" # unique account names, unique host:index, unique (host,events/serve) ports dup=$(awk -F'\t' '$1 !~ /^#/ {print $1}' "$TSV" | sort | uniq -d | wc -l | tr -d ' ') check "T1 account names unique" "$([ "$dup" -eq 0 ]; echo $?)" dup=$(awk -F'\t' '$1 !~ /^#/ {print $2" "$7}' "$TSV" | sort | uniq -d | wc -l | tr -d ' ') check "T1 (host, events_port) unique" "$([ "$dup" -eq 0 ]; echo $?)" dup=$(awk -F'\t' '$1 !~ /^#/ {print $2" "$8}' "$TSV" | sort | uniq -d | wc -l | tr -d ' ') check "T1 (host, serve_port) unique" "$([ "$dup" -eq 0 ]; echo $?)" # port derivation + row sanity (also enforced by the installer itself) badrows=$(awk -F'\t' '$1 !~ /^#/ { if (NF != 8 || $3 !~ /^[0-9]+$/ || $7 != 4100 + $3 || $8 != 8090 + $3) bad++ } END {print bad + 0}' "$TSV") check "T1 every row: 8 cols, events=4100+index, serve=8090+index" "$([ "$badrows" -eq 0 ]; echo $?)" } # ---------------------------------------------------------------- T2-T6 t2_t6() { TMP=$(mktemp -d /tmp/mopac-deploy-test.XXXXXX) || { bad "T2 mktemp"; return; } trap 'rm -rf "$TMP"' EXIT INT TERM # stub binary (real one not needed to test the packaging) printf '#!/bin/sh\necho stub-harness "$@"\n' >"$TMP/harness-linux-amd64" chmod 755 "$TMP/harness-linux-amd64" rc_all=0 for acct in $(awk -F'\t' '$1 !~ /^#/ {print $1}' "$TSV"); do row=$(awk -F'\t' -v a="$acct" '$1 == a {print}' "$TSV") idx=$(printf '%s\n' "$row" | awk -F'\t' '{print $3}') vert=$(printf '%s\n' "$row" | awk -F'\t' '{print $4}') proj=$(printf '%s\n' "$row" | awk -F'\t' '{print $5}') ev=$((4100 + idx)); sv=$((8090 + idx)) FAKEHOME="$TMP/home-$acct" mkdir -p "$FAKEHOME" HOME="$FAKEHOME" MOPAC_HARNESS_BIN="$TMP/harness-linux-amd64" \ sh "$INSTALL" "$acct" >"$TMP/out-$acct" 2>&1 rc=$? [ "$rc" -eq 0 ] || { bad "T2 install $acct exits 0 (got $rc)"; sed 's/^/ /' "$TMP/out-$acct"; rc_all=1; continue; } cfg="$FAKEHOME/.mopac/harness.toml" for cond in \ "[ -f \"\$cfg\" ]" \ "[ -x \"\$FAKEHOME/.mopac/bin/harness\" ]" \ "[ -x \"\$FAKEHOME/.mopac/bin/mopac-start\" ]" \ "[ -x \"\$FAKEHOME/.mopac/bin/mopac-stop\" ]" \ "[ -d \"\$FAKEHOME/.mopac/state/loop\" ]" \ "[ -d \"\$FAKEHOME/.mopac/state/events\" ]" \ "[ -d \"\$FAKEHOME/.mopac/reports\" ]" \ "[ -d \"\$FAKEHOME/.mopac/work\" ]" \ "! grep -q '@[A-Z_][A-Z0-9_]*@' \"\$cfg\"" \ "grep -q \"vertical = \\\"\$vert\\\"\" \"\$cfg\"" \ "grep -q 'listen = \":'\$ev'\"' \"\$cfg\"" \ "grep -q 'listen = \":'\$sv'\"' \"\$cfg\"" \ "grep -q \"project=\$proj&\" \"\$cfg\"" \ "grep -q \"\$FAKEHOME/.mopac/state/loop\" \"\$cfg\"" \ "grep -q \":\$ev\" \"\$FAKEHOME/.mopac/bin/mopac-start\"" \ "[ \"\$(stat -c %a \"\$FAKEHOME/.mopac/env\")\" = 600 ]" do if ! eval "$cond"; then bad "T2 $acct: $cond" rc_all=1 fi done done [ "$rc_all" -eq 0 ] && ok "T2 render all 9 accounts: files, modes, substitutions, ports" # --- T3 idempotence (re-run one account: exit 0, config + env unchanged) acct=TSGBOD FAKEHOME="$TMP/home-$acct" sum_cfg=$(cksum "$FAKEHOME/.mopac/harness.toml" | awk '{print $1, $2}') sum_env=$(cksum "$FAKEHOME/.mopac/env" | awk '{print $1, $2}') HOME="$FAKEHOME" MOPAC_HARNESS_BIN="$TMP/harness-linux-amd64" \ sh "$INSTALL" "$acct" >"$TMP/out-rerun" 2>&1 rc=$? [ "$rc" -eq 0 ] && \ [ "$sum_cfg" = "$(cksum "$FAKEHOME/.mopac/harness.toml" | awk '{print $1, $2}')" ] && \ [ "$sum_env" = "$(cksum "$FAKEHOME/.mopac/env" | awk '{print $1, $2}')" ] \ && ok "T3 idempotent re-run: exit 0, harness.toml + env byte-identical" \ || bad "T3 idempotent re-run (rc=$rc)" # --- T4 hand-edited config survives (refuse to overwrite) echo "# hand-edited marker" >>"$FAKEHOME/.mopac/harness.toml" HOME="$FAKEHOME" MOPAC_HARNESS_BIN="$TMP/harness-linux-amd64" \ sh "$INSTALL" "$acct" >"$TMP/out-keep" 2>&1 rc=$? grep -q "# hand-edited marker" "$FAKEHOME/.mopac/harness.toml" && [ "$rc" -eq 0 ] \ && grep -q "kept existing" "$TMP/out-keep" \ && ok "T4 existing harness.toml kept on re-run (exit 0, marker intact)" \ || bad "T4 refuse-to-overwrite (rc=$rc)" # --- T5 unknown account HOME="$TMP/home-nowhere" MOPAC_HARNESS_BIN="$TMP/harness-linux-amd64" \ sh "$INSTALL" no-such-account >"$TMP/out-unknown" 2>&1 [ "$?" -ne 0 ] && grep -q "not in" "$TMP/out-unknown" \ && ok "T5 unknown account -> non-zero + message" \ || bad "T5 unknown account" # --- T6 default binary lookup (staged bundle layout: ../bin/harness-linux-amd64) STAGE="$TMP/stage"; mkdir -p "$STAGE/deploy" "$STAGE/bin" cp "$TSV" "$TEMPLATE" "$INSTALL" "$STAGE/deploy/" cp "$TMP/harness-linux-amd64" "$STAGE/bin/harness-linux-amd64" FAKEHOME="$TMP/home-stage"; mkdir -p "$FAKEHOME" HOME="$FAKEHOME" sh "$STAGE/deploy/install-account.sh" TSGCCO >"$TMP/out-stage" 2>&1 rc=$? [ "$rc" -eq 0 ] && [ -x "$FAKEHOME/.mopac/bin/harness" ] && \ grep -q "vertical = \"cco\"" "$FAKEHOME/.mopac/harness.toml" \ && ok "T6 staged-bundle lookup ../bin/harness-linux-amd64 works (no env override)" \ || bad "T6 staged-bundle lookup (rc=$rc)" # --- T7 generated TOML loads (needs a built dev binary; skip otherwise) if [ -x "$ROOT/bin/harness" ]; then cfg="$TMP/home-TSGCOO/.mopac/harness.toml" HOME="$TMP/home-TSGCOO" "$ROOT/bin/harness" once --dry-run --demo \ -config "$cfg" >"$TMP/out-load" 2>&1 rc=$? grep -q "vertical: coo" "$TMP/out-load" && [ "$rc" -eq 0 ] \ && ok "T7 rendered harness.toml loads (once --dry-run --demo, exit 0)" \ || { bad "T7 rendered config loads (rc=$rc)"; sed 's/^/ /' "$TMP/out-load"; } else echo "skip T7 (bin/harness not built; run ./dev.sh check or make release first)" fi } t1 t2_t6 echo echo "pass=$PASS fail=$FAIL" [ "$FAIL" -eq 0 ]