@@ -65,10 +65,14 @@ var (
6565// --- Mocks ---
6666
6767type mockAdmissionController struct {
68- admitErr error
68+ admitErr error
69+ admitCallback func (request * fwksched.InferenceRequest )
6970}
7071
71- func (m * mockAdmissionController ) Admit (context.Context , * handlers.RequestContext , int ) error {
72+ func (m * mockAdmissionController ) Admit (ctx context.Context , reqCtx * handlers.RequestContext , priority int ) error {
73+ if m .admitCallback != nil {
74+ m .admitCallback (reqCtx .SchedulingRequest )
75+ }
7276 return m .admitErr
7377}
7478
@@ -141,6 +145,27 @@ func newMockDataProducerPlugin(name string) *mockDataProducerPlugin {
141145 }
142146}
143147
148+ type mockDataProducer struct {
149+ name string
150+ produces map [fwkplugin.DataKey ]any
151+ produceCallback func (ctx context.Context , request * fwksched.InferenceRequest , endpoints []fwksched.Endpoint ) error
152+ }
153+
154+ func (m * mockDataProducer ) TypedName () fwkplugin.TypedName {
155+ return fwkplugin.TypedName {Type : "mock-data-producer" , Name : m .name }
156+ }
157+
158+ func (m * mockDataProducer ) Produces () map [fwkplugin.DataKey ]any {
159+ return m .produces
160+ }
161+
162+ func (m * mockDataProducer ) Produce (ctx context.Context , request * fwksched.InferenceRequest , endpoints []fwksched.Endpoint ) error {
163+ if m .produceCallback != nil {
164+ return m .produceCallback (ctx , request , endpoints )
165+ }
166+ return nil
167+ }
168+
144169type mockAdmissionPlugin struct {
145170 typedName fwkplugin.TypedName
146171 denialError error
@@ -328,7 +353,10 @@ func TestDirector_HandleRequest(t *testing.T) {
328353 preRequestPlugin * mockPreRequestPlugin
329354 wantMutatedBody map [string ]any
330355 fairnessIDHeader string // If non-empty, set as metadata.FlowFairnessIDKey on the incoming request.
356+ preAdmissionProducers []fwkrc.DataProducer
357+ postAdmissionProducers []fwkrc.DataProducer
331358 wantFairnessID string // If non-empty, asserted against returnedReqCtx.SchedulingRequest.FairnessID.
359+ checkFn func (t * testing.T , reqCtx * handlers.RequestContext )
332360 }{
333361 {
334362 name : "successful completions request" ,
@@ -734,6 +762,86 @@ func TestDirector_HandleRequest(t *testing.T) {
734762 wantErrCode : errcommon .Internal ,
735763 inferenceObjectiveName : objectiveName ,
736764 },
765+ {
766+ name : "pre-admission data producer failure aborts request" ,
767+ reqBodyMap : map [string ]any {
768+ "model" : model ,
769+ "prompt" : "prompt with failed pre-producer" ,
770+ },
771+ mockAdmissionController : & mockAdmissionController {admitErr : nil },
772+ inferenceObjectiveName : objectiveName ,
773+ preAdmissionProducers : []fwkrc.DataProducer {
774+ & mockDataProducer {
775+ name : "failed-pre-producer" ,
776+ produceCallback : func (ctx context.Context , request * fwksched.InferenceRequest , endpoints []fwksched.Endpoint ) error {
777+ return errcommon.Error {
778+ Code : errcommon .Internal ,
779+ Msg : "simulated pre-admission data producer error" ,
780+ }
781+ },
782+ },
783+ },
784+ wantErrCode : errcommon .Internal ,
785+ },
786+ {
787+ name : "attributes wrapped in read-only container during queue blocking" ,
788+ reqBodyMap : map [string ]any {
789+ "model" : model ,
790+ "prompt" : "prompt for queue blocking safety" ,
791+ },
792+ mockAdmissionController : & mockAdmissionController {
793+ admitErr : nil ,
794+ admitCallback : func (req * fwksched.InferenceRequest ) {
795+ assert .PanicsWithValue (t , "cannot write to ReadOnlyAttributes" , func () {
796+ req .Attributes .Put ("illegal_key" , "illegal_value" )
797+ })
798+ val , ok := req .Attributes .Get ("pre_key" )
799+ assert .True (t , ok )
800+ assert .Equal (t , "pre_val" , val )
801+ },
802+ },
803+ schedulerMockSetup : func (m * mockScheduler ) {
804+ m .scheduleResults = defaultSuccessfulScheduleResults
805+ },
806+ inferenceObjectiveName : objectiveName ,
807+ preAdmissionProducers : []fwkrc.DataProducer {
808+ & mockDataProducer {
809+ name : "pre-producer" ,
810+ produces : map [fwkplugin.DataKey ]any {fwkplugin .NewDataKey ("pre_key" , "pre-producer" ): nil },
811+ produceCallback : func (ctx context.Context , request * fwksched.InferenceRequest , endpoints []fwksched.Endpoint ) error {
812+ request .Attributes .Put ("pre_key" , "pre_val" )
813+ return nil
814+ },
815+ },
816+ },
817+ postAdmissionProducers : []fwkrc.DataProducer {
818+ & mockDataProducer {
819+ name : "post-producer" ,
820+ produces : map [fwkplugin.DataKey ]any {fwkplugin .NewDataKey ("post_key" , "post-producer" ): nil },
821+ produceCallback : func (ctx context.Context , request * fwksched.InferenceRequest , endpoints []fwksched.Endpoint ) error {
822+ request .Attributes .Put ("post_key" , "post_val" )
823+ return nil
824+ },
825+ },
826+ },
827+ checkFn : func (t * testing.T , returnedReqCtx * handlers.RequestContext ) {
828+ require .NotNil (t , returnedReqCtx .SchedulingRequest )
829+ assert .NotPanics (t , func () {
830+ returnedReqCtx .SchedulingRequest .Attributes .Put ("writable_now" , "success" )
831+ })
832+ v1 , ok := returnedReqCtx .SchedulingRequest .Attributes .Get ("pre_key" )
833+ assert .True (t , ok )
834+ assert .Equal (t , "pre_val" , v1 )
835+
836+ v2 , ok := returnedReqCtx .SchedulingRequest .Attributes .Get ("post_key" )
837+ assert .True (t , ok )
838+ assert .Equal (t , "post_val" , v2 )
839+
840+ v3 , ok := returnedReqCtx .SchedulingRequest .Attributes .Get ("writable_now" )
841+ assert .True (t , ok )
842+ assert .Equal (t , "success" , v3 )
843+ },
844+ },
737845 }
738846
739847 period := time .Second
@@ -781,6 +889,12 @@ func TestDirector_HandleRequest(t *testing.T) {
781889 test .schedulerMockSetup (mockSched )
782890 }
783891 config := NewConfig ()
892+ if len (test .preAdmissionProducers ) > 0 {
893+ config = config .WithPreAdmissionDataProducers (test .preAdmissionProducers ... )
894+ }
895+ if len (test .postAdmissionProducers ) > 0 {
896+ config = config .WithPostAdmissionDataProducers (test .postAdmissionProducers ... )
897+ }
784898 if test .dataProducerPlugin != nil {
785899 config = config .WithDataProducerPlugins (test .dataProducerPlugin )
786900 }
@@ -870,6 +984,9 @@ func TestDirector_HandleRequest(t *testing.T) {
870984 t .Errorf ("reqCtx.Request.RawBody mismatch (-want +got):\n %s" , diff )
871985 }
872986 }
987+ if test .checkFn != nil {
988+ test .checkFn (t , returnedReqCtx )
989+ }
873990 assert .Equal (t , len (reqCtx .Request .RawBody ), reqCtx .RequestSize )
874991 })
875992 }
@@ -1448,7 +1565,7 @@ type testResponseStreaming struct {
14481565 respsOnStreaming []* fwkrc.Response
14491566 targetPodsOnStreaming []string
14501567
1451- // Legacy fields for existing tests if any, but better to update them
1568+ // Legacy fields maintained for backward compatibility.
14521569 lastRespOnStreaming * fwkrc.Response
14531570 lastTargetPodOnStreaming string
14541571}
0 commit comments