56 lines
2.5 KiB
Go
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)
|
|
}
|