Files
browser/platform/service/ai_provider_http_test.go
2026-07-20 16:42:33 +08:00

56 lines
2.5 KiB
Go

package service
import (
"io"
"net/http"
"strings"
"testing"
"browser.local/platform/domain"
)
func TestHTTPAIProviderClientReturnsBoundedStructuredRecommendation(t *testing.T) {
transport := roundTripFunc(func(r *http.Request) (*http.Response, error) {
if r.URL.Path != "/v1/chat/completions" {
t.Fatalf("unexpected provider path %q", r.URL.Path)
}
if r.Header.Get("Authorization") != "" {
t.Fatal("local provider must not receive an authorization header")
}
body, _ := io.ReadAll(r.Body)
if strings.Contains(string(body), "apiKeyRef") {
t.Fatal("provider request leaked secret reference metadata")
}
return &http.Response{StatusCode: http.StatusOK, Header: http.Header{"Content-Type": []string{"application/json"}}, Body: io.NopCloser(strings.NewReader(`{"choices":[{"message":{"role":"assistant","content":"{\"recommendation\":\"Review PVP policy\",\"suggestedConfig\":\"pvp=false\\n\"}"}}],"usage":{"prompt_tokens":12,"completion_tokens":8}}`))}, nil
})
client := HTTPAIProviderClient{HTTPClient: &http.Client{Transport: transport}}
result, err := client.Invoke(domain.AIProvider{ID: "local", Kind: domain.AIProviderKindOllama, BaseURL: "http://127.0.0.1:18000/v1", RelayMode: domain.AIRelayModeLocal, TimeoutMS: 1000, DefaultModel: "test-model"}, domain.AIInvocationRequest{RequestID: "http-ai-1", Purpose: "config.suggest", Prompt: "disable pvp", CurrentConfig: "pvp=true\n"})
if err != nil {
t.Fatalf("invoke provider: %v", err)
}
if result.Recommendation != "Review PVP policy" || result.SuggestedConfig != "pvp=false\n" || result.Usage.Mocked {
t.Fatalf("unexpected provider result %+v", result)
}
}
func TestHTTPAIProviderClientRedactsTransportFailure(t *testing.T) {
client := HTTPAIProviderClient{HTTPClient: &http.Client{Transport: failingRoundTripper{}}}
_, err := client.Invoke(domain.AIProvider{ID: "local", Kind: domain.AIProviderKindOllama, BaseURL: "http://127.0.0.1:18000/v1", RelayMode: domain.AIRelayModeLocal, TimeoutMS: 1000, DefaultModel: "test-model"}, domain.AIInvocationRequest{RequestID: "http-ai-fail", Purpose: "logs.diagnose", Prompt: "inspect"})
if err == nil || err.Error() != "AI provider transport failed" {
t.Fatalf("expected redacted transport failure, got %v", err)
}
}
type failingRoundTripper struct{}
func (failingRoundTripper) RoundTrip(*http.Request) (*http.Response, error) {
return nil, io.ErrUnexpectedEOF
}
type roundTripFunc func(*http.Request) (*http.Response, error)
func (fn roundTripFunc) RoundTrip(request *http.Request) (*http.Response, error) {
return fn(request)
}