package processing import ( "context" "errors" "testing" "github.com/google/uuid" ) func TestChunkUUIDs(t *testing.T) { ids := make([]uuid.UUID, 12) for i := range ids { ids[i] = uuid.New() } chunks := chunkUUIDs(ids, 5) if len(chunks) != 3 { t.Fatalf("chunks=%d want 3", len(chunks)) } if len(chunks[0]) != 5 || len(chunks[1]) != 5 || len(chunks[2]) != 2 { t.Fatalf("sizes=%d,%d,%d", len(chunks[0]), len(chunks[1]), len(chunks[2])) } if chunks[0][0] != ids[0] || chunks[2][1] != ids[11] { t.Fatal("chunk order must preserve input order") } if chunkUUIDs(nil, 5) != nil { t.Fatal("nil/empty input must return nil") } one := chunkUUIDs(ids[:3], 0) if len(one) != 1 || len(one[0]) != 3 { t.Fatalf("size<=0 must keep whole slice, got %v", one) } } func TestChunkUUIDs_jobCapBoundaries(t *testing.T) { ids := make([]uuid.UUID, maxJobProducts+1) chunks := chunkUUIDs(ids, maxJobProducts) if len(chunks) != 2 { t.Fatalf("chunks=%d want 2", len(chunks)) } if len(chunks[0]) != maxJobProducts || len(chunks[1]) != 1 { t.Fatalf("sizes=%d,%d", len(chunks[0]), len(chunks[1])) } exact := chunkUUIDs(ids[:maxJobProducts], maxJobProducts) if len(exact) != 1 || len(exact[0]) != maxJobProducts { t.Fatalf("exact cap must be one chunk, got %d chunks", len(exact)) } } func TestStartJobRejectsOverMaxStartProducts(t *testing.T) { p := &Pipeline{} ids := make([]uuid.UUID, MaxStartProducts+1) _, err := p.StartJob(context.Background(), uuid.New(), uuid.New(), ids, "full") if !errors.Is(err, ErrTooManyProducts) { t.Fatalf("err=%v want ErrTooManyProducts", err) } } func TestAssertProcessingGatesNilBilling(t *testing.T) { p := &Pipeline{} if err := p.assertProcessingGates(context.Background(), uuid.New(), "enhance", 3); err != nil { t.Fatalf("nil billing must no-op: %v", err) } } func TestStartJobRejectsEmpty(t *testing.T) { p := &Pipeline{} _, err := p.StartJob(context.Background(), uuid.New(), uuid.New(), nil, "full") if !errors.Is(err, ErrRawIDsRequired) { t.Fatalf("err=%v want ErrRawIDsRequired", err) } }