mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
test(multiplayer): add allocated compose smoke flow
This commit is contained in:
Executable
+89
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Independent allocated-flow fixture for multiplayer-next.md §8.48. This
|
||||
# intentionally does not call compose.phase6-smoke.yml or reuse its ports.
|
||||
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
compose_file="$root_dir/compose.allocated-smoke.yml"
|
||||
project="${COMPOSE_PROJECT_NAME:-cosmic-clash-allocated-smoke}"
|
||||
api_url="http://127.0.0.1:18080"
|
||||
secret="compose-workload-secret"
|
||||
compose=(docker compose -p "$project" -f "$compose_file")
|
||||
|
||||
cleanup() {
|
||||
local rc=$?
|
||||
"${compose[@]}" down --volumes --remove-orphans >/dev/null 2>&1 || true
|
||||
exit "$rc"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
command -v docker >/dev/null 2>&1 || { echo "Docker is required for 8.48" >&2; exit 2; }
|
||||
docker info >/dev/null 2>&1 || { echo "A running Docker daemon is required for 8.48" >&2; exit 2; }
|
||||
|
||||
"${compose[@]}" down --volumes --remove-orphans >/dev/null 2>&1 || true
|
||||
"${compose[@]}" up -d --build
|
||||
|
||||
for attempt in $(seq 1 60); do
|
||||
if curl -fsS "$api_url/healthz" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
if [[ "$attempt" == 60 ]]; then
|
||||
"${compose[@]}" logs >&2
|
||||
echo "allocated Compose control plane did not become ready" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Model the durable state produced by the allocator, then use the real HTTP
|
||||
# workload authentication and mutation boundaries for every action below.
|
||||
"${compose[@]}" exec -T database psql -v ON_ERROR_STOP=1 -U cosmic_clash_test -d cosmic_clash_test <<'SQL'
|
||||
INSERT INTO game_servers (server_id, region, build, protocol_version, transport, state)
|
||||
VALUES ('compose-server', 'EU', 'build-1', 1, 'enet', 'ALLOCATED');
|
||||
INSERT INTO matches (match_id, playlist, state, region, protocol_version, server_id, revision)
|
||||
VALUES ('compose-match', 'casual', 'RESULT_PENDING', 'EU', 1, 'compose-server', 2);
|
||||
INSERT INTO allocations (allocation_id, match_id, server_id, region, build, protocol_version, transport, request_digest, state, allocated_at)
|
||||
VALUES ('compose-allocation', 'compose-match', 'compose-server', 'EU', 'build-1', 1, 'enet', decode(repeat('00', 32), 'hex'), 'ALLOCATED', now());
|
||||
SQL
|
||||
|
||||
token="$(python3 - "$secret" <<'PY'
|
||||
import base64, hashlib, hmac, json, sys, time
|
||||
secret = sys.argv[1].encode()
|
||||
payload = {"a": "compose-allocation", "e": time.time() + 300}
|
||||
encoded = base64.urlsafe_b64encode(json.dumps(payload, separators=(",", ":")).encode()).rstrip(b"=")
|
||||
signature = hmac.new(secret, encoded, hashlib.sha256).digest()
|
||||
sig = base64.urlsafe_b64encode(signature).rstrip(b"=")
|
||||
print(encoded.decode() + "." + sig.decode())
|
||||
PY
|
||||
)"
|
||||
|
||||
result_body='{"match_id":"compose-match","result_nonce":"compose-result-nonce-1234","score":{"team_0":3,"team_1":2},"integrity_state":"CERTIFIED"}'
|
||||
curl -fsS -o /dev/null -w '%{http_code}' \
|
||||
-X POST "$api_url/v1/servers/compose-server/result" \
|
||||
-H "Authorization: Bearer $token" \
|
||||
-H 'Idempotency-Key: compose-result-key-123456' \
|
||||
-H 'Content-Type: application/json' -d "$result_body" | grep -qx 202
|
||||
|
||||
# An identical retry must be acknowledged without a second receipt.
|
||||
curl -fsS -o /dev/null -w '%{http_code}' \
|
||||
-X POST "$api_url/v1/servers/compose-server/result" \
|
||||
-H "Authorization: Bearer $token" \
|
||||
-H 'Idempotency-Key: compose-result-key-123456' \
|
||||
-H 'Content-Type: application/json' -d "$result_body" | grep -qx 202
|
||||
|
||||
"${compose[@]}" exec -T database psql -At -U cosmic_clash_test -d cosmic_clash_test -c "SELECT state FROM matches WHERE match_id = 'compose-match'" | grep -qx COMPLETED
|
||||
"${compose[@]}" exec -T database psql -At -U cosmic_clash_test -d cosmic_clash_test -c "SELECT count(*) FROM result_receipts WHERE match_id = 'compose-match'" | grep -qx 1
|
||||
|
||||
curl -fsS -o /dev/null -w '%{http_code}' \
|
||||
-X POST "$api_url/v1/servers/compose-server/shutdown" \
|
||||
-H "Authorization: Bearer $token" \
|
||||
-H 'Idempotency-Key: compose-shutdown-key-123456' \
|
||||
-H 'Content-Type: application/json' -d '{"reason":"server_draining"}' | grep -qx 204
|
||||
|
||||
"${compose[@]}" exec -T database psql -At -U cosmic_clash_test -d cosmic_clash_test -c "SELECT count(*) FROM audit_events WHERE action = 'SERVER_SHUTDOWN' AND aggregate_id = 'compose-match'" | grep -qx 1
|
||||
"${compose[@]}" stop -t 10 control-plane >/dev/null
|
||||
if "${compose[@]}" ps --status running --services | grep -qx control-plane; then
|
||||
echo "control-plane did not stop cleanly" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "8.48 PASS: allocated Compose HTTP result/retry/shutdown flow completed"
|
||||
@@ -28,6 +28,7 @@ echo "local multiplayer gate: contracts and manifests"
|
||||
python3 -m json.tool "$root_dir/server/contracts/v1/openapi.json" >/dev/null
|
||||
python3 "$root_dir/server/migrations/test_migration.py"
|
||||
python3 "$root_dir/server/security/test_fleet_manifests.py"
|
||||
python3 "$root_dir/server/security/test_compose_manifests.py"
|
||||
python3 "$root_dir/server/security/test_kubernetes_policies.py"
|
||||
python3 "$root_dir/server/security/test_supply_chain.py"
|
||||
python3 "$root_dir/scripts/verify_observability_manifests.py"
|
||||
|
||||
Reference in New Issue
Block a user