(t *testing.T)
| 1252 | } |
| 1253 | |
| 1254 | func TestErrorHandling(t *testing.T) { |
| 1255 | t.Parallel() |
| 1256 | |
| 1257 | // Tests that errors which occur *before* a streaming response begins, or in non-streaming requests, are handled as expected. |
| 1258 | t.Run("non-stream error", func(t *testing.T) { |
| 1259 | t.Parallel() |
| 1260 | |
| 1261 | cases := []struct { |
| 1262 | name string |
| 1263 | fixture []byte |
| 1264 | path string |
| 1265 | responseHandlerFn func(resp *http.Response) |
| 1266 | }{ |
| 1267 | { |
| 1268 | name: config.ProviderAnthropic, |
| 1269 | fixture: fixtures.AntNonStreamError, |
| 1270 | path: pathAnthropicMessages, |
| 1271 | responseHandlerFn: func(resp *http.Response) { |
| 1272 | require.Equal(t, http.StatusBadRequest, resp.StatusCode) |
| 1273 | body, err := io.ReadAll(resp.Body) |
| 1274 | require.NoError(t, err) |
| 1275 | require.Equal(t, "error", gjson.GetBytes(body, "type").Str) |
| 1276 | require.Equal(t, "invalid_request_error", gjson.GetBytes(body, "error.type").Str) |
| 1277 | require.Contains(t, gjson.GetBytes(body, "error.message").Str, "prompt is too long") |
| 1278 | }, |
| 1279 | }, |
| 1280 | { |
| 1281 | name: config.ProviderOpenAI, |
| 1282 | fixture: fixtures.OaiChatNonStreamError, |
| 1283 | path: pathOpenAIChatCompletions, |
| 1284 | responseHandlerFn: func(resp *http.Response) { |
| 1285 | require.Equal(t, http.StatusBadRequest, resp.StatusCode) |
| 1286 | body, err := io.ReadAll(resp.Body) |
| 1287 | require.NoError(t, err) |
| 1288 | require.Equal(t, "context_length_exceeded", gjson.GetBytes(body, "error.code").Str) |
| 1289 | require.Equal(t, "invalid_request_error", gjson.GetBytes(body, "error.type").Str) |
| 1290 | require.Contains(t, gjson.GetBytes(body, "error.message").Str, "Input tokens exceed the configured limit") |
| 1291 | }, |
| 1292 | }, |
| 1293 | } |
| 1294 | |
| 1295 | for _, tc := range cases { |
| 1296 | t.Run(tc.name, func(t *testing.T) { |
| 1297 | t.Parallel() |
| 1298 | |
| 1299 | for _, streaming := range []bool{true, false} { |
| 1300 | t.Run(fmt.Sprintf("streaming=%v", streaming), func(t *testing.T) { |
| 1301 | t.Parallel() |
| 1302 | |
| 1303 | ctx, cancel := context.WithTimeout(t.Context(), testutil.WaitLong) |
| 1304 | t.Cleanup(cancel) |
| 1305 | |
| 1306 | // Setup mock server. Error fixtures contain raw HTTP |
| 1307 | // responses that may cause the bridge to retry. |
| 1308 | fix := fixtures.Parse(t, tc.fixture) |
| 1309 | upstream := newMockUpstream(ctx, t, newFixtureResponse(fix)) |
| 1310 | |
| 1311 | bridgeServer := newBridgeTestServer(ctx, t, upstream.URL) |
nothing calls this directly
no test coverage detected