internal/ci/cron_test.go

e91fdfe0cc2f9bfdcf99bf1a316d219bed8e2ebf
gitbay/internal/ci/cron_test.go history · blame · raw

54 lines · 1503 bytes

 1package ci
 2
 3import (
 4	"testing"
 5	"time"
 6)
 7
 8func at(s string) time.Time {
 9	t, err := time.Parse("2006-01-02 15:04", s)
10	if err != nil {
11		panic(err)
12	}
13	return t
14}
15
16func TestCronNext(t *testing.T) {
17	cases := []struct{ expr, from, want string }{
18		{"* * * * *", "2026-08-25 10:30", "2026-08-25 10:31"},
19		{"17 11,23 * * *", "2026-08-25 10:30", "2026-08-25 11:17"},
20		{"17 11,23 * * *", "2026-08-25 11:17", "2026-08-25 23:17"},
21		{"0 6 * * 1", "2026-08-25 00:00", "2026-08-31 06:00"}, // next Monday
22		{"*/15 * * * *", "2026-08-25 10:31", "2026-08-25 10:45"},
23		{"0 0 1 * *", "2026-08-25 10:00", "2026-09-01 00:00"},
24		{"30 4 1-7 * 0", "2026-08-25 10:00", "2026-08-30 04:30"}, // dom OR dow: Sunday wins
25		{"0 12 29 2 *", "2026-03-01 00:00", "2028-02-29 12:00"},  // leap day beyond a year -> zero
26	}
27	for _, c := range cases {
28		cr, err := ParseCron(c.expr)
29		if err != nil {
30			t.Fatalf("%q: %v", c.expr, err)
31		}
32		got := cr.Next(at(c.from))
33		if c.expr == "0 12 29 2 *" {
34			if !got.IsZero() {
35				t.Errorf("%q from %s: want zero, got %s", c.expr, c.from, got)
36			}
37			continue
38		}
39		if !got.Equal(at(c.want)) {
40			t.Errorf("%q from %s: got %s, want %s", c.expr, c.from, got, c.want)
41		}
42	}
43}
44
45func TestCronParseErrors(t *testing.T) {
46	for _, expr := range []string{
47		"", "* * * *", "60 * * * *", "* 24 * * *", "* * 0 * *", "* * * 13 *",
48		"* * * * 8", "a * * * *", "*/0 * * * *", "5-2 * * * *",
49	} {
50		if _, err := ParseCron(expr); err == nil {
51			t.Errorf("%q parsed without error", expr)
52		}
53	}
54}