Skip to content

Commit 1a9817b

Browse files
test: added calculate-desired-instances test
1 parent 597056a commit 1a9817b

File tree

2 files changed

+147
-2
lines changed

2 files changed

+147
-2
lines changed

coderd/prebuilds/preset_snapshot.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func MatchesCron(cronExpression string, now time.Time) (bool, error) {
9797
return sched.IsWithinRange(now), nil
9898
}
9999

100-
func (p PresetSnapshot) calculateDesiredInstances(now time.Time) (int32, error) {
100+
func (p PresetSnapshot) CalculateDesiredInstances(now time.Time) (int32, error) {
101101
if !p.Preset.AutoscalingEnabled {
102102
return p.Preset.DesiredInstances.Int32, nil
103103
}
@@ -152,7 +152,7 @@ func (p PresetSnapshot) CalculateState() *ReconciliationState {
152152

153153
if p.isActive() {
154154
var err error
155-
desired, err = p.calculateDesiredInstances(time.Now())
155+
desired, err = p.CalculateDesiredInstances(time.Now())
156156
if err != nil {
157157
// TODO: handle error
158158
}

coderd/prebuilds/preset_snapshot_test.go

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,151 @@ func TestMatchesCron(t *testing.T) {
941941
}
942942
}
943943

944+
func TestCalculateDesiredInstances(t *testing.T) {
945+
t.Parallel()
946+
947+
mkPreset := func(instances int32, timezone string) database.GetTemplatePresetsWithPrebuildsRow {
948+
return database.GetTemplatePresetsWithPrebuildsRow{
949+
DesiredInstances: sql.NullInt32{
950+
Int32: instances,
951+
Valid: true,
952+
},
953+
AutoscalingEnabled: true,
954+
AutoscalingTimezone: timezone,
955+
}
956+
}
957+
mkSchedule := func(cronExpr string, instances int32) database.TemplateVersionPresetPrebuildSchedule {
958+
return database.TemplateVersionPresetPrebuildSchedule{
959+
CronExpression: cronExpr,
960+
Instances: instances,
961+
}
962+
}
963+
mkSnapshot := func(preset database.GetTemplatePresetsWithPrebuildsRow, schedules ...database.TemplateVersionPresetPrebuildSchedule) prebuilds.PresetSnapshot {
964+
return prebuilds.PresetSnapshot{
965+
Preset: preset,
966+
PrebuildSchedules: schedules,
967+
}
968+
}
969+
970+
testCases := []struct {
971+
name string
972+
snapshot prebuilds.PresetSnapshot
973+
at time.Time
974+
expectedCalculatedInstances int32
975+
}{
976+
// "* 9-18 * * 1-5" should be interpreted as a continuous time range from 08:59:00 to 18:58:59, Monday through Friday
977+
{
978+
name: "Right before the start of the time range",
979+
snapshot: mkSnapshot(
980+
mkPreset(1, "UTC"),
981+
mkSchedule("* 9-18 * * 1-5", 3),
982+
),
983+
at: mustParseTime(t, time.RFC1123, "Mon, 02 Jun 2025 8:58:59 UTC"),
984+
expectedCalculatedInstances: 1,
985+
},
986+
{
987+
name: "Start of the time range",
988+
snapshot: mkSnapshot(
989+
mkPreset(1, "UTC"),
990+
mkSchedule("* 9-18 * * 1-5", 3),
991+
),
992+
at: mustParseTime(t, time.RFC1123, "Mon, 02 Jun 2025 8:59:00 UTC"),
993+
expectedCalculatedInstances: 3,
994+
},
995+
{
996+
name: "9AM - One minute after the start of the time range",
997+
snapshot: mkSnapshot(
998+
mkPreset(1, "UTC"),
999+
mkSchedule("* 9-18 * * 1-5", 3),
1000+
),
1001+
at: mustParseTime(t, time.RFC1123, "Mon, 02 Jun 2025 9:00:00 UTC"),
1002+
expectedCalculatedInstances: 3,
1003+
},
1004+
{
1005+
name: "2PM - The middle of the time range",
1006+
snapshot: mkSnapshot(
1007+
mkPreset(1, "UTC"),
1008+
mkSchedule("* 9-18 * * 1-5", 3),
1009+
),
1010+
at: mustParseTime(t, time.RFC1123, "Mon, 02 Jun 2025 14:00:00 UTC"),
1011+
expectedCalculatedInstances: 3,
1012+
},
1013+
{
1014+
name: "6PM - Around one hour before the end of the time range",
1015+
snapshot: mkSnapshot(
1016+
mkPreset(1, "UTC"),
1017+
mkSchedule("* 9-18 * * 1-5", 3),
1018+
),
1019+
at: mustParseTime(t, time.RFC1123, "Mon, 02 Jun 2025 18:00:00 UTC"),
1020+
expectedCalculatedInstances: 3,
1021+
},
1022+
{
1023+
name: "End of the time range",
1024+
snapshot: mkSnapshot(
1025+
mkPreset(1, "UTC"),
1026+
mkSchedule("* 9-18 * * 1-5", 3),
1027+
),
1028+
at: mustParseTime(t, time.RFC1123, "Mon, 02 Jun 2025 18:58:59 UTC"),
1029+
expectedCalculatedInstances: 3,
1030+
},
1031+
{
1032+
name: "Right after the end of the time range",
1033+
snapshot: mkSnapshot(
1034+
mkPreset(1, "UTC"),
1035+
mkSchedule("* 9-18 * * 1-5", 3),
1036+
),
1037+
at: mustParseTime(t, time.RFC1123, "Mon, 02 Jun 2025 18:59:00 UTC"),
1038+
expectedCalculatedInstances: 1,
1039+
},
1040+
{
1041+
name: "7PM - Around one minute after the end of the time range",
1042+
snapshot: mkSnapshot(
1043+
mkPreset(1, "UTC"),
1044+
mkSchedule("* 9-18 * * 1-5", 3),
1045+
),
1046+
at: mustParseTime(t, time.RFC1123, "Mon, 02 Jun 2025 19:00:00 UTC"),
1047+
expectedCalculatedInstances: 1,
1048+
},
1049+
{
1050+
name: "2AM - Significantly outside the time range",
1051+
snapshot: mkSnapshot(
1052+
mkPreset(1, "UTC"),
1053+
mkSchedule("* 9-18 * * 1-5", 3),
1054+
),
1055+
at: mustParseTime(t, time.RFC1123, "Mon, 02 Jun 2025 02:00:00 UTC"),
1056+
expectedCalculatedInstances: 1,
1057+
},
1058+
{
1059+
name: "Outside the day range #1",
1060+
snapshot: mkSnapshot(
1061+
mkPreset(1, "UTC"),
1062+
mkSchedule("* 9-18 * * 1-5", 3),
1063+
),
1064+
at: mustParseTime(t, time.RFC1123, "Sat, 07 Jun 2025 14:00:00 UTC"),
1065+
expectedCalculatedInstances: 1,
1066+
},
1067+
{
1068+
name: "Outside the day range #2",
1069+
snapshot: mkSnapshot(
1070+
mkPreset(1, "UTC"),
1071+
mkSchedule("* 9-18 * * 1-5", 3),
1072+
),
1073+
at: mustParseTime(t, time.RFC1123, "Sun, 08 Jun 2025 14:00:00 UTC"),
1074+
expectedCalculatedInstances: 1,
1075+
},
1076+
}
1077+
1078+
for _, tc := range testCases {
1079+
tc := tc
1080+
t.Run(tc.name, func(t *testing.T) {
1081+
t.Parallel()
1082+
desiredInstances, err := tc.snapshot.CalculateDesiredInstances(tc.at)
1083+
require.NoError(t, err)
1084+
require.Equal(t, tc.expectedCalculatedInstances, desiredInstances)
1085+
})
1086+
}
1087+
}
1088+
9441089
func mustParseTime(t *testing.T, layout, value string) time.Time {
9451090
t.Helper()
9461091
parsedTime, err := time.Parse(layout, value)

0 commit comments

Comments
 (0)