#!/usr/bin/env bash set -euo pipefail root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$root_dir" if [[ -n "${GODOT_BIN:-}" ]]; then godot_bin="$GODOT_BIN" elif command -v godot >/dev/null 2>&1; then godot_bin="$(command -v godot)" elif [[ -x "/Applications/Godot.app/Contents/MacOS/Godot" ]]; then godot_bin="/Applications/Godot.app/Contents/MacOS/Godot" else godot_bin="godot" fi logs_dir="$(mktemp -d "${TMPDIR:-/tmp}/cosmic-clash-enet.XXXXXX")" pids=() # Comma-separated selection for local debugging; CI leaves this unset and # therefore runs the complete suite. selected_cases=",${VERIFY_ENET_CASES:-net,match-net,clock,lobby,networked-match}," cleanup() { local status=$? if (( status != 0 )); then for log_file in "$logs_dir"/*.log; do [[ -f "$log_file" ]] || continue echo "--- $log_file" >&2 cat "$log_file" >&2 done fi for pid in "${pids[@]}"; do kill "$pid" 2>/dev/null || true done echo "ENet integration logs: $logs_dir" } trap cleanup EXIT start_role() { local log_file="$1" local scene="$2" shift 2 "$godot_bin" --headless --path Game "$scene" -- "$@" >"$log_file" 2>&1 & pids+=("$!") } wait_for_role() { local pid="$1" wait "$pid" } assert_clean_logs() { local label="$1" shift if grep -E "(SCRIPT ERROR|ERROR:|SMOKE FAIL)" "$@"; then echo "$label emitted an engine or smoke error" >&2 return 1 fi } run_pair() { local label="$1" local scene="$2" local host_log="$logs_dir/${label}-host.log" local client_log="$logs_dir/${label}-client.log" echo "ENet integration: $label" start_role "$host_log" "$scene" --role=host local host_pid="${pids[${#pids[@]} - 1]}" sleep 0.5 start_role "$client_log" "$scene" --role=client local client_pid="${pids[${#pids[@]} - 1]}" wait_for_role "$client_pid" wait_for_role "$host_pid" assert_clean_logs "$label" "$host_log" "$client_log" } run_networked_match() { local host_log="$logs_dir/networked-match-host.log" local client_one_log="$logs_dir/networked-match-client-one.log" local client_two_log="$logs_dir/networked-match-client-two.log" echo "ENet integration: networked match" start_role "$host_log" res://tests/networked_match_ci.tscn --role=host local host_pid="${pids[${#pids[@]} - 1]}" sleep 0.5 start_role "$client_one_log" res://tests/networked_match_ci.tscn --role=client-bot --test-bot local client_one_pid="${pids[${#pids[@]} - 1]}" sleep 0.2 start_role "$client_two_log" res://tests/networked_match_ci.tscn --role=client-bot --test-bot local client_two_pid="${pids[${#pids[@]} - 1]}" wait_for_role "$client_one_pid" wait_for_role "$client_two_pid" wait_for_role "$host_pid" assert_clean_logs "networked match" "$host_log" "$client_one_log" "$client_two_log" } if [[ "$selected_cases" == *",net,"* ]]; then run_pair net res://tests/net_smoke.tscn fi if [[ "$selected_cases" == *",match-net,"* ]]; then run_pair match-net res://tests/match_net_smoke.tscn fi if [[ "$selected_cases" == *",clock,"* ]]; then run_pair clock res://tests/clock_smoke.tscn fi if [[ "$selected_cases" == *",lobby,"* ]]; then run_pair lobby res://tests/lobby_smoke.tscn fi if [[ "$selected_cases" == *",networked-match,"* ]]; then run_networked_match fi echo "ENet integration verification passed"