package creator import ( "testing" "time" ) func TestFixedScheduleUsesDueBoundary(t *testing.T) { now := time.Date(2026, 4, 1, 12, 0, 0, 0, time.UTC) last := now.Add(-time.Hour) if !IsDue(last, now, time.Hour) || IsDue(last.Add(time.Minute), now, time.Hour) { t.Fatal("schedule due check must include the exact boundary") } if got := NextFixedRun(last, now, time.Hour); !got.Equal(now.Add(time.Hour)) { t.Fatalf("next fixed run = %s", got) } if got := NextFixedRun(time.Time{}, now, time.Hour); !got.Equal(now) { t.Fatalf("first fixed run = %s", got) } } func TestMetricDuePreservesUnavailableState(t *testing.T) { now := time.Now().UTC() if MetricDue(Work{}, now) { t.Fatal("missing metric schedule is not due") } past := now.Add(-time.Minute) if !MetricDue(Work{NextMetricAt: &past}, now) { t.Fatal("past metric schedule is due") } } func TestNextMetricAtSkipsLateHistoricalPoints(t *testing.T) { published := time.Date(2026, 4, 1, 0, 0, 0, 0, time.UTC) now := published.Add(8 * time.Hour) got, reason := NextMetricAt(published, now, time.Hour, 24*time.Hour, 2, 48*time.Hour) want := published.Add(15 * time.Hour) if reason != "" || !got.Equal(want) { t.Fatalf("late metric schedule = %s, reason %q; want %s", got, reason, want) } } func TestNextMetricAtStopsAtMonitoringAge(t *testing.T) { published := time.Date(2026, 4, 1, 0, 0, 0, 0, time.UTC) if got, reason := NextMetricAt(published, published.Add(47*time.Hour), time.Hour, 24*time.Hour, 2, 48*time.Hour); !got.IsZero() || reason != "monitoring_age_reached" { t.Fatalf("expired metric schedule = %s, reason %q", got, reason) } }