github.com/ngicks/gokugen@v0.0.5/cron/cron_test.go (about) 1 package cron_test 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/ngicks/gokugen/cron" 8 "github.com/stretchr/testify/require" 9 ) 10 11 func TestCron(t *testing.T) { 12 t.Parallel() 13 t.Run("building cron row", func(t *testing.T) { 14 t.Parallel() 15 // Sunday 16 pseudoNow := time.Date(2022, time.April, 10, 0, 0, 0, 0, time.UTC) 17 builder := cron.Builder{}.Command([]string{"ls"}) 18 19 t.Run("weekly", func(t *testing.T) { 20 sched := builder.Weekly([]time.Weekday{time.Monday}, []uint8{11}, []uint8{23}).Build() 21 targetDate, _ := sched.NextSchedule(pseudoNow) 22 23 expected := pseudoNow.AddDate(0, 0, 1).Add(11*time.Hour + 23*time.Minute) 24 require.Equal(t, expected, targetDate) 25 }) 26 27 t.Run("yearly", func(t *testing.T) { 28 sched := builder.Yearly([]time.Month{time.January}, []uint8{23}, []uint8{2}, []uint8{15}).Build() 29 targetDate, _ := sched.NextSchedule(pseudoNow) 30 31 expected := pseudoNow.AddDate(1, -3, 13).Add(2*time.Hour + 15*time.Minute) 32 require.Equal(t, expected, targetDate) 33 }) 34 35 t.Run("monthly", func(t *testing.T) { 36 sched := builder.Monthly([]uint8{9}, []uint8{23}, []uint8{59}).Build() 37 targetDate, _ := sched.NextSchedule(pseudoNow) 38 39 expected := pseudoNow.AddDate(0, 1, -1).Add(23*time.Hour + 59*time.Minute) 40 require.Equal(t, expected, targetDate) 41 }) 42 43 t.Run("daily", func(t *testing.T) { 44 sched := builder.Daily([]uint8{3}, []uint8{15}).Build() 45 targetDate, _ := sched.NextSchedule(pseudoNow) 46 47 expected := pseudoNow.AddDate(0, 0, 0).Add(3*time.Hour + 15*time.Minute) 48 require.Equal(t, expected, targetDate) 49 }) 50 51 t.Run("hourly", func(t *testing.T) { 52 sched := builder.Hourly([]uint8{23}).Build() 53 targetDate, _ := sched.NextSchedule(pseudoNow) 54 55 expected := pseudoNow.AddDate(0, 0, 0).Add(23 * time.Minute) 56 require.Equal(t, expected, targetDate) 57 }) 58 59 t.Run("reboot", func(t *testing.T) { 60 sched := builder.Reboot().Build() 61 targetDate, _ := sched.NextSchedule(pseudoNow) 62 63 require.Equal(t, pseudoNow, targetDate) 64 }) 65 }) 66 67 t.Run("invalid range", func(t *testing.T) { 68 b := cron.Builder{}.Command([]string{"ls"}) 69 nilWork := cron.Builder{}.Yearly([]time.Month{time.April}, []uint8{1}, []uint8{1}, []uint8{1}).Build() 70 testCases := []cron.Row{ 71 nilWork, 72 b.Month(0).Build(), 73 b.Month(13).Build(), 74 b.Month(187).Build(), 75 b.Day(0).Build(), 76 b.Day(32).Build(), 77 b.Day(67).Build(), 78 b.Hour(24).Build(), 79 b.Hour(32).Build(), 80 b.Minute(60).Build(), 81 b.Minute(70).Build(), 82 } 83 for _, testCase := range testCases { 84 _, err := testCase.NextSchedule(time.Now()) 85 require.Error(t, err) 86 } 87 }) 88 89 t.Run("leap year", func(t *testing.T) { 90 c := cron.Builder{}. 91 Command([]string{"ls"}). 92 Yearly([]time.Month{time.February}, []uint8{31}, []uint8{0}, []uint8{0}). 93 Build() 94 for i := 2022; i < 2022+100; i++ { 95 target := time.Date(i, time.January, 1, 0, 0, 0, 0, time.UTC) 96 sched, _ := c.NextSchedule(target) 97 if cron.IsLeapYear(time.Date(i, 1, 1, 0, 0, 0, 0, time.UTC)) { 98 require.Equal(t, sched.Day(), 29) 99 } else { 100 require.Equal(t, sched.Day(), 28) 101 } 102 } 103 }) 104 105 t.Run("monthly: overflow of 30th and 31st", func(t *testing.T) { 106 testMonthly := func(target time.Time, row cron.Row) { 107 for i := 1; i <= 12*4; i++ { 108 added := target.AddDate(0, i, 0) 109 // fmt.Println("case:", added.Format(time.RFC3339Nano)) 110 sched, _ := row.NextSchedule(added) 111 112 var expectedDayMax int 113 switch sched.Month() { 114 // 28 | 29 115 case time.February: 116 if cron.IsLeapYear(sched) { 117 expectedDayMax = 29 118 } else { 119 expectedDayMax = 28 120 } 121 // 30 122 case time.April, time.June, time.September, time.November: 123 expectedDayMax = 30 124 // 31 125 case time.January, time.March, time.May, time.July, time.August, time.October, time.December: 126 expectedDayMax = 31 127 default: 128 t.Fatalf("unknown month: %d", sched.Month()) 129 } 130 131 var expectedDay int 132 if row.Day != nil && uint((*row.Day)[0]) < uint(expectedDayMax) { 133 expectedDay = int((*row.Day)[0]) 134 } else { 135 expectedDay = expectedDayMax 136 } 137 138 require.Equal(t, expectedDay, sched.Day()) 139 } 140 } 141 142 target := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) 143 testMonthly( 144 target, 145 cron.Builder{}.Command([]string{"ls"}).Monthly([]uint8{31}, []uint8{12}, []uint8{30}).Build(), 146 ) 147 testMonthly( 148 target, 149 cron.Builder{}.Command([]string{"ls"}).Monthly([]uint8{30}, []uint8{12}, []uint8{30}).Build(), 150 ) 151 }) 152 153 t.Run("multiple value", func(t *testing.T) { 154 b := cron.Builder{}.Command([]string{"ls"}) 155 pseudoNow := time.Date(2022, time.April, 10, 0, 0, 0, 0, time.UTC) 156 157 row := b.WeekDay(time.Saturday, time.Tuesday, time.Thursday).Hour(0).Minute(0).Build() 158 159 next := pseudoNow 160 161 next, _ = row.NextSchedule(next) 162 require.Equal(t, pseudoNow.AddDate(0, 0, 2), next) 163 next, _ = row.NextSchedule(next) 164 require.Equal(t, pseudoNow.AddDate(0, 0, 4), next) 165 next, _ = row.NextSchedule(next) 166 require.Equal(t, pseudoNow.AddDate(0, 0, 6), next) 167 168 row = b.Hour(12, 5, 7).Minute(0).Build() 169 next = pseudoNow 170 171 next, _ = row.NextSchedule(next) 172 require.Equal(t, pseudoNow.Add(5*time.Hour), next) 173 next, _ = row.NextSchedule(next) 174 require.Equal(t, pseudoNow.Add(7*time.Hour), next) 175 next, _ = row.NextSchedule(next) 176 require.Equal(t, pseudoNow.Add(12*time.Hour), next) 177 }) 178 }