test: check request errors and stop asserting PathRewrite on /v1/models
/v1/models is served from config by ServeHTTP (task 2.5) so it never reaches routing; the rewrite test now uses a non-reserved path.
This commit is contained in:
@@ -76,7 +76,10 @@ func TestBodyBasedDispatch(t *testing.T) {
|
||||
reasoningCalled = false
|
||||
ornithCalled = false
|
||||
requestBody := `{"model":"reasoning","messages":[{"role":"user","content":"hi"}]}`
|
||||
resp, _ := http.Post(server.URL+"/v1/chat/completions", "application/json", strings.NewReader(requestBody))
|
||||
resp, err := http.Post(server.URL+"/v1/chat/completions", "application/json", strings.NewReader(requestBody))
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
if !reasoningCalled {
|
||||
@@ -151,7 +154,10 @@ func TestBodyPreservedUnmodified(t *testing.T) {
|
||||
|
||||
// Send a request with specific body content
|
||||
originalBody := `{"model":"reasoning","stream":true,"messages":[{"role":"user","content":"hello world"}],"temperature":0.7}`
|
||||
resp, _ := http.Post(server.URL+"/v1/chat/completions", "application/json", strings.NewReader(originalBody))
|
||||
resp, err := http.Post(server.URL+"/v1/chat/completions", "application/json", strings.NewReader(originalBody))
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
if string(receivedBody) != originalBody {
|
||||
@@ -249,7 +255,10 @@ func TestUnknownModelReject(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
requestBody := `{"model":"unknown-model","messages":[]}`
|
||||
resp, _ := http.Post(server.URL+"/v1/chat/completions", "application/json", strings.NewReader(requestBody))
|
||||
resp, err := http.Post(server.URL+"/v1/chat/completions", "application/json", strings.NewReader(requestBody))
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusBadRequest {
|
||||
@@ -300,7 +309,10 @@ func TestMissingModelField(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
requestBody := `{"messages":[]}`
|
||||
resp, _ := http.Post(server.URL+"/v1/chat/completions", "application/json", strings.NewReader(requestBody))
|
||||
resp, err := http.Post(server.URL+"/v1/chat/completions", "application/json", strings.NewReader(requestBody))
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusBadRequest {
|
||||
|
||||
@@ -323,7 +323,10 @@ func TestBodySizeCapRejectionLogged(t *testing.T) {
|
||||
|
||||
// Send an oversized body
|
||||
body := strings.Repeat("a", int(maxBodySize)+1)
|
||||
resp, _ := http.Post(server.URL+"/test", "text/plain", strings.NewReader(body))
|
||||
resp, err := http.Post(server.URL+"/test", "text/plain", strings.NewReader(body))
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
// Verify rejection status
|
||||
|
||||
@@ -45,11 +45,14 @@ func TestEmbeddingsPassthroughNoRewrite(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/embeddings",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":"nomic-ai/nomic-embed-text-v2-moe","input":"hello"}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if !embeddingsCalled {
|
||||
@@ -91,11 +94,14 @@ func TestEmbeddingsResponsePassthrough(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/embeddings",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":"nomic-ai/nomic-embed-text-v2-moe","input":"test"}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
@@ -135,11 +141,14 @@ func TestRerankPathRewrite(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/rerank",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":"BAAI/bge-reranker-base","query":"test","texts":["a","b"]}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Verify path IS rewritten to /rerank
|
||||
@@ -177,11 +186,14 @@ func TestRerankResponsePassthrough(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/rerank",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":"BAAI/bge-reranker-base","query":"q","texts":["a"]}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
@@ -209,11 +221,14 @@ func TestEmbeddingsUnknownModel(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/embeddings",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":"unknown-embeddings","input":"test"}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusBadRequest {
|
||||
@@ -244,11 +259,14 @@ func TestRerankerUnknownModel(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/rerank",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":"unknown-reranker","query":"q","texts":["a"]}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusBadRequest {
|
||||
@@ -288,11 +306,14 @@ func TestEmbeddingsBodyForwarded(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
originalBody := `{"model":"nomic-ai/nomic-embed-text-v2-moe","input":"test data with special chars: \u0001"}`
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/embeddings",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(originalBody)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
// The received body should match the original (though may have different formatting)
|
||||
@@ -337,11 +358,14 @@ func TestRerankerBodyForwarded(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
originalBody := `{"model":"BAAI/bge-reranker-base","query":"test","texts":["a","b","c"]}`
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/rerank",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(originalBody)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
var orig, received map[string]interface{}
|
||||
@@ -380,11 +404,14 @@ func TestUpstreamErrorStatusSurfaced(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/embeddings",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":"nomic-ai/nomic-embed-text-v2-moe","input":"test"}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusInternalServerError {
|
||||
|
||||
@@ -71,7 +71,7 @@ func TestHeaderHygiene(t *testing.T) {
|
||||
t.Errorf("hop-by-hop header %s should be stripped, but found: %s", header, receivedHeaders.Get(header))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TE header is tricky - it should be stripped but may be handled differently
|
||||
// Just verify it's not the original value for now
|
||||
if receivedHeaders.Get("TE") == "trailers" {
|
||||
|
||||
@@ -74,7 +74,10 @@ func TestModelsEndpointContentType(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Get(server.URL + "/v1/models")
|
||||
resp, err := http.Get(server.URL + "/v1/models")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
ct := resp.Header.Get("Content-Type")
|
||||
@@ -101,7 +104,10 @@ func TestModelsEndpointResponseShape(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Get(server.URL + "/v1/models")
|
||||
resp, err := http.Get(server.URL + "/v1/models")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result ModelListResponse
|
||||
@@ -161,7 +167,10 @@ func TestModelsEndpointEnumeratesAllModels(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Get(server.URL + "/v1/models")
|
||||
resp, err := http.Get(server.URL + "/v1/models")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result ModelListResponse
|
||||
@@ -211,7 +220,10 @@ func TestModelsEndpointHasRequiredFields(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Get(server.URL + "/v1/models")
|
||||
resp, err := http.Get(server.URL + "/v1/models")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result ModelListResponse
|
||||
@@ -292,7 +304,10 @@ func TestModelsEndpointDerivedFromConfig(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Get(server.URL + "/v1/models")
|
||||
resp, err := http.Get(server.URL + "/v1/models")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result ModelListResponse
|
||||
@@ -347,18 +362,24 @@ func TestModelsEndpointConsistentWithDispatch(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
// Get list of models
|
||||
resp, _ := http.Get(server.URL + "/v1/models")
|
||||
resp, err := http.Get(server.URL + "/v1/models")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
var result ModelListResponse
|
||||
json.NewDecoder(resp.Body).Decode(&result)
|
||||
resp.Body.Close()
|
||||
|
||||
// Try to dispatch to each advertised model
|
||||
for _, model := range result.Data {
|
||||
dispatchResp, _ := http.Post(
|
||||
dispatchResp, err := http.Post(
|
||||
server.URL+"/v1/chat/completions",
|
||||
"application/json",
|
||||
strings.NewReader(`{"model":"`+model.ID+`","messages":[]}`),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer dispatchResp.Body.Close()
|
||||
|
||||
// Should not return 400 (unknown model error)
|
||||
@@ -394,14 +415,20 @@ func TestModelsEndpointResponseIsConsistent(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
// Call endpoint twice
|
||||
resp1, _ := http.Get(server.URL + "/v1/models")
|
||||
resp1, err := http.Get(server.URL + "/v1/models")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
var result1 ModelListResponse
|
||||
json.NewDecoder(resp1.Body).Decode(&result1)
|
||||
resp1.Body.Close()
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
resp2, _ := http.Get(server.URL + "/v1/models")
|
||||
resp2, err := http.Get(server.URL + "/v1/models")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
var result2 ModelListResponse
|
||||
json.NewDecoder(resp2.Body).Decode(&result2)
|
||||
resp2.Body.Close()
|
||||
|
||||
@@ -105,7 +105,9 @@ func TestProxyPathRewrite(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, err := http.Get(server.URL + "/v1/models")
|
||||
// Not /v1/models: ServeHTTP serves that endpoint from config (task 2.5)
|
||||
// and returns before routing, so it never exercises PathRewrite.
|
||||
resp, err := http.Get(server.URL + "/some/path")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
@@ -146,7 +148,7 @@ func TestProxyConnectionReuse(t *testing.T) {
|
||||
defer handler.Close()
|
||||
|
||||
// Verify connection reuse by checking that the same transport is used
|
||||
|
||||
|
||||
// We can't easily count raw TCP connections in this test setup,
|
||||
// but we can verify that the transport is being reused by checking
|
||||
// that the same transport handles both requests
|
||||
@@ -402,7 +404,10 @@ func TestProxyPreservesBody(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
testBody := `{"model": "test", "messages": []}`
|
||||
resp, _ := http.Post(server.URL+"/test", "application/json", strings.NewReader(testBody))
|
||||
resp, err := http.Post(server.URL+"/test", "application/json", strings.NewReader(testBody))
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
if receivedBody != testBody {
|
||||
|
||||
@@ -102,7 +102,10 @@ func TestReadTimeout(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
start := time.Now()
|
||||
resp, _ := http.Get(server.URL + "/test")
|
||||
resp, err := http.Get(server.URL + "/test")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
elapsed := time.Since(start)
|
||||
|
||||
// Should timeout around the read timeout (with some tolerance)
|
||||
|
||||
@@ -16,8 +16,8 @@ import (
|
||||
|
||||
// OpenAI-style tool definition
|
||||
type Tool struct {
|
||||
Type string `json:"type"`
|
||||
Function ToolFunction `json:"function"`
|
||||
Type string `json:"type"`
|
||||
Function ToolFunction `json:"function"`
|
||||
}
|
||||
|
||||
type ToolFunction struct {
|
||||
@@ -28,21 +28,21 @@ type ToolFunction struct {
|
||||
|
||||
// OpenAI chat completion with tools request
|
||||
type ChatCompletionRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []Message `json:"messages"`
|
||||
Tools []Tool `json:"tools,omitempty"`
|
||||
Stream bool `json:"stream,omitempty"`
|
||||
Model string `json:"model"`
|
||||
Messages []Message `json:"messages"`
|
||||
Tools []Tool `json:"tools,omitempty"`
|
||||
Stream bool `json:"stream,omitempty"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Role string `json:"role"`
|
||||
Content interface{} `json:"content"`
|
||||
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
||||
Role string `json:"role"`
|
||||
Content interface{} `json:"content"`
|
||||
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
||||
}
|
||||
|
||||
type ToolCall struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Function FunctionCall `json:"function"`
|
||||
}
|
||||
|
||||
@@ -64,21 +64,21 @@ func TestToolCallOpenAIStyle(t *testing.T) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
response := map[string]interface{}{
|
||||
"id": "chatcmpl-123",
|
||||
"object": "chat.completion",
|
||||
"model": "reasoning",
|
||||
"id": "chatcmpl-123",
|
||||
"object": "chat.completion",
|
||||
"model": "reasoning",
|
||||
"choices": []map[string]interface{}{
|
||||
{
|
||||
"index": 0,
|
||||
"message": map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"role": "assistant",
|
||||
"content": nil,
|
||||
"tool_calls": []map[string]interface{}{
|
||||
{
|
||||
"id": "call_abc123",
|
||||
"id": "call_abc123",
|
||||
"type": "function",
|
||||
"function": map[string]interface{}{
|
||||
"name": "get_weather",
|
||||
"name": "get_weather",
|
||||
"arguments": `{"location":"San Francisco","unit":"celsius"}`,
|
||||
},
|
||||
},
|
||||
@@ -372,10 +372,10 @@ func TestToolCallMultiTurn(t *testing.T) {
|
||||
"content": nil,
|
||||
"tool_calls": []map[string]interface{}{
|
||||
{
|
||||
"id": "call_abc123",
|
||||
"id": "call_abc123",
|
||||
"type": "function",
|
||||
"function": map[string]interface{}{
|
||||
"name": "get_weather",
|
||||
"name": "get_weather",
|
||||
"arguments": `{"location":"San Francisco"}`,
|
||||
},
|
||||
},
|
||||
@@ -430,7 +430,10 @@ func TestToolCallMultiTurn(t *testing.T) {
|
||||
}
|
||||
|
||||
body1, _ := json.Marshal(turn1)
|
||||
resp1, _ := http.Post(server.URL+"/v1/chat/completions", "application/json", bytes.NewReader(body1))
|
||||
resp1, err := http.Post(server.URL+"/v1/chat/completions", "application/json", bytes.NewReader(body1))
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
var turn1Resp map[string]interface{}
|
||||
json.NewDecoder(resp1.Body).Decode(&turn1Resp)
|
||||
resp1.Body.Close()
|
||||
@@ -472,7 +475,10 @@ func TestToolCallMultiTurn(t *testing.T) {
|
||||
}
|
||||
|
||||
body2, _ := json.Marshal(turn2)
|
||||
resp2, _ := http.Post(server.URL+"/v1/chat/completions", "application/json", bytes.NewReader(body2))
|
||||
resp2, err := http.Post(server.URL+"/v1/chat/completions", "application/json", bytes.NewReader(body2))
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
var turn2Resp map[string]interface{}
|
||||
json.NewDecoder(resp2.Body).Decode(&turn2Resp)
|
||||
resp2.Body.Close()
|
||||
@@ -503,7 +509,7 @@ func TestParallelToolCalls(t *testing.T) {
|
||||
"content": nil,
|
||||
"tool_calls": []map[string]interface{}{
|
||||
{
|
||||
"id": "call_1",
|
||||
"id": "call_1",
|
||||
"type": "function",
|
||||
"function": map[string]interface{}{
|
||||
"name": "get_weather",
|
||||
@@ -511,7 +517,7 @@ func TestParallelToolCalls(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "call_2",
|
||||
"id": "call_2",
|
||||
"type": "function",
|
||||
"function": map[string]interface{}{
|
||||
"name": "get_weather",
|
||||
@@ -519,7 +525,7 @@ func TestParallelToolCalls(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "call_3",
|
||||
"id": "call_3",
|
||||
"type": "function",
|
||||
"function": map[string]interface{}{
|
||||
"name": "get_weather",
|
||||
@@ -576,7 +582,10 @@ func TestParallelToolCalls(t *testing.T) {
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(request)
|
||||
resp, _ := http.Post(server.URL+"/v1/chat/completions", "application/json", bytes.NewReader(body))
|
||||
resp, err := http.Post(server.URL+"/v1/chat/completions", "application/json", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
var respData map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&respData)
|
||||
resp.Body.Close()
|
||||
@@ -627,9 +636,9 @@ func TestAnthropicToolUse(t *testing.T) {
|
||||
|
||||
// Anthropic response format with tool_use block
|
||||
response := map[string]interface{}{
|
||||
"id": "msg_123",
|
||||
"type": "message",
|
||||
"role": "assistant",
|
||||
"id": "msg_123",
|
||||
"type": "message",
|
||||
"role": "assistant",
|
||||
"content": []map[string]interface{}{
|
||||
{
|
||||
"type": "text",
|
||||
@@ -714,7 +723,10 @@ func TestAnthropicToolUse(t *testing.T) {
|
||||
body, _ := json.Marshal(anthropicRequest)
|
||||
// Note: For now we route through a generic path
|
||||
// In Phase 2.9+, this would be integrated with the Anthropic dialect handler
|
||||
resp, _ := http.Post(server.URL+"/v1/messages", "application/json", bytes.NewReader(body))
|
||||
resp, err := http.Post(server.URL+"/v1/messages", "application/json", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
var respData map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&respData)
|
||||
resp.Body.Close()
|
||||
@@ -762,7 +774,7 @@ func TestComplexToolArguments(t *testing.T) {
|
||||
"content": nil,
|
||||
"tool_calls": []map[string]interface{}{
|
||||
{
|
||||
"id": "call_complex",
|
||||
"id": "call_complex",
|
||||
"type": "function",
|
||||
"function": map[string]interface{}{
|
||||
"name": "create_event",
|
||||
@@ -832,7 +844,10 @@ func TestComplexToolArguments(t *testing.T) {
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(request)
|
||||
resp, _ := http.Post(server.URL+"/v1/chat/completions", "application/json", bytes.NewReader(body))
|
||||
resp, err := http.Post(server.URL+"/v1/chat/completions", "application/json", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
var respData map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&respData)
|
||||
resp.Body.Close()
|
||||
|
||||
@@ -134,11 +134,14 @@ func TestUnknownModelEnumeratesValidModels(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/chat/completions",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":"unknown","messages":[]}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var prob map[string]interface{}
|
||||
@@ -188,11 +191,14 @@ func TestMissingModelFieldReturns4xx(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
// Request with no model field
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/chat/completions",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"messages":[]}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode < 400 || resp.StatusCode >= 500 {
|
||||
@@ -230,11 +236,14 @@ func TestNullModelFieldReturns4xx(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
// Request with null model
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/chat/completions",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":null,"messages":[]}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode < 400 || resp.StatusCode >= 500 {
|
||||
@@ -266,11 +275,14 @@ func TestEmptyModelFieldReturns4xx(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
// Request with empty model string
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/chat/completions",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":"","messages":[]}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode < 400 || resp.StatusCode >= 500 {
|
||||
@@ -297,11 +309,14 @@ func TestInvalidJSONIsDistinguishableError(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
// Request with invalid JSON
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/chat/completions",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`not json`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode < 400 || resp.StatusCode >= 500 {
|
||||
@@ -405,19 +420,25 @@ func TestMissingModelAndUnknownModelBothReturn4xx(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
// Test missing model
|
||||
resp1, _ := http.Post(
|
||||
resp1, err := http.Post(
|
||||
server.URL+"/v1/chat/completions",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"messages":[]}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
resp1.Body.Close()
|
||||
|
||||
// Test unknown model
|
||||
resp2, _ := http.Post(
|
||||
resp2, err := http.Post(
|
||||
server.URL+"/v1/chat/completions",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":"unknown","messages":[]}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
resp2.Body.Close()
|
||||
|
||||
// Both should be in 4xx range
|
||||
@@ -460,11 +481,14 @@ func TestProblemDetailHasRequiredFields(t *testing.T) {
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
resp, _ := http.Post(
|
||||
resp, err := http.Post(
|
||||
server.URL+"/v1/chat/completions",
|
||||
"application/json",
|
||||
bytes.NewReader([]byte(`{"model":"unknown","messages":[]}`)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var prob map[string]interface{}
|
||||
|
||||
Reference in New Issue
Block a user