feat: gamemaster
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
package cronutil_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"galaxy/cronutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParseAcceptsFiveFieldExpressions(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
accepted := []string{
|
||||
"0 18 * * *",
|
||||
"*/15 * * * *",
|
||||
"0 */6 * * *",
|
||||
"0 */4 * * *",
|
||||
"0 0 * * *",
|
||||
"0 0 1 1 *",
|
||||
"30 9 * * MON-FRI",
|
||||
}
|
||||
for _, expr := range accepted {
|
||||
t.Run(expr, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := cronutil.Parse(expr)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseRejectsInvalidExpressions(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
expr string
|
||||
}{
|
||||
{name: "empty", expr: ""},
|
||||
{name: "whitespace only", expr: " "},
|
||||
{name: "garbage", expr: "not a cron"},
|
||||
{name: "six field with seconds", expr: "*/30 * * * * *"},
|
||||
{name: "too few fields", expr: "0 18 *"},
|
||||
{name: "minute out of range", expr: "60 * * * *"},
|
||||
{name: "hour out of range", expr: "* 24 * * *"},
|
||||
{name: "month out of range", expr: "* * * 13 *"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := cronutil.Parse(tc.expr)
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduleNextComputesExpectedFire(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
schedule, err := cronutil.Parse("0 18 * * *")
|
||||
require.NoError(t, err)
|
||||
|
||||
after := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
next := schedule.Next(after)
|
||||
|
||||
assert.Equal(t, time.Date(2026, 1, 1, 18, 0, 0, 0, time.UTC), next)
|
||||
assert.Equal(t, time.UTC, next.Location())
|
||||
}
|
||||
|
||||
func TestScheduleNextStepsToNextFifteenMinuteSlot(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
schedule, err := cronutil.Parse("*/15 * * * *")
|
||||
require.NoError(t, err)
|
||||
|
||||
after := time.Date(2026, 6, 30, 12, 7, 33, 0, time.UTC)
|
||||
next := schedule.Next(after)
|
||||
|
||||
assert.Equal(t, time.Date(2026, 6, 30, 12, 15, 0, 0, time.UTC), next)
|
||||
assert.Equal(t, time.UTC, next.Location())
|
||||
}
|
||||
|
||||
func TestScheduleNextReturnsUTCForNonUTCInput(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
schedule, err := cronutil.Parse("0 18 * * *")
|
||||
require.NoError(t, err)
|
||||
|
||||
moscow, err := time.LoadLocation("Europe/Moscow")
|
||||
require.NoError(t, err)
|
||||
|
||||
after := time.Date(2026, 1, 1, 12, 0, 0, 0, moscow) // 09:00 UTC
|
||||
next := schedule.Next(after)
|
||||
|
||||
assert.Equal(t, time.Date(2026, 1, 1, 18, 0, 0, 0, time.UTC), next)
|
||||
assert.Equal(t, time.UTC, next.Location())
|
||||
}
|
||||
Reference in New Issue
Block a user