package controllogic import ( "testing" "time" ) func mustSched(t *testing.T, spec string) *Schedule { t.Helper() s, err := ParseSchedule(spec) if err != nil { t.Fatalf("ParseSchedule(%q): %v", spec, err) } return s } func TestCronEveryMinute(t *testing.T) { s := mustSched(t, "* * * * *") if !s.Match(time.Date(2026, 6, 18, 12, 34, 0, 0, time.UTC)) { t.Error("* * * * * should match any time") } } func TestCronSpecificTime(t *testing.T) { s := mustSched(t, "30 9 * * *") if !s.Match(time.Date(2026, 6, 18, 9, 30, 0, 0, time.UTC)) { t.Error("should match 09:30") } if s.Match(time.Date(2026, 6, 18, 9, 31, 0, 0, time.UTC)) { t.Error("should not match 09:31") } } func TestCronStep(t *testing.T) { s := mustSched(t, "*/15 * * * *") for _, m := range []int{0, 15, 30, 45} { if !s.Match(time.Date(2026, 6, 18, 1, m, 0, 0, time.UTC)) { t.Errorf("*/15 should match minute %d", m) } } if s.Match(time.Date(2026, 6, 18, 1, 7, 0, 0, time.UTC)) { t.Error("*/15 should not match minute 7") } } func TestCronRangeAndList(t *testing.T) { s := mustSched(t, "0 9-17 * * 1,2,3,4,5") // 2026-06-18 is a Thursday (weekday 4). if !s.Match(time.Date(2026, 6, 18, 10, 0, 0, 0, time.UTC)) { t.Error("should match Thursday 10:00") } if s.Match(time.Date(2026, 6, 18, 18, 0, 0, 0, time.UTC)) { t.Error("should not match 18:00 (out of 9-17)") } // 2026-06-20 is a Saturday (weekday 6). if s.Match(time.Date(2026, 6, 20, 10, 0, 0, 0, time.UTC)) { t.Error("should not match Saturday") } } func TestCronDOWSunday7(t *testing.T) { s := mustSched(t, "0 0 * * 7") // 2026-06-21 is a Sunday. if !s.Match(time.Date(2026, 6, 21, 0, 0, 0, 0, time.UTC)) { t.Error("7 should mean Sunday") } } func TestCronDomOrDow(t *testing.T) { // When both day fields restricted, match either (Vixie semantics). s := mustSched(t, "0 0 1 * 5") // 2026-06-01 is a Monday — matches via day-of-month=1. if !s.Match(time.Date(2026, 6, 1, 0, 0, 0, 0, time.UTC)) { t.Error("should match day-of-month 1") } // 2026-06-19 is a Friday (weekday 5) — matches via day-of-week. if !s.Match(time.Date(2026, 6, 19, 0, 0, 0, 0, time.UTC)) { t.Error("should match Friday") } // 2026-06-18 Thursday, not the 1st — no match. if s.Match(time.Date(2026, 6, 18, 0, 0, 0, 0, time.UTC)) { t.Error("should not match Thursday the 18th") } } func TestCronInvalid(t *testing.T) { for _, bad := range []string{"* * * *", "60 * * * *", "* 24 * * *", "* * 0 * *", "a * * * *", "*/0 * * * *"} { if _, err := ParseSchedule(bad); err == nil { t.Errorf("ParseSchedule(%q) should error", bad) } } }