mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-16 09:22:21 +00:00
fix(multiplayer): recover assignment handoff
This commit is contained in:
@@ -110,6 +110,37 @@ func test_websocket_event_validation_requires_contract_specific_fields() -> void
|
||||
var unsafe_resource := envelope.duplicate()
|
||||
unsafe_resource["resource_id"] = "ticket_123456789/secret"
|
||||
assert_true(not ControlPlaneClient._valid_websocket_event(unsafe_resource), "resource identifier with separators is rejected")
|
||||
var match_state := {"event": "state_changed", "revision": 4, "resource_id": "match_1234567890", "occurred_at": "2026-08-31T12:00:00Z", "state": "ASSIGNMENT_READY", "match_id": "match_1234567890"}
|
||||
assert_true(ControlPlaneClient._valid_websocket_event(match_state), "match-scoped lifecycle event is accepted")
|
||||
match_state["match_id"] = "different_match_123"
|
||||
assert_true(not ControlPlaneClient._valid_websocket_event(match_state), "match lifecycle identity must equal its resource identity")
|
||||
|
||||
|
||||
func test_match_assignment_ready_event_recovers_ticket_and_schedules_assignment_fetch() -> void:
|
||||
var client := ControlPlaneClient.new()
|
||||
client._ready()
|
||||
assert_true(client.state.begin_queue("ticket_assignment_1", "casual"), "queue setup succeeds")
|
||||
client._operation = "queue_heartbeat"
|
||||
var event := {"event": "state_changed", "revision": 4, "resource_id": "match_assignment_1", "occurred_at": "2026-08-31T12:00:00Z", "state": "ASSIGNMENT_READY", "match_id": "match_assignment_1"}
|
||||
client._handle_websocket_packet(JSON.stringify(event).to_utf8_buffer())
|
||||
assert_eq(client._pending_resync_resource_id, "ticket_assignment_1", "match event requests authoritative ticket recovery")
|
||||
assert_eq(client._pending_assignment_match_id, "match_assignment_1", "assignment lookup no longer depends on a prior assignment GET")
|
||||
assert_eq(client.state.ticket_id, "ticket_assignment_1", "match resource is never projected as a ticket identity")
|
||||
client.free()
|
||||
|
||||
|
||||
func test_recovered_assignment_ready_ticket_schedules_fetch_after_missed_revisions() -> void:
|
||||
var client := ControlPlaneClient.new()
|
||||
client._ready()
|
||||
client.player_id = "player_1234567890"
|
||||
client.state.begin_queue("ticket_assignment_1", "casual")
|
||||
assert_true(client.state.apply_ticket_update({"ticket_id": "ticket_assignment_1", "revision": 1, "state": "PROPOSED", "playlist": "casual"}), "proposal setup applies")
|
||||
client._operation = "queue_recover"
|
||||
var recovered := {"ticket_id": "ticket_assignment_1", "player_id": "player_1234567890", "match_id": "match_assignment_1", "playlist": "casual", "state": "ASSIGNMENT_READY", "revision": 5, "enqueued_at": "2026-08-31T12:00:00Z", "expires_at": "2026-08-31T12:01:00Z"}
|
||||
client._on_request_completed(HTTPRequest.RESULT_SUCCESS, 200, PackedStringArray(), JSON.stringify(recovered).to_utf8_buffer())
|
||||
assert_eq(client.state.phase, MatchmakingState.ASSIGNMENT_READY, "REST recovery applies a forward authoritative snapshot")
|
||||
assert_eq(client._pending_assignment_match_id, "match_assignment_1", "recovered snapshot supplies the assignment lookup key")
|
||||
client.free()
|
||||
|
||||
|
||||
func test_websocket_reconnect_defers_recovery_while_http_mutation_is_in_flight() -> void:
|
||||
@@ -188,6 +219,15 @@ func test_queue_response_requires_the_complete_contract_shape() -> void:
|
||||
var malformed_player := valid.duplicate()
|
||||
malformed_player["player_id"] = "player/unsafe"
|
||||
assert_true(not ControlPlaneClient._valid_queue_response(malformed_player), "unsafe queue player id is rejected")
|
||||
var assigned := valid.duplicate()
|
||||
assigned["state"] = "ASSIGNMENT_READY"
|
||||
assigned["match_id"] = "match_1234567890"
|
||||
assert_true(ControlPlaneClient._valid_queue_response(assigned), "recovered assignment-ready ticket carries its match lookup identity")
|
||||
var premature_match := valid.duplicate()
|
||||
premature_match["match_id"] = "match_1234567890"
|
||||
assert_true(not ControlPlaneClient._valid_queue_response(premature_match), "pre-match ticket cannot smuggle a match identity")
|
||||
assigned["match_id"] = "match/unsafe"
|
||||
assert_true(not ControlPlaneClient._valid_queue_response(assigned), "unsafe recovered match identity is rejected")
|
||||
|
||||
|
||||
func test_proposal_response_requires_structured_unique_participants() -> void:
|
||||
|
||||
Reference in New Issue
Block a user