From b15081076e4efc36734bc725b9fd587de535cf2f Mon Sep 17 00:00:00 2001 From: Vernon Stinebaker Date: Tue, 5 May 2026 12:38:49 +0800 Subject: [PATCH 1/2] test(smoke): isolate E2E home and detect server exits --- tests/test_e2e.sh | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/tests/test_e2e.sh b/tests/test_e2e.sh index 1d133b5..bff08ec 100755 --- a/tests/test_e2e.sh +++ b/tests/test_e2e.sh @@ -10,6 +10,34 @@ PASSED=0 FAILED=0 PORT=19800 # Use high port to avoid conflicts BASE="http://127.0.0.1:$PORT" +TEST_HOME=$(mktemp -d "${TMPDIR:-/tmp}/nullhub-e2e.XXXXXX") +SERVER_LOG="$TEST_HOME/nullhub-server.log" + +server_is_running() { + kill -0 "$SERVER_PID" 2>/dev/null +} + +fail_if_server_exited() { + local context="$1" + + if server_is_running; then + return 0 + fi + + local exit_code=0 + set +e + wait "$SERVER_PID" + exit_code=$? + set -e + + echo -e "${RED}FAIL${NC}: nullhub exited unexpectedly during $context (exit $exit_code)" + if [ -f "$SERVER_LOG" ]; then + echo "--- nullhub server log ---" + cat "$SERVER_LOG" + echo "--- end nullhub server log ---" + fi + exit 1 +} # Build echo "Building nullhub..." @@ -18,20 +46,24 @@ EXPECTED_VERSION=$(./zig-out/bin/nullhub --version 2>&1 | awk '{print $2}' | sed # Start server in background echo "Starting nullhub on port $PORT..." -./zig-out/bin/nullhub serve --port $PORT --no-open & +HOME="$TEST_HOME" ./zig-out/bin/nullhub serve --port "$PORT" --no-open >"$SERVER_LOG" 2>&1 & SERVER_PID=$! # Cleanup on exit cleanup() { echo "Stopping server..." - kill $SERVER_PID 2>/dev/null || true - wait $SERVER_PID 2>/dev/null || true + if [ -n "${SERVER_PID:-}" ]; then + kill "$SERVER_PID" 2>/dev/null || true + wait "$SERVER_PID" 2>/dev/null || true + fi + rm -rf "$TEST_HOME" } trap cleanup EXIT # Wait for server to be ready (retry loop instead of fixed sleep) echo "Waiting for server..." for i in $(seq 1 20); do + fail_if_server_exited "startup" if curl -s -o /dev/null -w "%{http_code}" "$BASE/health" 2>/dev/null | grep -q "200"; then echo "Server ready after ${i} attempt(s)." break @@ -51,12 +83,16 @@ assert_status() { local url="$4" local body="${5:-}" + fail_if_server_exited "$description (before request)" + if [ -n "$body" ]; then actual=$(curl -s -o /dev/null -w "%{http_code}" -X "$method" -H "Content-Type: application/json" -d "$body" "$url") else actual=$(curl -s -o /dev/null -w "%{http_code}" -X "$method" "$url") fi + fail_if_server_exited "$description (after request)" + if [ "$actual" = "$expected" ]; then echo -e "${GREEN}PASS${NC}: $description (HTTP $actual)" PASSED=$((PASSED + 1)) @@ -72,7 +108,9 @@ assert_json_field() { local field="$3" local expected="$4" + fail_if_server_exited "$description (before request)" local response=$(curl -s "$url") + fail_if_server_exited "$description (after request)" local actual=$(echo "$response" | python3 -c "import sys,json; print(json.load(sys.stdin)$field)" 2>/dev/null || echo "PARSE_ERROR") if [ "$actual" = "$expected" ]; then @@ -129,6 +167,8 @@ echo "================================" echo -e "Results: ${GREEN}$PASSED passed${NC}, ${RED}$FAILED failed${NC}" echo "================================" +fail_if_server_exited "final result collection" + if [ $FAILED -gt 0 ]; then exit 1 fi From 959345734ab4645f83085a90d82ab372e4e0021b Mon Sep 17 00:00:00 2001 From: Igor Somov Date: Tue, 5 May 2026 13:07:31 -0300 Subject: [PATCH 2/2] test(smoke): harden e2e server diagnostics --- tests/test_e2e.sh | 50 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/tests/test_e2e.sh b/tests/test_e2e.sh index bff08ec..4e3fc3d 100755 --- a/tests/test_e2e.sh +++ b/tests/test_e2e.sh @@ -12,8 +12,23 @@ PORT=19800 # Use high port to avoid conflicts BASE="http://127.0.0.1:$PORT" TEST_HOME=$(mktemp -d "${TMPDIR:-/tmp}/nullhub-e2e.XXXXXX") SERVER_LOG="$TEST_HOME/nullhub-server.log" +SERVER_PID="" + +# Cleanup on exit +cleanup() { + if [ -n "${SERVER_PID:-}" ]; then + echo "Stopping server..." + kill "$SERVER_PID" 2>/dev/null || true + wait "$SERVER_PID" 2>/dev/null || true + fi + rm -rf "$TEST_HOME" +} +trap cleanup EXIT server_is_running() { + if [ -z "${SERVER_PID:-}" ]; then + return 1 + fi kill -0 "$SERVER_PID" 2>/dev/null } @@ -49,17 +64,6 @@ echo "Starting nullhub on port $PORT..." HOME="$TEST_HOME" ./zig-out/bin/nullhub serve --port "$PORT" --no-open >"$SERVER_LOG" 2>&1 & SERVER_PID=$! -# Cleanup on exit -cleanup() { - echo "Stopping server..." - if [ -n "${SERVER_PID:-}" ]; then - kill "$SERVER_PID" 2>/dev/null || true - wait "$SERVER_PID" 2>/dev/null || true - fi - rm -rf "$TEST_HOME" -} -trap cleanup EXIT - # Wait for server to be ready (retry loop instead of fixed sleep) echo "Waiting for server..." for i in $(seq 1 20); do @@ -82,17 +86,26 @@ assert_status() { local method="$3" local url="$4" local body="${5:-}" + local actual="" + local curl_exit=0 fail_if_server_exited "$description (before request)" + set +e if [ -n "$body" ]; then actual=$(curl -s -o /dev/null -w "%{http_code}" -X "$method" -H "Content-Type: application/json" -d "$body" "$url") else actual=$(curl -s -o /dev/null -w "%{http_code}" -X "$method" "$url") fi + curl_exit=$? + set -e fail_if_server_exited "$description (after request)" + if [ "$curl_exit" -ne 0 ]; then + actual="CURL_ERROR($curl_exit, HTTP ${actual:-000})" + fi + if [ "$actual" = "$expected" ]; then echo -e "${GREEN}PASS${NC}: $description (HTTP $actual)" PASSED=$((PASSED + 1)) @@ -107,11 +120,22 @@ assert_json_field() { local url="$2" local field="$3" local expected="$4" + local response="" + local curl_exit=0 + local actual="" fail_if_server_exited "$description (before request)" - local response=$(curl -s "$url") + set +e + response=$(curl -s "$url") + curl_exit=$? + set -e fail_if_server_exited "$description (after request)" - local actual=$(echo "$response" | python3 -c "import sys,json; print(json.load(sys.stdin)$field)" 2>/dev/null || echo "PARSE_ERROR") + + if [ "$curl_exit" -ne 0 ]; then + actual="CURL_ERROR($curl_exit)" + else + actual=$(echo "$response" | python3 -c "import sys,json; print(json.load(sys.stdin)$field)" 2>/dev/null || echo "PARSE_ERROR") + fi if [ "$actual" = "$expected" ]; then echo -e "${GREEN}PASS${NC}: $description ($field = $actual)"