package orbit import ( "context" "encoding/json" "net/http" "net/http/httptest" "sync/atomic" "testing" "time" ) func TestTaskSourceValidationAndPrecision(t *testing.T) { const task = "11111111111111111111111111111111" const parent = "22222222222222222222222222222222" const occurrence = "33333333333333333333333333333333" at := time.Date(2026, 9, 17, 0, 0, 0, 123456000, time.UTC) until := at.Add(time.Minute) var reply atomic.Value var calls atomic.Int32 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { calls.Add(1) if r.Method != "GET" || r.URL.Path != "/v1/tasks/"+task+"/source" || r.Header.Get("Authorization") != "Bearer example-token" || r.Header.Get("Idempotency-Key") != "" { t.Error("invalid source request") } json.NewEncoder(w).Encode(map[string]any{"request_id": task, "data": reply.Load()}) })) defer server.Close() client, _ := NewClient(server.URL, Options{Token: "example-token"}) p := parent valid := []TaskSource{{TaskID: task, Kind: "DIRECT"}, {TaskID: task, Kind: "MANUAL_RETRY", RetryOf: &p}, {TaskID: task, Kind: "SCHEDULE", Schedule: &TaskScheduleSource{ScheduleID: parent, ScheduleVersion: 9007199254740993, OccurrenceID: occurrence, ScheduledAt: at, Decision: "FIRED"}}, {TaskID: task, Kind: "SCHEDULE", Schedule: &TaskScheduleSource{ScheduleID: parent, ScheduleVersion: 1, OccurrenceID: occurrence, ScheduledAt: at, Decision: "COALESCED", CoveredUntil: &until}}} for _, v := range valid { reply.Store(v) out, err := client.GetTaskSource(context.Background(), task) if err != nil { t.Fatal(err) } if v.Schedule != nil && out.Schedule.ScheduleVersion != v.Schedule.ScheduleVersion { t.Fatal("version precision lost") } } self := task invalid := []TaskSource{{TaskID: parent, Kind: "DIRECT"}, {TaskID: task, Kind: "unknown"}, {TaskID: task, Kind: "DIRECT", RetryOf: &p}, {TaskID: task, Kind: "MANUAL_RETRY"}, {TaskID: task, Kind: "MANUAL_RETRY", RetryOf: &self}, {TaskID: task, Kind: "SCHEDULE"}} for _, change := range []func(*TaskScheduleSource){func(v *TaskScheduleSource) { v.ScheduleVersion = 0 }, func(v *TaskScheduleSource) { v.Decision = "SKIPPED" }, func(v *TaskScheduleSource) { v.Decision = "COALESCED" }, func(v *TaskScheduleSource) { v.CoveredUntil = &until }, func(v *TaskScheduleSource) { v.ScheduledAt = time.Time{} }, func(v *TaskScheduleSource) { v.OccurrenceID = "invalid" }} { v := valid[2] s := *v.Schedule change(&s) v.Schedule = &s invalid = append(invalid, v) } for _, v := range invalid { reply.Store(v) if _, err := client.GetTaskSource(context.Background(), task); err == nil { t.Fatal("invalid source accepted", v) } } before := calls.Load() if _, err := client.GetTaskSource(context.Background(), "../tasks"); err == nil || calls.Load() != before { t.Fatal("unsafe source path sent") } }