@@ -55,8 +55,9 @@ func (c *fakeAsyncClient) Close() error { return nil }
5555func (c * fakeAsyncClient ) deliver (requestID string , body map [string ]any ) {
5656 resp , _ := json .Marshal (body )
5757 c .results <- & inference.GenerateResponse {
58- RequestID : requestID ,
59- Response : resp ,
58+ RequestID : requestID ,
59+ Response : resp ,
60+ StatusCode : 200 ,
6061 }
6162}
6263
@@ -127,34 +128,123 @@ func TestAsyncEndToEnd(t *testing.T) {
127128 }
128129}
129130
130- func TestAsyncResult_NilResponseBody (t * testing.T ) {
131- resp := & inference.GenerateResponse {
132- RequestID : "req-nil-body" ,
133- Response : nil ,
134- }
135- result := asyncResult (resp , logr .Discard ())
136- if result .Error == nil {
137- t .Fatal ("expected error for nil response body" )
138- }
139- if result .Error .Code != "server_error" {
140- t .Fatalf ("error code = %q, want %q" , result .Error .Code , "server_error" )
141- }
142- if result .Response != nil {
143- t .Fatalf ("expected nil response, got %+v" , result .Response )
131+ func TestAsyncResult (t * testing.T ) {
132+ tests := []struct {
133+ name string
134+ resp * inference.GenerateResponse
135+ wantStatusCode int
136+ wantErrCode string
137+ wantResponse bool
138+ }{
139+ {
140+ name : "nil body treated as empty 2xx" ,
141+ resp : & inference.GenerateResponse {
142+ RequestID : "req-nil-body" ,
143+ Response : nil ,
144+ },
145+ wantErrCode : "server_error" ,
146+ },
147+ {
148+ name : "bad JSON on 2xx is parse_error" ,
149+ resp : & inference.GenerateResponse {
150+ RequestID : "req-bad-json" ,
151+ Response : []byte (`{not valid json` ),
152+ StatusCode : 200 ,
153+ },
154+ wantErrCode : "parse_error" ,
155+ },
156+ {
157+ name : "legacy success without StatusCode defaults to 200" ,
158+ resp : & inference.GenerateResponse {
159+ RequestID : "req-ok" ,
160+ Response : []byte (`{"choices":[]}` ),
161+ },
162+ wantStatusCode : 200 ,
163+ wantResponse : true ,
164+ },
165+ {
166+ name : "success with StatusCode 200" ,
167+ resp : & inference.GenerateResponse {
168+ RequestID : "req-ok-200" ,
169+ Response : []byte (`{"choices":[]}` ),
170+ StatusCode : 200 ,
171+ },
172+ wantStatusCode : 200 ,
173+ wantResponse : true ,
174+ },
175+ {
176+ name : "HTTP 403 with empty body preserves status" ,
177+ resp : & inference.GenerateResponse {
178+ RequestID : "req-403" ,
179+ Response : []byte {},
180+ StatusCode : 403 ,
181+ },
182+ wantStatusCode : 403 ,
183+ wantResponse : true ,
184+ },
185+ {
186+ name : "HTTP 403 with JSON error body preserves status" ,
187+ resp : & inference.GenerateResponse {
188+ RequestID : "req-403-json" ,
189+ Response : []byte (`{"error":{"message":"unauthorized"}}` ),
190+ StatusCode : 403 ,
191+ },
192+ wantStatusCode : 403 ,
193+ wantResponse : true ,
194+ },
195+ {
196+ name : "HTTP 422 with unparseable body preserves status" ,
197+ resp : & inference.GenerateResponse {
198+ RequestID : "req-422" ,
199+ Response : []byte (`not-json` ),
200+ StatusCode : 422 ,
201+ },
202+ wantStatusCode : 422 ,
203+ wantResponse : true ,
204+ },
205+ {
206+ name : "non-HTTP failure uses ErrorCode" ,
207+ resp : & inference.GenerateResponse {
208+ RequestID : "req-deadline" ,
209+ StatusCode : 0 ,
210+ ErrorCode : "DEADLINE_EXCEEDED" ,
211+ ErrorMessage : "deadline exceeded" ,
212+ },
213+ wantErrCode : "DEADLINE_EXCEEDED" ,
214+ },
144215 }
145- }
146216
147- func TestAsyncResult_BadJSONBody (t * testing.T ) {
148- resp := & inference.GenerateResponse {
149- RequestID : "req-bad-json" ,
150- Response : []byte (`{not valid json` ),
151- }
152- result := asyncResult (resp , logr .Discard ())
153- if result .Error == nil {
154- t .Fatal ("expected error for bad JSON body" )
155- }
156- if result .Error .Code != "parse_error" {
157- t .Fatalf ("error code = %q, want %q" , result .Error .Code , "parse_error" )
217+ for _ , tt := range tests {
218+ t .Run (tt .name , func (t * testing.T ) {
219+ result := asyncResult (tt .resp , logr .Discard ())
220+ if tt .wantErrCode != "" {
221+ if result .Error == nil {
222+ t .Fatalf ("expected error code %q, got nil error" , tt .wantErrCode )
223+ }
224+ if result .Error .Code != tt .wantErrCode {
225+ t .Fatalf ("error code = %q, want %q" , result .Error .Code , tt .wantErrCode )
226+ }
227+ if result .Response != nil {
228+ t .Fatalf ("expected nil response, got %+v" , result .Response )
229+ }
230+ return
231+ }
232+ if result .Error != nil {
233+ t .Fatalf ("unexpected error: %+v" , result .Error )
234+ }
235+ if ! tt .wantResponse {
236+ return
237+ }
238+ if result .Response == nil {
239+ t .Fatal ("expected response" )
240+ }
241+ if result .Response .StatusCode != tt .wantStatusCode {
242+ t .Fatalf ("StatusCode = %d, want %d" , result .Response .StatusCode , tt .wantStatusCode )
243+ }
244+ if result .Response .RequestID != tt .resp .RequestID {
245+ t .Fatalf ("RequestID = %q, want %q" , result .Response .RequestID , tt .resp .RequestID )
246+ }
247+ })
158248 }
159249}
160250
@@ -178,26 +268,6 @@ func TestSafeChannelSend(t *testing.T) {
178268 })
179269}
180270
181- func TestAsyncResult_Success (t * testing.T ) {
182- resp := & inference.GenerateResponse {
183- RequestID : "req-ok" ,
184- Response : []byte (`{"choices":[]}` ),
185- }
186- result := asyncResult (resp , logr .Discard ())
187- if result .Error != nil {
188- t .Fatalf ("unexpected error: %+v" , result .Error )
189- }
190- if result .Response == nil {
191- t .Fatal ("expected response" )
192- }
193- if result .Response .StatusCode != 200 {
194- t .Fatalf ("StatusCode = %d, want 200" , result .Response .StatusCode )
195- }
196- if result .Response .RequestID != "req-ok" {
197- t .Fatalf ("RequestID = %q, want %q" , result .Response .RequestID , "req-ok" )
198- }
199- }
200-
201271func TestBroadcaster_RetriesTransientError (t * testing.T ) {
202272 synctest .Test (t , func (t * testing.T ) {
203273 var callCount atomic.Int32
0 commit comments