Files
CosmicClash/server/store/candidates_test.go
T
2026-08-31 22:12:03 +01:00

67 lines
2.4 KiB
Go

package store
import (
"testing"
"time"
"github.com/cosmic-clash/cosmic-clash/server/domain"
)
func TestCandidateCacheRebuildRepairsLossAndKeepsDeterministicOrder(t *testing.T) {
now := time.Unix(1000, 0)
cache := NewCandidateCache()
candidates := []domain.Candidate{{TicketID: "ticket-b", PlayerID: "player-b", EnqueuedAt: now}, {TicketID: "ticket-a", PlayerID: "player-a", EnqueuedAt: now}}
if err := cache.Rebuild(candidates); err != nil {
t.Fatal(err)
}
cache.Remove("ticket-a")
if got := cache.Snapshot(now); len(got) != 1 || got[0].TicketID != "ticket-b" {
t.Fatalf("stale cache snapshot = %+v", got)
}
if err := cache.Rebuild(candidates); err != nil {
t.Fatal(err)
}
got := cache.Snapshot(now)
if len(got) != 2 || got[0].TicketID != "ticket-a" || got[1].TicketID != "ticket-b" {
t.Fatalf("repaired order = %+v", got)
}
}
func TestCandidateCacheRejectsInvalidOrDuplicateDurableProjection(t *testing.T) {
cache := NewCandidateCache()
if err := cache.Upsert(domain.Candidate{TicketID: "", PlayerID: "p", EnqueuedAt: time.Unix(1000, 0)}); err == nil {
t.Fatal("invalid candidate accepted")
}
candidate := domain.Candidate{TicketID: "ticket-a", PlayerID: "player-a", EnqueuedAt: time.Unix(1000, 0)}
if err := cache.Rebuild([]domain.Candidate{candidate, candidate}); err == nil {
t.Fatal("duplicate candidate accepted")
}
}
func TestRebuildFromQueueUsesAuthoritativeExpiryAndState(t *testing.T) {
now := time.Unix(1000, 0)
queue := domain.NewQueue()
active := domain.Candidate{TicketID: "ticket-active", PlayerID: "player-active", EnqueuedAt: now}
stale := domain.Candidate{TicketID: "ticket-stale", PlayerID: "player-stale", EnqueuedAt: now}
if _, err := queue.Create(active.PlayerID, active.TicketID, "create-active-123456", active, now); err != nil {
t.Fatal(err)
}
if _, err := queue.Create(stale.PlayerID, stale.TicketID, "create-stale-123456", stale, now); err != nil {
t.Fatal(err)
}
if _, err := queue.Cancel(stale.PlayerID, stale.TicketID, "cancel-stale-123456", 0, now); err != nil {
t.Fatal(err)
}
cache := NewCandidateCache()
if err := cache.Upsert(domain.Candidate{TicketID: "obsolete", PlayerID: "obsolete", EnqueuedAt: now}); err != nil {
t.Fatal(err)
}
if err := RebuildFromQueue(cache, queue, now); err != nil {
t.Fatal(err)
}
got := cache.Snapshot(now)
if len(got) != 1 || got[0].TicketID != active.TicketID {
t.Fatalf("authoritative rebuild = %+v", got)
}
}