Skip to content

Commit 2c32461

Browse files
committed
Updates to tests
Signed-off-by: Shmuel Kallner <[email protected]>
1 parent 1c98421 commit 2c32461

File tree

11 files changed

+146
-85
lines changed

11 files changed

+146
-85
lines changed

pkg/epp/config/loader/configloader_test.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,17 @@ import (
2121
"encoding/json"
2222
"os"
2323
"testing"
24+
"time"
2425

2526
"github.com/google/go-cmp/cmp"
2627
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2728
"k8s.io/utils/ptr"
2829

2930
configapi "sigs.k8s.io/gateway-api-inference-extension/apix/config/v1alpha1"
3031
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/config"
32+
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datalayer"
3133
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/plugins"
34+
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/saturationdetector"
3235
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework"
3336
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/multi/prefix"
3437
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/framework/plugins/picker"
@@ -97,6 +100,10 @@ func TestLoadRawConfiguration(t *testing.T) {
97100
},
98101
},
99102
},
103+
FeatureGates: configapi.FeatureGates{datalayer.FeatureGate},
104+
SaturationDetector: &configapi.SaturationDetector{
105+
MetricsStalenessThreshold: metav1.Duration{Duration: 150 * time.Millisecond},
106+
},
100107
}
101108

102109
goodConfigNoProfiles := &configapi.EndpointPickerConfig{
@@ -199,6 +206,12 @@ func TestLoadRawConfigurationWithDefaults(t *testing.T) {
199206
},
200207
},
201208
},
209+
FeatureGates: configapi.FeatureGates{datalayer.FeatureGate},
210+
SaturationDetector: &configapi.SaturationDetector{
211+
QueueDepthThreshold: saturationdetector.DefaultQueueDepthThreshold,
212+
KVCacheUtilThreshold: saturationdetector.DefaultKVCacheUtilThreshold,
213+
MetricsStalenessThreshold: metav1.Duration{Duration: 150 * time.Millisecond},
214+
},
202215
}
203216

204217
goodConfigNoProfiles := &configapi.EndpointPickerConfig{
@@ -234,6 +247,12 @@ func TestLoadRawConfigurationWithDefaults(t *testing.T) {
234247
},
235248
},
236249
},
250+
FeatureGates: configapi.FeatureGates{},
251+
SaturationDetector: &configapi.SaturationDetector{
252+
QueueDepthThreshold: saturationdetector.DefaultQueueDepthThreshold,
253+
KVCacheUtilThreshold: saturationdetector.DefaultKVCacheUtilThreshold,
254+
MetricsStalenessThreshold: metav1.Duration{Duration: saturationdetector.DefaultMetricsStalenessThreshold},
255+
},
237256
}
238257

239258
tests := []testStruct{
@@ -346,6 +365,7 @@ func checkError(t *testing.T, function string, test testStruct, err error) {
346365
}
347366

348367
func TestInstantiatePlugins(t *testing.T) {
368+
registerNeededFeatureGates()
349369
handle := utils.NewTestHandle(context.Background())
350370
_, err := LoadConfig([]byte(successConfigText), handle, logging.NewTestLogger())
351371
if err != nil {
@@ -425,8 +445,14 @@ func TestLoadConfig(t *testing.T) {
425445
configText: errorMultiProfilesUseSingleProfileHandlerText,
426446
wantErr: true,
427447
},
448+
{
449+
name: "errorUnknownFeatureGate",
450+
configText: errorUnknownFeatureGateText,
451+
wantErr: true,
452+
},
428453
}
429454

455+
registerNeededFeatureGates()
430456
registerNeededPlgugins()
431457

432458
logger := logging.NewTestLogger()
@@ -444,6 +470,10 @@ func TestLoadConfig(t *testing.T) {
444470
}
445471
}
446472

473+
func registerNeededFeatureGates() {
474+
RegisterFeatureGate(datalayer.FeatureGate)
475+
}
476+
447477
func registerNeededPlgugins() {
448478
plugins.Register(prefix.PrefixCachePluginType, prefix.PrefixCachePluginFactory)
449479
plugins.Register(picker.MaxScorePickerType, picker.MaxScorePickerFactory)
@@ -452,6 +482,64 @@ func registerNeededPlgugins() {
452482
plugins.Register(profile.SingleProfileHandlerType, profile.SingleProfileHandlerFactory)
453483
}
454484

485+
func TestNewDetector(t *testing.T) {
486+
tests := []struct {
487+
name string
488+
config *configapi.SaturationDetector
489+
expectedConfig saturationdetector.Config
490+
}{
491+
{
492+
name: "Valid config",
493+
config: &configapi.SaturationDetector{
494+
QueueDepthThreshold: 10,
495+
KVCacheUtilThreshold: 0.8,
496+
MetricsStalenessThreshold: metav1.Duration{Duration: 100 * time.Millisecond},
497+
},
498+
expectedConfig: saturationdetector.Config{
499+
QueueDepthThreshold: 10,
500+
KVCacheUtilThreshold: 0.8,
501+
MetricsStalenessThreshold: 100 * time.Millisecond,
502+
},
503+
},
504+
{
505+
name: "invalid thresholds, fallback to default",
506+
config: &configapi.SaturationDetector{
507+
QueueDepthThreshold: -1,
508+
KVCacheUtilThreshold: -5.0,
509+
MetricsStalenessThreshold: metav1.Duration{Duration: 0 * time.Second},
510+
},
511+
expectedConfig: saturationdetector.Config{
512+
QueueDepthThreshold: saturationdetector.DefaultQueueDepthThreshold,
513+
KVCacheUtilThreshold: saturationdetector.DefaultKVCacheUtilThreshold,
514+
MetricsStalenessThreshold: saturationdetector.DefaultMetricsStalenessThreshold,
515+
},
516+
},
517+
{
518+
name: "kv cache threshold above range, fallback to default",
519+
config: &configapi.SaturationDetector{
520+
QueueDepthThreshold: 10,
521+
KVCacheUtilThreshold: 1.5,
522+
MetricsStalenessThreshold: metav1.Duration{Duration: 100 * time.Millisecond},
523+
},
524+
expectedConfig: saturationdetector.Config{
525+
QueueDepthThreshold: 10,
526+
KVCacheUtilThreshold: saturationdetector.DefaultKVCacheUtilThreshold,
527+
MetricsStalenessThreshold: 100 * time.Millisecond,
528+
},
529+
},
530+
}
531+
532+
for _, test := range tests {
533+
t.Run(test.name, func(t *testing.T) {
534+
// validate configuration values are loaded from configuration struct properly, including the use of default values when provided value is invalid.
535+
sdConfig := loadSaturationDetectorConfig(test.config)
536+
if diff := cmp.Diff(test.expectedConfig, sdConfig); diff != "" {
537+
t.Errorf("Unexpected output (-want +got): %v", diff)
538+
}
539+
})
540+
}
541+
}
542+
455543
// The following multi-line string constants, cause false positive lint errors (dupword)
456544

457545
// valid configuration
@@ -479,6 +567,10 @@ schedulingProfiles:
479567
- pluginRef: test-two
480568
weight: 50
481569
- pluginRef: testPicker
570+
featureGates:
571+
- dataLayer
572+
saturationDetector:
573+
metricsStalenessThreshold: 150ms
482574
`
483575

484576
// success with missing scheduling profiles
@@ -644,6 +736,21 @@ schedulingProfiles:
644736
- pluginRef: test2
645737
`
646738

739+
// error with an unknown feature gate
740+
//
741+
//nolint:dupword
742+
const errorUnknownFeatureGateText = `
743+
apiVersion: inference.networking.x-k8s.io/v1alpha1
744+
kind: EndpointPickerConfig
745+
plugins:
746+
- name: test1
747+
type: test-one
748+
parameters:
749+
threshold: 10
750+
featureGates:
751+
- qwerty
752+
`
753+
647754
// compile-time type validation
648755
var _ framework.Filter = &test1{}
649756

@@ -783,6 +890,8 @@ schedulingProfiles:
783890
- pluginRef: prefixCacheScorer
784891
weight: 50
785892
- pluginRef: maxScorePicker
893+
featureGates:
894+
- dataLayer
786895
`
787896

788897
// valid configuration, with default weight for scorer

pkg/epp/controller/inferenceobjective_reconciler_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ func TestInferenceObjectiveReconciler(t *testing.T) {
160160
WithObjects(initObjs...).
161161
Build()
162162
pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Second)
163-
ds := datastore.NewDatastore(t.Context(), pmf, 0)
163+
ds := datastore.NewDatastore(t.Context(), 0)
164+
ds.SetEndpointFactory(pmf)
164165
for _, m := range test.objectivessInStore {
165166
ds.ObjectiveSet(m)
166167
}

pkg/epp/controller/inferencepool_reconciler_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ func TestInferencePoolReconciler(t *testing.T) {
114114
ctx := context.Background()
115115

116116
pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Second)
117-
ds := datastore.NewDatastore(ctx, pmf, 0)
117+
ds := datastore.NewDatastore(ctx, 0)
118+
ds.SetEndpointFactory(pmf)
118119
inferencePoolReconciler := &InferencePoolReconciler{Reader: fakeClient, Datastore: ds, PoolGKNN: gknn}
119120

120121
// Step 1: Inception, only ready pods matching pool1 are added to the store.
@@ -261,7 +262,8 @@ func TestXInferencePoolReconciler(t *testing.T) {
261262
ctx := context.Background()
262263

263264
pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Second)
264-
ds := datastore.NewDatastore(ctx, pmf, 0)
265+
ds := datastore.NewDatastore(ctx, 0)
266+
ds.SetEndpointFactory(pmf)
265267
inferencePoolReconciler := &InferencePoolReconciler{Reader: fakeClient, Datastore: ds, PoolGKNN: gknn}
266268

267269
// Step 1: Inception, only ready pods matching pool1 are added to the store.

pkg/epp/controller/pod_reconciler_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ func TestPodReconciler(t *testing.T) {
196196
Build()
197197

198198
// Configure the initial state of the datastore.
199-
store := datastore.NewDatastore(t.Context(), pmf, 0)
199+
store := datastore.NewDatastore(t.Context(), 0)
200+
store.SetEndpointFactory(pmf)
200201
_ = store.PoolSet(t.Context(), fakeClient, test.pool)
201202
for _, pod := range test.existingPods {
202203
store.PodUpdateOrAddIfNotExist(pod)

pkg/epp/datastore/datastore_test.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ func TestPool(t *testing.T) {
8686
WithScheme(scheme).
8787
Build()
8888
pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Second)
89-
ds := NewDatastore(context.Background(), pmf, 0)
89+
ds := NewDatastore(context.Background(), 0)
90+
ds.SetEndpointFactory(pmf)
9091
_ = ds.PoolSet(context.Background(), fakeClient, tt.inferencePool)
9192
gotPool, gotErr := ds.PoolGet()
9293
if diff := cmp.Diff(tt.wantErr, gotErr, cmpopts.EquateErrors()); diff != "" {
@@ -193,7 +194,8 @@ func TestObjective(t *testing.T) {
193194
for _, test := range tests {
194195
t.Run(test.name, func(t *testing.T) {
195196
pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Second)
196-
ds := NewDatastore(t.Context(), pmf, 0)
197+
ds := NewDatastore(t.Context(), 0)
198+
ds.SetEndpointFactory(pmf)
197199
for _, m := range test.existingModels {
198200
ds.ObjectiveSet(m)
199201
}
@@ -327,7 +329,8 @@ func TestMetrics(t *testing.T) {
327329
WithScheme(scheme).
328330
Build()
329331
pmf := backendmetrics.NewPodMetricsFactory(test.pmc, time.Millisecond)
330-
ds := NewDatastore(ctx, pmf, 0)
332+
ds := NewDatastore(ctx, 0)
333+
ds.SetEndpointFactory(pmf)
331334
_ = ds.PoolSet(ctx, fakeClient, inferencePool)
332335
for _, pod := range test.storePods {
333336
ds.PodUpdateOrAddIfNotExist(pod)
@@ -395,7 +398,8 @@ func TestPods(t *testing.T) {
395398
t.Run(test.name, func(t *testing.T) {
396399
ctx := context.Background()
397400
pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Second)
398-
ds := NewDatastore(t.Context(), pmf, 0)
401+
ds := NewDatastore(t.Context(), 0)
402+
ds.SetEndpointFactory(pmf)
399403
fakeClient := fake.NewFakeClient()
400404
if err := ds.PoolSet(ctx, fakeClient, inferencePool); err != nil {
401405
t.Error(err)
@@ -579,7 +583,8 @@ func TestPodInfo(t *testing.T) {
579583
t.Run(test.name, func(t *testing.T) {
580584
ctx := context.Background()
581585
pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Second)
582-
ds := NewDatastore(t.Context(), pmf, 0)
586+
ds := NewDatastore(t.Context(), 0)
587+
ds.SetEndpointFactory(pmf)
583588
fakeClient := fake.NewFakeClient()
584589
if err := ds.PoolSet(ctx, fakeClient, test.pool); err != nil {
585590
t.Error(err)

pkg/epp/metrics/collectors/inference_pool_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ var (
5050

5151
func TestNoMetricsCollected(t *testing.T) {
5252
pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Second)
53-
ds := datastore.NewDatastore(context.Background(), pmf, 0)
53+
ds := datastore.NewDatastore(context.Background(), 0)
54+
ds.SetEndpointFactory(pmf)
5455

5556
collector := &inferencePoolMetricsCollector{
5657
ds: ds,
@@ -68,7 +69,8 @@ func TestMetricsCollected(t *testing.T) {
6869
},
6970
}
7071
pmf := backendmetrics.NewPodMetricsFactory(pmc, time.Millisecond)
71-
ds := datastore.NewDatastore(context.Background(), pmf, 0)
72+
ds := datastore.NewDatastore(context.Background(), 0)
73+
ds.SetEndpointFactory(pmf)
7274

7375
scheme := runtime.NewScheme()
7476
fakeClient := fake.NewClientBuilder().

pkg/epp/requestcontrol/director_test.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ func TestDirector_HandleRequest(t *testing.T) {
120120

121121
// Datastore setup
122122
pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Second)
123-
ds := datastore.NewDatastore(t.Context(), pmf, 0)
123+
ds := datastore.NewDatastore(t.Context(), 0)
124+
ds.SetEndpointFactory(pmf)
124125
ds.ObjectiveSet(ioFoodReview)
125126
ds.ObjectiveSet(ioFoodReviewResolve)
126127
ds.ObjectiveSet(ioFoodReviewSheddable)
@@ -594,7 +595,8 @@ func TestGetRandomPod(t *testing.T) {
594595
for _, test := range tests {
595596
t.Run(test.name, func(t *testing.T) {
596597
pmf := backendmetrics.NewPodMetricsFactory(&backendmetrics.FakePodMetricsClient{}, time.Millisecond)
597-
ds := datastore.NewDatastore(t.Context(), pmf, 0)
598+
ds := datastore.NewDatastore(t.Context(), 0)
599+
ds.SetEndpointFactory(pmf)
598600
err := ds.PoolSet(t.Context(), fakeClient, pool)
599601
if err != nil {
600602
t.Errorf("unexpected error setting pool: %s", err)
@@ -619,7 +621,7 @@ func TestDirector_HandleResponseReceived(t *testing.T) {
619621
pr1 := newTestResponseReceived("pr1")
620622

621623
ctx := logutil.NewTestLoggerIntoContext(context.Background())
622-
ds := datastore.NewDatastore(t.Context(), nil, 0)
624+
ds := datastore.NewDatastore(t.Context(), 0)
623625
mockSched := &mockScheduler{}
624626
director := NewDirectorWithConfig(ds, mockSched, &mockAdmissionController{}, NewConfig().WithResponseReceivedPlugins(pr1))
625627

@@ -656,7 +658,7 @@ func TestDirector_HandleResponseStreaming(t *testing.T) {
656658
ps1 := newTestResponseStreaming("ps1")
657659

658660
ctx := logutil.NewTestLoggerIntoContext(context.Background())
659-
ds := datastore.NewDatastore(t.Context(), nil, 0)
661+
ds := datastore.NewDatastore(t.Context(), 0)
660662
mockSched := &mockScheduler{}
661663
director := NewDirectorWithConfig(ds, mockSched, nil, NewConfig().WithResponseStreamingPlugins(ps1))
662664

@@ -692,7 +694,7 @@ func TestDirector_HandleResponseComplete(t *testing.T) {
692694
pc1 := newTestResponseComplete("pc1")
693695

694696
ctx := logutil.NewTestLoggerIntoContext(context.Background())
695-
ds := datastore.NewDatastore(t.Context(), nil, 0)
697+
ds := datastore.NewDatastore(t.Context(), 0)
696698
mockSched := &mockScheduler{}
697699
director := NewDirectorWithConfig(ds, mockSched, nil, NewConfig().WithResponseCompletePlugins(pc1))
698700

0 commit comments

Comments
 (0)