@@ -941,6 +941,151 @@ func TestMatchesCron(t *testing.T) {
941
941
}
942
942
}
943
943
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
+
944
1089
func mustParseTime (t * testing.T , layout , value string ) time.Time {
945
1090
t .Helper ()
946
1091
parsedTime , err := time .Parse (layout , value )
0 commit comments