@@ -37,6 +37,7 @@ import (
3737 "sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
3838 "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend"
3939 backendmetrics "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/backend/metrics"
40+ "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datalayer"
4041 "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/datastore"
4142 "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/handlers"
4243 "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/metadata"
@@ -48,6 +49,10 @@ import (
4849 testutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/testing"
4950)
5051
52+ const (
53+ mockProducedDataKey = "producedDataKey"
54+ )
55+
5156// --- Mocks ---
5257
5358type mockAdmissionController struct {
@@ -66,9 +71,16 @@ func (m *mockAdmissionController) Admit(
6671type mockScheduler struct {
6772 scheduleResults * schedulingtypes.SchedulingResult
6873 scheduleErr error
74+ dataProduced bool // denotes whether data production is expected.
6975}
7076
71- func (m * mockScheduler ) Schedule (_ context.Context , _ * schedulingtypes.LLMRequest , _ []schedulingtypes.Pod ) (* schedulingtypes.SchedulingResult , error ) {
77+ func (m * mockScheduler ) Schedule (_ context.Context , _ * schedulingtypes.LLMRequest , pods []schedulingtypes.Pod ) (* schedulingtypes.SchedulingResult , error ) {
78+ if pods != nil && m .dataProduced {
79+ data , ok := pods [0 ].Get (mockProducedDataKey )
80+ if ! ok || data .(mockProducedDataType ).value != 42 {
81+ return nil , fmt .Errorf ("expected produced data not found in pod" )
82+ }
83+ }
7284 return m .scheduleResults , m .scheduleErr
7385}
7486
@@ -94,11 +106,10 @@ func (ds *mockDatastore) PodList(predicate func(backendmetrics.PodMetrics) bool)
94106}
95107
96108type mockDataProducerPlugin struct {
97- tn plugins.TypedName
98- prepareRequestDataCalled bool
109+ tn plugins.TypedName
99110}
100111
101- func newmockDataProducerPlugin (name string ) * mockDataProducerPlugin {
112+ func newMockDataProducerPlugin (name string ) * mockDataProducerPlugin {
102113 return & mockDataProducerPlugin {
103114 tn : plugins.TypedName {Type : "mock-prepare-request-data" , Name : name },
104115 }
@@ -109,33 +120,44 @@ func (m *mockDataProducerPlugin) TypedName() plugins.TypedName {
109120}
110121
111122func (m * mockDataProducerPlugin ) Produces () map [string ]any {
112- return map [string ]any {}
123+ // Produces data of type int, 0 denotes it is int.
124+ return map [string ]any {mockProducedDataKey : 0 }
113125}
114126
115127func (m * mockDataProducerPlugin ) PrepareRequestData (ctx context.Context , request * schedulingtypes.LLMRequest , pods []schedulingtypes.Pod ) {
116- m . prepareRequestDataCalled = true
128+ pods [ 0 ]. Put ( mockProducedDataKey , mockProducedDataType { value : 42 })
117129}
118130
119- type mockAdmitRequestPlugins struct {
120- tn plugins.TypedName
131+ type mockAdmitRequestPlugin struct {
132+ tn plugins.TypedName
133+ // TODO: Replace this will admission control.
121134 admitRequestCalled bool
122135}
123136
124- func newmockAdmitRequestPlugins (name string ) * mockAdmitRequestPlugins {
125- return & mockAdmitRequestPlugins {
137+ func newmockAdmitRequestPlugin (name string ) * mockAdmitRequestPlugin {
138+ return & mockAdmitRequestPlugin {
126139 tn : plugins.TypedName {Type : "mock-admit-data" , Name : name },
127140 }
128141}
129142
130- func (m * mockAdmitRequestPlugins ) TypedName () plugins.TypedName {
143+ func (m * mockAdmitRequestPlugin ) TypedName () plugins.TypedName {
131144 return m .tn
132145}
133146
134- func (m * mockAdmitRequestPlugins ) AdmitRequest (ctx context.Context , request * schedulingtypes.LLMRequest , pods []schedulingtypes.Pod ) error {
147+ func (m * mockAdmitRequestPlugin ) AdmitRequest (ctx context.Context , request * schedulingtypes.LLMRequest , pods []schedulingtypes.Pod ) error {
135148 m .admitRequestCalled = true
136149 return nil
137150}
138151
152+ type mockProducedDataType struct {
153+ value int
154+ }
155+
156+ // Clone implements types.Cloneable.
157+ func (m mockProducedDataType ) Clone () datalayer.Cloneable {
158+ return mockProducedDataType {value : m .value }
159+ }
160+
139161func TestDirector_HandleRequest (t * testing.T ) {
140162 ctx := logutil .NewTestLoggerIntoContext (context .Background ())
141163
@@ -210,6 +232,7 @@ func TestDirector_HandleRequest(t *testing.T) {
210232 TargetPods : []schedulingtypes.Pod {
211233 & schedulingtypes.ScoredPod {
212234 Pod : & schedulingtypes.PodMetrics {
235+ AttributeMap : datalayer .NewAttributes (),
213236 Pod : & backend.Pod {
214237 Address : "192.168.1.100" ,
215238 Port : "8000" ,
@@ -220,6 +243,7 @@ func TestDirector_HandleRequest(t *testing.T) {
220243 },
221244 & schedulingtypes.ScoredPod {
222245 Pod : & schedulingtypes.PodMetrics {
246+ AttributeMap : datalayer .NewAttributes (),
223247 Pod : & backend.Pod {
224248 Address : "192.168.2.100" ,
225249 Port : "8000" ,
@@ -230,6 +254,7 @@ func TestDirector_HandleRequest(t *testing.T) {
230254 },
231255 & schedulingtypes.ScoredPod {
232256 Pod : & schedulingtypes.PodMetrics {
257+ AttributeMap : datalayer .NewAttributes (),
233258 Pod : & backend.Pod {
234259 Address : "192.168.4.100" ,
235260 Port : "8000" ,
@@ -245,19 +270,18 @@ func TestDirector_HandleRequest(t *testing.T) {
245270 }
246271
247272 tests := []struct {
248- name string
249- reqBodyMap map [string ]any
250- mockAdmissionController * mockAdmissionController
251- inferenceObjectiveName string
252- schedulerMockSetup func (m * mockScheduler )
253- wantErrCode string // Expected errutil code string
254- wantReqCtx * handlers.RequestContext // Fields to check in the returned RequestContext
255- wantMutatedBodyModel string // Expected model in reqCtx.Request.Body after PostDispatch
256- targetModelName string // Expected model name after target model resolution
257- prepareRequestDataCalled bool
258- admitRequestCalled bool
259- dataProducerPlugins * mockDataProducerPlugin
260- admitRequestPlugins * mockAdmitRequestPlugins
273+ name string
274+ reqBodyMap map [string ]any
275+ mockAdmissionController * mockAdmissionController
276+ inferenceObjectiveName string
277+ schedulerMockSetup func (m * mockScheduler )
278+ wantErrCode string // Expected errutil code string
279+ wantReqCtx * handlers.RequestContext // Fields to check in the returned RequestContext
280+ wantMutatedBodyModel string // Expected model in reqCtx.Request.Body after PostDispatch
281+ targetModelName string // Expected model name after target model resolution
282+ admitRequestCalled bool
283+ dataProducerPlugin * mockDataProducerPlugin
284+ admitRequestPlugin * mockAdmitRequestPlugin
261285 }{
262286 {
263287 name : "successful completions request" ,
@@ -326,6 +350,7 @@ func TestDirector_HandleRequest(t *testing.T) {
326350 mockAdmissionController : & mockAdmissionController {admitErr : nil },
327351 schedulerMockSetup : func (m * mockScheduler ) {
328352 m .scheduleResults = defaultSuccessfulScheduleResults
353+ m .dataProduced = true
329354 },
330355 wantReqCtx : & handlers.RequestContext {
331356 TargetModelName : model ,
@@ -337,10 +362,9 @@ func TestDirector_HandleRequest(t *testing.T) {
337362 },
338363 TargetEndpoint : "192.168.1.100:8000,192.168.2.100:8000,192.168.4.100:8000" ,
339364 },
340- wantMutatedBodyModel : model ,
341- targetModelName : model ,
342- prepareRequestDataCalled : true ,
343- dataProducerPlugins : newmockDataProducerPlugin ("test-plugin" ),
365+ wantMutatedBodyModel : model ,
366+ targetModelName : model ,
367+ dataProducerPlugin : newMockDataProducerPlugin ("test-plugin" ),
344368 },
345369 {
346370 name : "successful chat completions request with admit request plugins" ,
@@ -370,7 +394,7 @@ func TestDirector_HandleRequest(t *testing.T) {
370394 wantMutatedBodyModel : model ,
371395 targetModelName : model ,
372396 admitRequestCalled : true ,
373- admitRequestPlugins : newmockAdmitRequestPlugins ("test-plugin" ),
397+ admitRequestPlugin : newmockAdmitRequestPlugin ("test-plugin" ),
374398 },
375399 {
376400 name : "successful chat completions request with multiple messages" ,
@@ -522,11 +546,11 @@ func TestDirector_HandleRequest(t *testing.T) {
522546 test .schedulerMockSetup (mockSched )
523547 }
524548 config := NewConfig ()
525- if test .dataProducerPlugins != nil {
526- config = config .WithDataProducers (test .dataProducerPlugins )
549+ if test .dataProducerPlugin != nil {
550+ config = config .WithDataProducers (test .dataProducerPlugin )
527551 }
528- if test .admitRequestPlugins != nil {
529- config = config .WithAdmitRequestPlugins (test .admitRequestPlugins )
552+ if test .admitRequestPlugin != nil {
553+ config = config .WithAdmitRequestPlugins (test .admitRequestPlugin )
530554 }
531555 director := NewDirectorWithConfig (ds , mockSched , test .mockAdmissionController , config )
532556
@@ -572,11 +596,12 @@ func TestDirector_HandleRequest(t *testing.T) {
572596 assert .Equal (t , test .wantMutatedBodyModel , returnedReqCtx .Request .Body ["model" ],
573597 "Mutated reqCtx.Request.Body model mismatch" )
574598 }
575- if test .admitRequestPlugins != nil {
576- assert .True (t , test .admitRequestPlugins .admitRequestCalled , "AdmitRequest not called" )
599+ if test .admitRequestPlugin != nil {
600+ assert .True (t , test .admitRequestPlugin .admitRequestCalled , "AdmitRequest not called" )
577601 }
578- if test .dataProducerPlugins != nil {
579- assert .True (t , test .dataProducerPlugins .prepareRequestDataCalled , "PrepareRequestData not called" )
602+ if test .dataProducerPlugin != nil && mockSched .dataProduced {
603+ // TODO: Test if the AttributeMap in pod got updated correctly.
604+
580605 }
581606 })
582607 }
0 commit comments