//go:build load package matcher import ( "context" "fmt" "sort" "sync" "sync/atomic" "testing" "time" "github.com/cosmic-clash/cosmic-clash/server/domain" ) // TestProposalFormationLoad is the local matcher-throughput portion of ยง8.51. // It drives the real Worker and domain formation code; durable PostgreSQL // proposal throughput and cross-replica fencing remain integration gates. func TestProposalFormationLoad(t *testing.T) { const proposals = 100 now := time.Unix(1_000_000, 0).UTC() var created atomic.Int64 ids := make(chan string, proposals) var wg sync.WaitGroup started := make(chan struct{}) for i := 0; i < proposals; i++ { workerIndex := i wg.Add(1) go func() { defer wg.Done() worker := Worker{ Playlist: domain.Casual, Size: 6, Now: func() time.Time { return now }, NextID: func() string { return fmt.Sprintf("load-proposal-%04d-123456", workerIndex) }, Source: func(context.Context, time.Time, domain.Playlist, int) ([]domain.Candidate, error) { candidates := make([]domain.Candidate, 6) for slot := range candidates { candidates[slot] = domain.Candidate{ PlayerID: fmt.Sprintf("load-player-%04d-%d", workerIndex, slot), TicketID: fmt.Sprintf("load-ticket-%04d-%d", workerIndex, slot), Playlist: domain.Casual, ClientBuild: "build-1", ProtocolVersion: 1, EnqueuedAt: now, PredictedRTT: map[string]float64{"EU": 20}, } } return candidates, nil }, Prepare: func(id string, playlist domain.Playlist, formation domain.MatchFormation, at time.Time) (domain.PreparedProposal, error) { return domain.PrepareProposal(id, playlist, formation, nil, domain.RankedArena{}, at) }, Creator: ProposalCreatorFunc(func(_ context.Context, proposal domain.Proposal, _ map[string]string, _ time.Time) error { created.Add(1) ids <- proposal.ProposalID return nil }), } <-started if formed, err := worker.RunOnce(context.Background()); err != nil || !formed { t.Errorf("worker %d formed=%v err=%v", workerIndex, formed, err) } }() } startedAt := time.Now() close(started) wg.Wait() close(ids) if created.Load() != proposals { t.Fatalf("created=%d, want %d", created.Load(), proposals) } ordered := make([]string, 0, proposals) for id := range ids { ordered = append(ordered, id) } sort.Strings(ordered) for i, id := range ordered { want := fmt.Sprintf("load-proposal-%04d-123456", i) if id != want { t.Fatalf("proposal %d = %q, want unique %q", i, id, want) } } t.Logf("proposal formation load: proposals=%d elapsed=%s rate=%.1f/s", proposals, time.Since(startedAt), float64(proposals)/time.Since(startedAt).Seconds()) }