fix(multiplayer): verify complete durable assignment rosters

This commit is contained in:
Josh Creek
2026-09-03 13:22:02 +01:00
parent bef71e1dcf
commit cee0163eac
4 changed files with 171 additions and 12 deletions
+22 -2
View File
@@ -9,8 +9,9 @@ import (
func TestAssignmentSQLBindsPlayerAndPreservesIdenticalReplay(t *testing.T) {
for query, fragments := range map[string][]string{
AssignmentUpsertSQL: {"ON CONFLICT (match_id, player_id)", "WHERE assignments.allocation_id = EXCLUDED.allocation_id", "join_authorisation", "manifest_digest"},
AssignmentSelectSQL: {"a.match_id = $1", "a.player_id = $2", "a.expires_at > $3", "JOIN matches", "ASSIGNMENT_READY", "m.server_id = a.server_id"},
AssignmentUpsertSQL: {"ON CONFLICT (match_id, player_id)", "WHERE assignments.allocation_id = EXCLUDED.allocation_id", "join_authorisation", "manifest_digest"},
AssignmentSelectSQL: {"a.match_id = $1", "a.player_id = $2", "a.expires_at > $3", "JOIN matches", "ASSIGNMENT_READY", "m.server_id = a.server_id"},
AssignmentExpectedRosterSQL: {"match_participants", "identities", "allocations", "m.allocation_id = $2", "m.server_id = $3", "a.state = 'ALLOCATED'", "participation_active", "FOR UPDATE OF mp"},
} {
for _, fragment := range fragments {
if !contains(query, fragment) {
@@ -20,6 +21,25 @@ func TestAssignmentSQLBindsPlayerAndPreservesIdenticalReplay(t *testing.T) {
}
}
func TestAssignmentBatchRejectsMixedAuthorityAndDuplicateSlots(t *testing.T) {
base := DurableAssignment{MatchID: "match-1", PlayerID: "player-1", AllocationID: "allocation-1", ServerID: "server-1", Slot: 0, Region: "EU", ClientBuild: "build-1", ProtocolVersion: 1, Transport: "enet", Endpoint: "127.0.0.1:1", JoinAuthorisation: "join-1", ManifestDigest: []byte("digest"), ExpiresAt: time.Unix(1001, 0), Revision: 1}
other := base
other.PlayerID = "player-2"
other.JoinAuthorisation = "join-2"
if err := validateAssignmentBatch([]DurableAssignment{base, other}); err == nil {
t.Fatal("duplicate slot accepted")
}
other.Slot = 3
other.ServerID = "server-2"
if err := validateAssignmentBatch([]DurableAssignment{base, other}); err == nil {
t.Fatal("mixed server batch accepted")
}
other.ServerID = base.ServerID
if err := validateAssignmentBatch([]DurableAssignment{base, other}); err != nil {
t.Fatalf("valid assignment batch rejected: %v", err)
}
}
func TestAssignmentStoreRejectsInvalidRecoveryAndManifestInputs(t *testing.T) {
if _, err := GetAssignment(nil, nil, "player-1", "match-1", time.Unix(1000, 0)); err == nil {
t.Fatal("nil database accepted")