package scheduler import ( "testing" "time" ) func TestCronMatchesAndNext(t *testing.T) { expr, err := Parse("*/15 2 * * 1-5") if err != nil { t.Fatal(err) } monday := time.Date(2026, 6, 15, 2, 30, 0, 0, time.UTC) if !expr.Matches(monday) { t.Fatal("expected expression to match") } next := expr.Next(time.Date(2026, 6, 15, 2, 31, 0, 0, time.UTC)) want := time.Date(2026, 6, 15, 2, 45, 0, 0, time.UTC) if !next.Equal(want) { t.Fatalf("next = %v, want %v", next, want) } } func TestCronRejectsInvalid(t *testing.T) { for _, value := range []string{"", "* * * *", "61 * * * *", "*/0 * * * *"} { if _, err := Parse(value); err == nil { t.Fatalf("accepted invalid cron %q", value) } } } func TestPreviousWithinCatchUpWindow(t *testing.T) { expr, err := Parse("0 2 * * *") if err != nil { t.Fatal(err) } now := time.Date(2026, 6, 13, 8, 30, 0, 0, time.UTC) want := time.Date(2026, 6, 13, 2, 0, 0, 0, time.UTC) if got := previous(expr, now, 24*time.Hour); !got.Equal(want) { t.Fatalf("previous = %v, want %v", got, want) } if got := previous(expr, now, 2*time.Hour); !got.IsZero() { t.Fatalf("unexpected catch-up match %v", got) } } func TestCronUsesOrForRestrictedMonthDayAndWeekday(t *testing.T) { expr, err := Parse("0 2 1 * 1") if err != nil { t.Fatal(err) } if !expr.Matches(time.Date(2026, 6, 8, 2, 0, 0, 0, time.UTC)) { t.Fatal("restricted day-of-month and weekday were treated as AND") } }