(t *testing.T)
| 211 | } |
| 212 | |
| 213 | func TestRequestBodySizeLimit(t *testing.T) { |
| 214 | t.Parallel() |
| 215 | |
| 216 | newOpenAI := func(baseURL string) provider.Provider { |
| 217 | return aibridge.NewOpenAIProvider(config.OpenAI{Name: "openai", BaseURL: baseURL}) |
| 218 | } |
| 219 | newAnthropic := func(baseURL string) provider.Provider { |
| 220 | return aibridge.NewAnthropicProvider(config.Anthropic{Name: "anthropic", BaseURL: baseURL}, nil) |
| 221 | } |
| 222 | newCopilot := func(baseURL string) provider.Provider { |
| 223 | return aibridge.NewCopilotProvider(config.Copilot{Name: "copilot", BaseURL: baseURL}) |
| 224 | } |
| 225 | |
| 226 | // Each body is a well-formed, schema-valid request for its provider, with |
| 227 | // an oversized message content that pushes it past the 32 MiB limit. |
| 228 | filler := strings.Repeat("A", 32<<20) |
| 229 | chatCompletionsBody := fmt.Appendf(nil, `{"model":"gpt-4","messages":[{"role":"user","content":"%s"}]}`, filler) |
| 230 | responsesBody := fmt.Appendf(nil, `{"model":"gpt-4","input":"%s"}`, filler) |
| 231 | messagesBody := fmt.Appendf(nil, `{"model":"claude-3-5-sonnet-latest","max_tokens":1024,"messages":[{"role":"user","content":"%s"}]}`, filler) |
| 232 | |
| 233 | tests := []struct { |
| 234 | name string |
| 235 | provider func(baseURL string) provider.Provider |
| 236 | path string |
| 237 | body []byte |
| 238 | }{ |
| 239 | {name: "openai_passthrough", provider: newOpenAI, path: "/openai/v1/models", body: chatCompletionsBody}, |
| 240 | {name: "openai_chat_completions", provider: newOpenAI, path: "/openai/v1/chat/completions", body: chatCompletionsBody}, |
| 241 | {name: "openai_responses", provider: newOpenAI, path: "/openai/v1/responses", body: responsesBody}, |
| 242 | {name: "anthropic_passthrough", provider: newAnthropic, path: "/anthropic/v1/models", body: messagesBody}, |
| 243 | {name: "anthropic_messages", provider: newAnthropic, path: "/anthropic/v1/messages", body: messagesBody}, |
| 244 | {name: "copilot_passthrough", provider: newCopilot, path: "/copilot/models", body: chatCompletionsBody}, |
| 245 | {name: "copilot_chat_completions", provider: newCopilot, path: "/copilot/chat/completions", body: chatCompletionsBody}, |
| 246 | {name: "copilot_responses", provider: newCopilot, path: "/copilot/responses", body: responsesBody}, |
| 247 | } |
| 248 | |
| 249 | for _, tc := range tests { |
| 250 | t.Run(tc.name, func(t *testing.T) { |
| 251 | t.Parallel() |
| 252 | |
| 253 | logger := slogtest.Make(t, nil) |
| 254 | |
| 255 | upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 256 | _, _ = io.ReadAll(r.Body) |
| 257 | w.WriteHeader(http.StatusOK) |
| 258 | })) |
| 259 | t.Cleanup(upstream.Close) |
| 260 | |
| 261 | prov := tc.provider(upstream.URL) |
| 262 | bridge, err := aibridge.NewRequestBridge( |
| 263 | t.Context(), |
| 264 | []provider.Provider{prov}, |
| 265 | nil, nil, logger, nil, bridgeTestTracer, |
| 266 | ) |
| 267 | require.NoError(t, err) |
| 268 | |
| 269 | req := httptest.NewRequest(http.MethodPost, tc.path, bytes.NewReader(tc.body)) |
| 270 | // Unknown Content-Length |
nothing calls this directly
no test coverage detected