#!/usr/bin/env bash # tests/pgserver/run.sh — integration harness for the pgserver wire # layer. Builds a bootstrap PRG that starts the server, then drives # it from a Go-side pgx client (located alongside this script). # # Verified scope (Phase 3): # * CREATE TABLE / INSERT / UPDATE / DELETE over Simple Query # * BEGIN / COMMIT / ROLLBACK from the wire # * Two-connection cross-visibility on shared DBF # * Per-session ROLLBACK doesn't affect other connection # # Known limitation (tracked for Phase 7): # * ≥3 concurrent connections doing in-flight INSERT/SELECT in # their own transactions can race at the hbrdd workarea layer # — surfaces as one worker's just-inserted row missing from its # own SELECT. Two-connection serial use, and N-connection use # where each goroutine completes its txn before the next starts, # are both reliable. Multi-way append-time WA arbitration is # deferred until the audit's "WorkArea collision under multi- # session" Top-Risk #2 fix lands. set -e ROOT="$(cd "$(dirname "$0")/../.." && pwd)" FIVE="$ROOT/five" PORT="${PGSERVER_TEST_PORT:-15432}" if [ ! -x "$FIVE" ]; then echo "five binary not found at $FIVE — run 'go build -o five ./cmd/five' first" >&2 exit 2 fi if ! command -v psql >/dev/null 2>&1; then echo "psql not in PATH — install PostgreSQL client tools to run this suite" >&2 exit 2 fi work="$(mktemp -d)" trap 'rm -rf "$work"' EXIT # Bootstrap PRG — opens nothing, just stands up the server. cat > "$work/boot.prg" </dev/null 2>&1 "$work/boot" & SERVER_PID=$! sleep 1 trap "kill $SERVER_PID 2>/dev/null; rm -rf '$work'" EXIT pass=0 total=0 ok() { pass=$((pass+1)) total=$((total+1)) echo "PASS $1" } fail() { total=$((total+1)) echo "FAIL $1" echo "$2" | sed 's/^/ /' } # 1) Simple Query via psql. out="$(psql "postgres://alice:any@127.0.0.1:$PORT/alice?sslmode=disable" \ -c "SELECT 1 AS one, 'hello' AS greet" -At 2>&1 || true)" if echo "$out" | grep -q "1|hello"; then ok "Simple Query: SELECT 1, 'hello'" else fail "Simple Query: SELECT 1, 'hello'" "$out" fi # 2) Multi-statement Simple Query — each ';'-separated stmt rolls # through the engine independently. Verifies wire reuses one # session across statements without bleed. out="$(psql "postgres://alice:any@127.0.0.1:$PORT/alice?sslmode=disable" -At <&1 || true SELECT 'first'; SELECT 2 AS n; SQL )" if echo "$out" | grep -q "first" && echo "$out" | grep -q "^2$"; then ok "Multi-statement Simple Query" else fail "Multi-statement Simple Query" "$out" fi # Note on Extended Protocol coverage: # psql can't drive raw Parse/Bind/Execute from -c invocations # (PG's SQL-level PREPARE/EXECUTE is a separate feature that # FiveSql2 doesn't parse). The Extended Protocol path is instead # covered by hbrtl/pgserver/wire_test.go (Go unit) plus the # pgx-driven manual sanity script in /tmp/pgs_test/. Adding a # self-contained Go integration that bootstraps the server + # drives pgx in one process is Phase 7 work. # 3) Transaction control via simple query — BEGIN/COMMIT round-trip # must leave ReadyForQuery in 'I' state so psql doesn't hang on # the next command. out="$(psql "postgres://alice:any@127.0.0.1:$PORT/alice?sslmode=disable" -At <&1 || true BEGIN; SELECT 'in-txn'; COMMIT; SELECT 'post-commit'; SQL )" if echo "$out" | grep -q "in-txn" && echo "$out" | grep -q "post-commit"; then ok "Transaction control: BEGIN/COMMIT round-trip" else fail "Transaction control: BEGIN/COMMIT round-trip" "$out" fi # 4) MD5 authentication — kill the trust-mode server, restart with # md5 + a known role, then verify both the rejection and success # paths. kill $SERVER_PID 2>/dev/null wait 2>/dev/null cat > "$work/auth.prg" </dev/null 2>&1 "$work/auth" & SERVER_PID=$! sleep 1 trap "kill $SERVER_PID 2>/dev/null; rm -rf '$work'" EXIT bad="$(PGPASSWORD=wrong psql "postgres://alice@127.0.0.1:$PORT/alice?sslmode=disable" \ -c "SELECT 1" 2>&1 | head -1 || true)" if echo "$bad" | grep -qi "md5 authentication failed"; then ok "MD5 auth: wrong password rejected" else fail "MD5 auth: wrong password rejected" "$bad" fi good="$(PGPASSWORD=swordfish psql "postgres://alice@127.0.0.1:$PORT/alice?sslmode=disable" \ -c "SELECT 'ok' AS x" -At 2>&1 || true)" if echo "$good" | grep -q "^ok$"; then ok "MD5 auth: correct password accepted" else fail "MD5 auth: correct password accepted" "$good" fi echo "================================================================" echo " pgserver integration: $pass / $total passed" echo "================================================================" [ $pass -eq $total ]