@@ -22,6 +22,7 @@ import (
2222 "github.com/NVIDIA/KAI-scheduler/pkg/scheduler/api/node_info"
2323 "github.com/NVIDIA/KAI-scheduler/pkg/scheduler/api/pod_info"
2424 "github.com/NVIDIA/KAI-scheduler/pkg/scheduler/api/pod_status"
25+ "github.com/NVIDIA/KAI-scheduler/pkg/scheduler/api/podgroup_info"
2526 "github.com/NVIDIA/KAI-scheduler/pkg/scheduler/api/resource_info"
2627 "github.com/NVIDIA/KAI-scheduler/pkg/scheduler/cache"
2728 "github.com/NVIDIA/KAI-scheduler/pkg/scheduler/conf"
@@ -773,6 +774,128 @@ var _ = Describe("Set Fair Share in Proportion", func() {
773774 }
774775
775776 })
777+
778+ Context ("getVictimResources" , func () {
779+ It ("should handle case where MinAvailable is greater than number of tasks (panic fix)" , func () {
780+ plugin := & proportionPlugin {
781+ allowConsolidatingReclaim : true ,
782+ }
783+
784+ // Create a victim with only 1 task but MinAvailable = 2
785+ // This should cause a slice bounds panic without the fix
786+ victim := & api.VictimInfo {
787+ Job : & podgroup_info.PodGroupInfo {},
788+ Tasks : []* pod_info.PodInfo {
789+ {
790+ Status : pod_status .Pending ,
791+ AcceptedResource : common_info .BuildResourceRequirements ("1" , "1Gi" ),
792+ },
793+ },
794+ }
795+ victim .Job .SetDefaultMinAvailable (2 )
796+
797+ // This should not panic
798+ result := plugin .getVictimResources (victim )
799+ // Should return resources for the single task that exists
800+ Expect (len (result )).To (Equal (1 ))
801+ Expect (result [0 ]).ToNot (BeNil ())
802+ Expect (result [0 ].Cpu ()).To (Equal (1000.0 ))
803+ })
804+
805+ It ("should correctly split elastic and core tasks when MinAvailable is less than task count" , func () {
806+ plugin := & proportionPlugin {
807+ allowConsolidatingReclaim : true ,
808+ }
809+
810+ // Create a victim with 3 tasks but MinAvailable = 1
811+ victim := & api.VictimInfo {
812+ Job : & podgroup_info.PodGroupInfo {},
813+ Tasks : []* pod_info.PodInfo {
814+ {
815+ Status : pod_status .Pending ,
816+ AcceptedResource : common_info .BuildResourceRequirements ("1" , "1Gi" ),
817+ },
818+ {
819+ Status : pod_status .Pending ,
820+ AcceptedResource : common_info .BuildResourceRequirements ("1" , "1Gi" ),
821+ },
822+ {
823+ Status : pod_status .Pending ,
824+ AcceptedResource : common_info .BuildResourceRequirements ("1" , "1Gi" ),
825+ },
826+ },
827+ }
828+ victim .Job .SetDefaultMinAvailable (1 )
829+
830+ result := plugin .getVictimResources (victim )
831+
832+ // Should return 3 resources: 2 elastic tasks + 1 core task group
833+ Expect (len (result )).To (Equal (3 ))
834+ for _ , res := range result {
835+ Expect (res ).ToNot (BeNil ())
836+ Expect (res .Cpu ()).To (Equal (1000.0 ))
837+ }
838+ })
839+
840+ It ("should handle case where MinAvailable equals task count" , func () {
841+ plugin := & proportionPlugin {
842+ allowConsolidatingReclaim : true ,
843+ }
844+
845+ // Create a victim with 2 tasks and MinAvailable = 2
846+ victim := & api.VictimInfo {
847+ Job : & podgroup_info.PodGroupInfo {},
848+ Tasks : []* pod_info.PodInfo {
849+ {
850+ Status : pod_status .Pending ,
851+ AcceptedResource : common_info .BuildResourceRequirements ("1" , "1Gi" ),
852+ },
853+ {
854+ Status : pod_status .Pending ,
855+ AcceptedResource : common_info .BuildResourceRequirements ("1" , "1Gi" ),
856+ },
857+ },
858+ }
859+ victim .Job .SetDefaultMinAvailable (2 )
860+
861+ result := plugin .getVictimResources (victim )
862+
863+ // Should return 1 resource for all core tasks (no elastic tasks)
864+ Expect (len (result )).To (Equal (1 ))
865+ Expect (result [0 ]).ToNot (BeNil ())
866+ Expect (result [0 ].Cpu ()).To (Equal (2000.0 )) // Combined resources
867+ })
868+
869+ It ("should handle zero MinAvailable" , func () {
870+ plugin := & proportionPlugin {
871+ allowConsolidatingReclaim : true ,
872+ }
873+
874+ victim := & api.VictimInfo {
875+ Job : & podgroup_info.PodGroupInfo {},
876+ Tasks : []* pod_info.PodInfo {
877+ {
878+ Status : pod_status .Pending ,
879+ AcceptedResource : common_info .BuildResourceRequirements ("1" , "1Gi" ),
880+ },
881+ {
882+ Status : pod_status .Pending ,
883+ AcceptedResource : common_info .BuildResourceRequirements ("1" , "1Gi" ),
884+ },
885+ },
886+ }
887+ victim .Job .SetDefaultMinAvailable (0 )
888+
889+ result := plugin .getVictimResources (victim )
890+
891+ // Should return 2 resources (each task individually as elastic)
892+ Expect (len (result )).To (Equal (2 ))
893+ for _ , res := range result {
894+ Expect (res ).ToNot (BeNil ())
895+ Expect (res .Cpu ()).To (Equal (1000.0 ))
896+ }
897+ })
898+ })
776899})
777900
778901var _ = Describe ("New" , func () {
0 commit comments