package usage import ( "encoding/json" "errors" "os" "testing" "time" ) func TestUsageCoreFixtureIsConsumedByGo(t *testing.T) { data, err := os.ReadFile("../../../contracts/usage/core-v1.json") if err != nil { t.Fatal(err) } var fixture struct { TimeZone string `json:"timeZone"` DedupeKey string `json:"dedupeKey"` Excluded struct { Sources []string `json:"sources"` Providers []string `json:"providers"` } `json:"excluded"` } if err := json.Unmarshal(data, &fixture); err != nil { t.Fatal(err) } if fixture.TimeZone != "Asia/Shanghai" || fixture.DedupeKey != "jobId" || len(fixture.Excluded.Sources) != 1 || fixture.Excluded.Sources[0] != "api" || len(fixture.Excluded.Providers) != 1 || fixture.Excluded.Providers[0] != "mock" { t.Fatalf("fixture = %#v", fixture) } } func TestPresetUsesShanghaiCalendarBoundaries(t *testing.T) { rangeValue, err := PresetRange(PresetMonth, time.Date(2026, 7, 27, 16, 30, 0, 0, time.UTC)) if err != nil { t.Fatal(err) } if rangeValue.StartDate != "2026-07-01" || rangeValue.EndDate != "2026-07-28" || rangeValue.From != "2026-07-01T00:00:00+08:00" || rangeValue.To != "2026-07-29T00:00:00+08:00" || rangeValue.DayCount != 28 { t.Fatalf("range = %#v", rangeValue) } } func TestServiceDedupesEligibleEventsAndScopesReports(t *testing.T) { repo := &memoryRepository{} service := Service{Repository: repo} for _, event := range []Event{ {ID: "1", JobID: "job-1", OwnerID: "a", Source: "platform", Provider: "bailian", OrganizationID: "org-1", AccountUsername: "secret", CreatedAt: "2026-07-03T01:00:00Z"}, {ID: "2", JobID: "job-1", OwnerID: "a", Source: "platform", Provider: "bailian", OrganizationID: "org-1", CreatedAt: "2026-07-03T01:01:00Z"}, {ID: "3", JobID: "job-api", OwnerID: "a", Source: "api", Provider: "bailian", OrganizationID: "org-1", CreatedAt: "2026-07-03T01:02:00Z"}, {ID: "4", JobID: "job-mock", OwnerID: "a", Source: "platform", Provider: "mock", OrganizationID: "org-1", CreatedAt: "2026-07-03T01:03:00Z"}, {ID: "5", JobID: "job-2", OwnerID: "b", Source: "platform", Provider: "seedance", OrganizationID: "org-2", AccountUsername: "other-secret", CreatedAt: "2026-07-03T01:04:00Z"}, } { if _, err := service.Record(event); err != nil { t.Fatal(err) } } personal, err := service.Report(Requester{AccountID: "a", Role: "user"}, Filters{}) if err != nil || len(personal) != 1 || personal[0].OwnerID != "a" { t.Fatalf("personal = %#v, %v", personal, err) } admin, err := service.Report(Requester{AccountID: "admin", OrganizationID: "org-1", Role: "organization_admin"}, Filters{}) if err != nil || len(admin) != 1 || admin[0].OrganizationID != "org-1" || admin[0].AccountUsername != "" { t.Fatalf("admin = %#v, %v", admin, err) } super, err := service.Report(Requester{AccountID: "root", Role: "super_admin"}, Filters{}) if err != nil || len(super) != 2 || super[0].AccountUsername == "" { t.Fatalf("super = %#v, %v", super, err) } } func TestOrganizationAdminCannotEscapeOrganizationScope(t *testing.T) { _, err := (Service{Repository: &memoryRepository{}}).Report(Requester{Role: "organization_admin", OrganizationID: "org-1"}, Filters{OrganizationID: "org-2"}) if !errors.Is(err, ErrForbidden) { t.Fatalf("error = %v", err) } } type memoryRepository struct{ events []Event } func (r *memoryRepository) Insert(event Event) (Event, bool, error) { for _, current := range r.events { if current.JobID == event.JobID { return current, false, nil } } r.events = append(r.events, event) return event, true, nil } func (r *memoryRepository) List(filters Filters) ([]Event, error) { return append([]Event(nil), r.events...), nil }