package store import ( "context" "database/sql" "testing" "time" "github.com/cosmic-clash/cosmic-clash/server/domain" ) func TestResultSQLPreservesReceiptConflictAndAtomicCommitBoundaries(t *testing.T) { checks := map[string][]string{ ResultReceiptInsertSQL: {"ON CONFLICT DO NOTHING", "payload_digest", "integrity_state"}, ResultReceiptSelectSQL: {"FOR UPDATE", "committed_at"}, ResultCommitLockSQL: {"server_id = $2", "FOR UPDATE"}, ResultMatchPendingSQL: {"state = 'RESULT_PENDING'", "state = 'LIVE'", "revision = revision + 1"}, ResultTicketsPendingSQL: {"queue_tickets", "match_participants", "participation_active", "state = 'LIVE'"}, ResultMatchCompleteSQL: {"state = 'RESULT_PENDING'", "revision = revision + 1"}, ResultTicketsCompleteSQL: {"state = 'COMPLETED'", "state = 'RESULT_PENDING'", "match_participants", "participation_active"}, ResultParticipantCountSQL: {"count(*)", "match_participants", "match_id = $1", "participation_active"}, ResultReceiptCommitSQL: {"COALESCE(committed_at", "committed_at"}, ResultOutboxSQL: {"match_completed", "aggregate_id", "revision"}, RatingLockSQL: {"ORDER BY player_id", "FOR UPDATE"}, MatchParticipantRatingsSQL: {"match_participants", "abandoned_at", "JOIN ratings", "participation_active", "ORDER BY mp.player_id"}, RatingValuesSQL: {"player_id = ANY($1)", "ORDER BY player_id"}, RatingUpdateSQL: {"ranked_games = ranked_games + $5", "revision = revision + 1"}, } for query, fragments := range checks { for _, fragment := range fragments { if !contains(query, fragment) { t.Fatalf("query %q missing %q", query, fragment) } } } } func TestCompleteResultWithResultRejectsReceiptResultMismatchBeforeDatabaseUse(t *testing.T) { now := time.Unix(100, 0).UTC() result := domain.MatchResult{ MatchID: "match", ServerID: "server", ResultNonce: "nonce-1234567890123456", Team0Score: 1, Team1Score: 0, IntegrityState: domain.IntegrityCertified, } receipt := domain.ResultReceipt{ ResultID: "result", MatchID: result.MatchID, ResultNonce: result.ResultNonce, PayloadDigest: domain.ResultDigest(result), IntegrityState: result.IntegrityState, ReceivedAt: now, } result.Team0Score = 2 if err := CompleteResultWithResult(context.Background(), nil, receipt, "server", "event", []byte("payload"), result, now); err == nil { t.Fatal("mismatched result was accepted") } } func TestCompleteResultRejectsIncompleteReceiptBeforeDatabaseUse(t *testing.T) { now := time.Unix(100, 0).UTC() receipt := domain.ResultReceipt{ResultID: "result", MatchID: "match", ResultNonce: "nonce-1234567890123456", IntegrityState: domain.IntegrityCertified, ReceivedAt: now} if err := CompleteResult(context.Background(), nil, receipt, "server", "event", []byte("payload"), now); err == nil { t.Fatal("nil database accepted") } receipt.ReceivedAt = time.Time{} if err := CompleteResult(context.Background(), &sql.DB{}, receipt, "server", "event", []byte("payload"), now); err == nil { t.Fatal("zero receipt time accepted") } } func contains(value, fragment string) bool { for i := 0; i+len(fragment) <= len(value); i++ { if value[i:i+len(fragment)] == fragment { return true } } return false }