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  }