#!/usr/bin/env bash # next/tests/http_server_tcp.sh — Step 9a-tcp live TCP smoke test. # # Boots sx_server in the background with a script that loads # http_server.erl and calls http_server:start/1 on a high port, # then drives the running server with curl from this shell to # verify the request → marshaling → route → marshaling → HTTP # response chain end-to-end. # # Boot timing: ~10s for all `lib/erlang/*.sx` loads + module # compile + spawn + Unix.bind. We hold the server's stdin open # via `(cat file; sleep 60) | sx_server` so EOF doesn't trigger # exit(0) before the listener finishes binding. set -uo pipefail cd "$(git rev-parse --show-toplevel)" SX_SERVER="${SX_SERVER:-hosts/ocaml/_build/default/bin/sx_server.exe}" if [ ! -x "$SX_SERVER" ]; then SX_SERVER="/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe" fi if [ ! -x "$SX_SERVER" ]; then echo "ERROR: sx_server.exe not found." >&2 exit 1 fi PORT=51820 VERBOSE="${1:-}" PASS=0; FAIL=0; ERRORS="" EPOCH_FILE=$(mktemp) LOG_FILE=$(mktemp) cleanup() { if [ -n "${SXPID:-}" ]; then kill -KILL "$SXPID" 2>/dev/null || true wait "$SXPID" 2>/dev/null || true fi if [ -n "${HOLDPID:-}" ]; then kill -KILL "$HOLDPID" 2>/dev/null || true wait "$HOLDPID" 2>/dev/null || true fi rm -f "$EPOCH_FILE" "$LOG_FILE" } trap cleanup EXIT cat > "$EPOCH_FILE" < "$FIFO" & HOLDPID=$! "$SX_SERVER" < "$FIFO" > "$LOG_FILE" 2>&1 & SXPID=$! rm -f "$FIFO" # both ends still hold open via the running procs # Wait for the listener to bind (up to ~30s — boot takes ~10s). BOUND="" for i in $(seq 1 60); do if (exec 3<>/dev/tcp/127.0.0.1/$PORT) 2>/dev/null; then exec 3<&-; exec 3>&- BOUND="yes" break fi sleep 0.5 done if [ -z "$BOUND" ]; then echo "FAIL: listener never bound on port $PORT" if [ "$VERBOSE" = "-v" ]; then echo "--- sx_server output ---" cat "$LOG_FILE" echo "---" fi exit 1 fi check_http() { local desc="$1" method="$2" path="$3" auth="$4" expected_status="$5" expected_body_substr="$6" local args=() args+=(-s -o /tmp/http_body.out -w "%{http_code}") args+=(-X "$method") if [ -n "$auth" ]; then args+=(-H "Authorization: $auth") fi if [ "$method" = "POST" ]; then args+=(-d "") fi args+=("http://127.0.0.1:$PORT$path") local code code=$(curl "${args[@]}" 2>/dev/null || echo "000") local body body=$(cat /tmp/http_body.out 2>/dev/null || echo "") local pass=1 if [ "$code" != "$expected_status" ]; then pass=0; fi if [ -n "$expected_body_substr" ] && ! echo "$body" | grep -qF -- "$expected_body_substr"; then pass=0; fi if [ $pass -eq 1 ]; then PASS=$((PASS+1)) [ "$VERBOSE" = "-v" ] && echo " ok $desc ($code)" else FAIL=$((FAIL+1)) ERRORS+=" FAIL [$desc] code=$code body=$body " fi } check_http "GET / -> 200" GET / "" 200 "" check_http "GET capabilities -> 200" GET /.well-known/sx-capabilities "" 200 "kernel:" check_http "GET unknown -> 404" GET /no-such-path "" 404 "" check_http "POST /activity no bearer -> 401" POST /activity "" 401 "" check_http "POST /activity bad bearer -> 401" POST /activity "Bearer wrong" 401 "" TOTAL=$((PASS+FAIL)) if [ $FAIL -eq 0 ]; then echo "ok $PASS/$TOTAL http_server_tcp tests passed (port $PORT)" else echo "FAIL $PASS/$TOTAL passed, $FAIL failed:" echo "$ERRORS" if [ "$VERBOSE" = "-v" ]; then echo "--- sx_server output (last 30 lines) ---" tail -30 "$LOG_FILE" echo "---" fi fi [ $FAIL -eq 0 ]