(t *testing.T)
| 1419 | } |
| 1420 | |
| 1421 | func TestErrorHandling(t *testing.T) { |
| 1422 | t.Parallel() |
| 1423 | |
| 1424 | // Tests that errors which occur *before* a streaming response begins, or in non-streaming requests, are handled as expected. |
| 1425 | t.Run("non-stream error", func(t *testing.T) { |
| 1426 | t.Parallel() |
| 1427 | |
| 1428 | cases := []struct { |
| 1429 | name string |
| 1430 | fixture []byte |
| 1431 | path string |
| 1432 | responseHandlerFn func(resp *http.Response) |
| 1433 | }{ |
| 1434 | { |
| 1435 | name: config.ProviderAnthropic, |
| 1436 | fixture: fixtures.AntNonStreamError, |
| 1437 | path: pathAnthropicMessages, |
| 1438 | responseHandlerFn: func(resp *http.Response) { |
| 1439 | require.Equal(t, http.StatusBadRequest, resp.StatusCode) |
| 1440 | body, err := io.ReadAll(resp.Body) |
| 1441 | require.NoError(t, err) |
| 1442 | require.Equal(t, "error", gjson.GetBytes(body, "type").Str) |
| 1443 | require.Equal(t, "invalid_request_error", gjson.GetBytes(body, "error.type").Str) |
| 1444 | require.Contains(t, gjson.GetBytes(body, "error.message").Str, "prompt is too long") |
| 1445 | }, |
| 1446 | }, |
| 1447 | { |
| 1448 | name: config.ProviderOpenAI, |
| 1449 | fixture: fixtures.OaiChatNonStreamError, |
| 1450 | path: pathOpenAIChatCompletions, |
| 1451 | responseHandlerFn: func(resp *http.Response) { |
| 1452 | require.Equal(t, http.StatusBadRequest, resp.StatusCode) |
| 1453 | body, err := io.ReadAll(resp.Body) |
| 1454 | require.NoError(t, err) |
| 1455 | require.Equal(t, "context_length_exceeded", gjson.GetBytes(body, "error.code").Str) |
| 1456 | require.Equal(t, "invalid_request_error", gjson.GetBytes(body, "error.type").Str) |
| 1457 | require.Contains(t, gjson.GetBytes(body, "error.message").Str, "Input tokens exceed the configured limit") |
| 1458 | }, |
| 1459 | }, |
| 1460 | } |
| 1461 | |
| 1462 | for _, tc := range cases { |
| 1463 | t.Run(tc.name, func(t *testing.T) { |
| 1464 | t.Parallel() |
| 1465 | |
| 1466 | for _, streaming := range []bool{true, false} { |
| 1467 | t.Run(fmt.Sprintf("streaming=%v", streaming), func(t *testing.T) { |
| 1468 | t.Parallel() |
| 1469 | |
| 1470 | ctx, cancel := context.WithTimeout(t.Context(), testutil.WaitLong) |
| 1471 | t.Cleanup(cancel) |
| 1472 | |
| 1473 | // Setup mock server. Error fixtures contain raw HTTP |
| 1474 | // responses that may cause the bridge to retry. |
| 1475 | fix := fixtures.Parse(t, tc.fixture) |
| 1476 | upstream := newMockUpstream(ctx, t, newFixtureResponse(fix)) |
| 1477 | |
| 1478 | bridgeServer := newBridgeTestServer(ctx, t, upstream.URL) |
nothing calls this directly
no test coverage detected