Skip to content

Commit 8b3dbe9

Browse files
authored
Add unit tests for picker plugin (#1103)
* Add unit tests for picker plugin * Fix import formatting in test * Refactor picker tests to follow table-driven format
1 parent e9e4558 commit 8b3dbe9

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package picker
18+
19+
import (
20+
"context"
21+
"testing"
22+
23+
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
24+
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/types"
25+
26+
k8stypes "k8s.io/apimachinery/pkg/types"
27+
)
28+
29+
func TestPickMaxScorePicker(t *testing.T) {
30+
tests := []struct {
31+
name string
32+
scoredPods []*types.ScoredPod
33+
wantNames []string
34+
shouldPanic bool
35+
}{
36+
{
37+
name: "Single max score",
38+
scoredPods: []*types.ScoredPod{
39+
{Pod: &types.PodMetrics{Pod: &backend.Pod{NamespacedName: k8stypes.NamespacedName{Name: "pod1"}}}, Score: 10},
40+
{Pod: &types.PodMetrics{Pod: &backend.Pod{NamespacedName: k8stypes.NamespacedName{Name: "pod2"}}}, Score: 25},
41+
{Pod: &types.PodMetrics{Pod: &backend.Pod{NamespacedName: k8stypes.NamespacedName{Name: "pod3"}}}, Score: 15},
42+
},
43+
wantNames: []string{"pod2"},
44+
},
45+
{
46+
name: "Multiple max scores",
47+
scoredPods: []*types.ScoredPod{
48+
{Pod: &types.PodMetrics{Pod: &backend.Pod{NamespacedName: k8stypes.NamespacedName{Name: "podA"}}}, Score: 50},
49+
{Pod: &types.PodMetrics{Pod: &backend.Pod{NamespacedName: k8stypes.NamespacedName{Name: "podB"}}}, Score: 50},
50+
{Pod: &types.PodMetrics{Pod: &backend.Pod{NamespacedName: k8stypes.NamespacedName{Name: "podC"}}}, Score: 30},
51+
},
52+
wantNames: []string{"podA", "podB"},
53+
},
54+
{
55+
name: "Empty pod list",
56+
scoredPods: []*types.ScoredPod{},
57+
wantNames: nil,
58+
shouldPanic: true,
59+
},
60+
}
61+
62+
for _, tt := range tests {
63+
t.Run(tt.name, func(t *testing.T) {
64+
if tt.shouldPanic {
65+
defer func() {
66+
if r := recover(); r == nil {
67+
t.Errorf("expected panic but did not get one")
68+
}
69+
}()
70+
}
71+
72+
p := NewMaxScorePicker()
73+
result := p.Pick(context.Background(), nil, tt.scoredPods)
74+
75+
if len(tt.scoredPods) == 0 && result != nil {
76+
t.Errorf("expected nil result for empty input, got %+v", result)
77+
return
78+
}
79+
80+
if result != nil {
81+
got := result.TargetPod.GetPod().NamespacedName.Name
82+
match := false
83+
for _, want := range tt.wantNames {
84+
if got == want {
85+
match = true
86+
break
87+
}
88+
}
89+
if !match {
90+
t.Errorf("got %q, want one of %v", got, tt.wantNames)
91+
}
92+
}
93+
})
94+
}
95+
}

0 commit comments

Comments
 (0)