Mercurial
view mrjunejune/test/config_validation_test.sh @ 272:41a49c29a28f
polish JRPG conversation experience
Integrate desktop conversations into the utility panel, simplify the mobile frame, add modal destinations and a reusable Zenbu composer lab, and preserve explicit conversation resume behavior.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 07 Aug 2026 16:05:29 -0700 |
| parents | 056790c4fb0d |
| children |
line wrap: on
line source
#!/usr/bin/env bash # config_validation_test.sh — startup config validation tests. # # Verifies that the server binary exits 1 (fail-closed) on bad config, # starts cleanly on env-only config (no .config file), and enforces the # loopback requirement for AUTH_DEV_INSECURE_COOKIE. # # Bazel passes the server binary path as $1. set -euo pipefail server="$(realpath "$1")" tmpdir="$(mktemp -d)" trap 'rm -rf "$tmpdir"' EXIT pass() { printf " %-62s PASS\n" "$1"; } fail() { echo "FAIL: $1" >&2; exit 1; } # A valid 64-hex-char secret (32 random bytes) for success cases. GOOD_SECRET="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" # Helper: run $@ as a command, expect it to exit non-zero ≤ 3 seconds. run_expect_fail() { local label="$1"; shift local out set +e out=$(timeout 3 "$@" 2>&1) local code=$? set -e if [[ $code -eq 0 || $code -eq 124 ]]; then echo "FAIL: '$label' — expected exit 1, got code $code" >&2 echo "$out" >&2 exit 1 fi pass "$label" } # Helper: run $@ as a command; expect it to emit an "Initialised" or # listen/startup log line within 5 seconds, then kill it. run_expect_start() { local label="$1"; shift local logfile="$tmpdir/start_${RANDOM}.log" set +e timeout 5 "$@" >"$logfile" 2>&1 & local pid=$! local started=false for _ in $(seq 1 50); do sleep 0.1 if grep -q -E 'Initialised|Listening|WTF is going on' "$logfile" 2>/dev/null; then started=true break fi if ! kill -0 "$pid" 2>/dev/null; then break fi done kill "$pid" 2>/dev/null || true wait "$pid" 2>/dev/null || true set -e if [[ "$started" != "true" ]]; then echo "FAIL: '$label' — server did not start (log below)" >&2 cat "$logfile" >&2 exit 1 fi pass "$label" } echo "" echo "[config validation]" # ── Fail cases ───────────────────────────────────────────────────────────────── # Missing secret → exit 1 run_expect_fail "missing AUTH_COOKIE_SECRET → exit 1" \ env -i "TEST_TMPDIR=$tmpdir" "$server" # Secret too short (62 hex chars = 31 bytes) run_expect_fail "short AUTH_COOKIE_SECRET (62 hex) → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "TEST_TMPDIR=$tmpdir" \ "$server" # Secret with non-hex characters run_expect_fail "non-hex AUTH_COOKIE_SECRET → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "TEST_TMPDIR=$tmpdir" \ "$server" # AUTH_DEV_INSECURE_COOKIE=true with non-loopback SERVER_HOST → exit 1 run_expect_fail "insecure cookie without loopback SERVER_HOST → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=0.0.0.0" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "TEST_TMPDIR=$tmpdir" \ "$server" # AUTH_DEV_INSECURE_COOKIE=true with no SERVER_HOST → exit 1 run_expect_fail "insecure cookie without any SERVER_HOST → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "TEST_TMPDIR=$tmpdir" \ "$server" # Bootstrap username set without hash → exit 1 run_expect_fail "bootstrap username without hash → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "AUTH_BOOTSTRAP_USERNAME=admin" \ "TEST_TMPDIR=$tmpdir" \ "$server" # Bootstrap hash with wrong format → exit 1 run_expect_fail "bootstrap hash with wrong format → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "AUTH_BOOTSTRAP_USERNAME=admin" \ "AUTH_BOOTSTRAP_PASSWORD_HASH=not-a-real-hash" \ "TEST_TMPDIR=$tmpdir" \ "$server" # Bootstrap hash with partial/truncated format → exit 1 run_expect_fail "bootstrap hash truncated (only prefix) → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "AUTH_BOOTSTRAP_USERNAME=admin" \ "AUTH_BOOTSTRAP_PASSWORD_HASH=zenbu-scrypt\$v=1\$N=32768\$r=8\$p=1\$" \ "TEST_TMPDIR=$tmpdir" \ "$server" # idle TTL > abs TTL → exit 1 run_expect_fail "idle TTL exceeds abs TTL → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "AUTH_SESSION_IDLE_TTL=9999999" \ "AUTH_SESSION_ABS_TTL=100" \ "TEST_TMPDIR=$tmpdir" \ "$server" # Malformed AUTH_SESSION_IDLE_TTL (non-integer) → exit 1 run_expect_fail "malformed AUTH_SESSION_IDLE_TTL → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "AUTH_SESSION_IDLE_TTL=3600abc" \ "TEST_TMPDIR=$tmpdir" \ "$server" # Malformed AUTH_SESSION_ABS_TTL (non-integer) → exit 1 run_expect_fail "malformed AUTH_SESSION_ABS_TTL → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "AUTH_SESSION_ABS_TTL=not_a_number" \ "TEST_TMPDIR=$tmpdir" \ "$server" # Malformed S3_URL_EXPIRES (non-integer) → exit 1 run_expect_fail "malformed S3_URL_EXPIRES → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "S3_URL_EXPIRES=3600x" \ "TEST_TMPDIR=$tmpdir" \ "$server" # S3_URL_EXPIRES = 0 (not positive) → exit 1 run_expect_fail "S3_URL_EXPIRES=0 (non-positive) → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "S3_URL_EXPIRES=0" \ "TEST_TMPDIR=$tmpdir" \ "$server" # Trusted proxy with invalid chars → exit 1 run_expect_fail "invalid trusted proxy (bad chars) → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "AUTH_TRUSTED_PROXY=not an ip!" \ "TEST_TMPDIR=$tmpdir" \ "$server" # Trusted proxy with out-of-range IPv4 octet (999.999.999.999) → exit 1 run_expect_fail "trusted proxy 999.999.999.999 → exit 1" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "AUTH_TRUSTED_PROXY=999.999.999.999" \ "TEST_TMPDIR=$tmpdir" \ "$server" # ── Success cases ───────────────────────────────────────────────────────────── # env-only startup (no .config file) with loopback host run_expect_start "env-only startup (no .config) with loopback host" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "MRJUNEJUNE_PORT=16969" \ "TEST_TMPDIR=$tmpdir" \ "$server" # Valid IPv4 trusted proxy is accepted run_expect_start "valid IPv4 trusted proxy accepted" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "AUTH_TRUSTED_PROXY=10.0.0.1" \ "MRJUNEJUNE_PORT=16970" \ "TEST_TMPDIR=$tmpdir" \ "$server" # Valid IPv6 trusted proxy (canonical ::1) is accepted run_expect_start "valid IPv6 trusted proxy (::1) accepted" \ env -i \ "AUTH_COOKIE_SECRET=$GOOD_SECRET" \ "SERVER_HOST=127.0.0.1" \ "AUTH_DEV_INSECURE_COOKIE=true" \ "AUTH_TRUSTED_PROXY=::1" \ "MRJUNEJUNE_PORT=16971" \ "TEST_TMPDIR=$tmpdir" \ "$server" # A service-owned config outside the bundle/workspace is authoritative. The # deliberately bad environment secret must not override the valid file. external_config="$tmpdir/service.config" cat > "$external_config" <<EOF AUTH_COOKIE_SECRET=$GOOD_SECRET SERVER_HOST=127.0.0.1 AUTH_DEV_INSECURE_COOKIE=true MRJUNEJUNE_ALLOW_GUEST_INFERENCE=false DB_PATH=$tmpdir/external-config.db EOF run_expect_start "external config path loads and overrides compatibility env" \ env -i \ "MRJUNEJUNE_CONFIG_PATH=$external_config" \ "AUTH_COOKIE_SECRET=bad-env-secret" \ "MRJUNEJUNE_PORT=16972" \ "TEST_TMPDIR=$tmpdir" \ "$server" echo ""