package configuration import ( "context" "encoding/json" "errors" "net/http" "net/http/httptest" "reflect" "testing" "gitea.maximumdirect.net/eric/promptkit/internal/defaults" "gitea.maximumdirect.net/eric/promptkit/internal/domain" "gitea.maximumdirect.net/eric/promptkit/internal/llm" profilepkg "gitea.maximumdirect.net/eric/promptkit/internal/profile" ) func TestLoadBuildsEffectiveTargetsAfterInheritance(t *testing.T) { state, err := load(mapping("effective-targets", map[string]any{ "backends": map[string]any{ "first": map[string]any{"endpoint": "https://first.example/v1", "api_key_env": "FIRST_KEY", "extra_params": map[string]any{"source": "first", "nested": map[string]any{"old": true}}}, "second": map[string]any{"endpoint": "https://second.example/v1", "api_key_env": "SECOND_KEY", "concurrency_limit": 2, "queue_capacity": 0, "extra_params": map[string]any{"source": "second", "nested": map[string]any{"backend": true}}}, }, "profiles": map[string]any{ "base": map[string]any{"backend": "first", "model": "model", "temperature": 0.8, "top_p": 0.9, "max_tokens": 100, "timeout_seconds": 30, "api_key_required": true, "extra_params": map[string]any{"nested": map[string]any{"profile": true}}}, "child": map[string]any{"extends": "base", "backend": "second", "temperature": 0.0, "top_p": nil, "max_tokens": 0, "timeout_seconds": nil, "api_key_env": nil, "api_key_required": false, "extra_params": map[string]any{"nested": map[string]any{"child": nil}}}, "direct-key": map[string]any{"backend": "second", "api_key_required": true}, "named-key": map[string]any{"backend": "second", "api_key_required": true, "api_key_env": "CUSTOM_KEY"}, "no-provider-map": map[string]any{"backend": "second", "extra_params": nil}, "no-timeout": map[string]any{"backend": "second", "timeout_seconds": 0}, "partial": map[string]any{}, "endpoint-only": map[string]any{"endpoint": "https://standalone.example/v1"}, "cleared-endpoint": map[string]any{"extends": "base", "endpoint": nil}, }, }), nil) if err != nil { t.Fatal(err) } selected, err := state.registry.GetBackend("second") if err != nil || selected.QueueCapacity != 0 || !selected.QueueCapacitySet { t.Fatalf("backend capacity was not preserved: %+v, %v", selected, err) } child, err := state.GetProfile(context.Background(), "child") if err != nil { t.Fatal(err) } if _, err := state.GetProfile(context.Background(), " child "); err == nil { t.Fatal("profile lookup silently changed a literal ID") } target := child.ResolvedTarget if target.BackendID != "second" || target.Endpoint != "https://second.example/v1" || target.Model != "model" || target.Temperature != 0 || target.TopP != 0 || target.MaxTokens != 0 || target.TimeoutSeconds != defaults.ExecutionDefaultTimeoutSeconds || target.APIKeyEnv != "" || target.APIKeyRequired { t.Fatalf("effective child target is wrong: %+v", target) } if !child.TargetPresence.Temperature || !child.TargetPresence.MaxTokens || child.TargetPresence.TopP || child.TargetPresence.TimeoutSeconds { t.Fatalf("numeric presence was not retained: %+v", child.TargetPresence) } wantParams := map[string]any{"source": "second", "nested": map[string]any{ "backend": true, "profile": true, "child": nil, }} if !reflect.DeepEqual(target.ExtraParams, wantParams) { t.Fatalf("backend/profile provider map overlay failed: %+v", target.ExtraParams) } if _, exists := target.ExtraParams["nested"].(map[string]any)["old"]; exists { t.Fatal("previous backend derived parameter leaked into child") } for id, wantEnv := range map[string]string{"direct-key": "", "named-key": "CUSTOM_KEY"} { profile, err := state.GetProfile(context.Background(), id) if err != nil || profile.ResolvedTarget.APIKeyEnv != wantEnv { t.Fatalf("credential source for %s: %+v, %v", id, profile, err) } } noMap, _ := state.GetProfile(context.Background(), "no-provider-map") if noMap.ResolvedTarget.ExtraParams != nil { t.Fatalf("explicit null provider map did not suppress backend defaults: %+v", noMap.ResolvedTarget.ExtraParams) } noTimeout, _ := state.GetProfile(context.Background(), "no-timeout") if noTimeout.ResolvedTarget.TimeoutSeconds != 0 || !noTimeout.TargetPresence.TimeoutSeconds { t.Fatalf("explicit zero timeout was lost: %+v", noTimeout) } partial, _ := state.GetProfile(context.Background(), "partial") if partial.ResolvedTarget.Endpoint != "" || partial.ResolvedTarget.Model != "" { t.Fatalf("partial profile gained a runnable target: %+v", partial.ResolvedTarget) } identity, err := state.GetProfileIdentity(context.Background(), "partial") if err != nil || identity != "partial" { t.Fatalf("partial profile identity=(%q, %v)", identity, err) } if _, err := state.GetProfileIdentity(context.Background(), "missing"); !errors.Is(err, profilepkg.ErrProfileNotFound) { t.Fatalf("missing profile identity error=%v", err) } ctx, cancel := context.WithCancel(context.Background()) cancel() if _, err := state.GetProfileIdentity(ctx, "partial"); !errors.Is(err, context.Canceled) { t.Fatalf("canceled profile identity lookup error=%v", err) } endpointOnly, _ := state.GetProfile(context.Background(), "endpoint-only") if endpointOnly.ResolvedTarget.Endpoint != "https://standalone.example/v1" || endpointOnly.ResolvedTarget.BackendID != "" || endpointOnly.ResolvedTarget.Model != "" { t.Fatalf("endpoint-only profile was not retained: %+v", endpointOnly.ResolvedTarget) } clearedEndpoint, _ := state.GetProfile(context.Background(), "cleared-endpoint") if clearedEndpoint.ResolvedTarget.Endpoint != "" || clearedEndpoint.ResolvedTarget.BackendID != "first" { t.Fatalf("explicit null recovered backend endpoint: %+v", clearedEndpoint.ResolvedTarget) } child.ResolvedTarget.ExtraParams["source"] = "mutated" again, _ := state.GetProfile(context.Background(), "child") if again.ResolvedTarget.ExtraParams["source"] != "second" { t.Fatal("profile lookup exposed snapshot ownership") } } func TestLoadedZeroControlsReachBuiltInRequest(t *testing.T) { payloads := make(chan map[string]any, 1) server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { var payload map[string]any if err := json.NewDecoder(request.Body).Decode(&payload); err != nil { writer.WriteHeader(http.StatusBadRequest) return } payloads <- payload writer.Header().Set("Content-Type", "application/json") _, _ = writer.Write([]byte(`{"choices":[{"message":{"content":"ok"}}]}`)) })) defer server.Close() state, err := load(mapping("wire-controls", map[string]any{ "backends": map[string]any{"local": map[string]any{"endpoint": server.URL + "/v1"}}, "profiles": map[string]any{"direct": map[string]any{ "backend": "local", "model": "example", "temperature": 0.0, "max_tokens": 0, "top_p": nil, }}, }), nil) if err != nil { t.Fatal(err) } profile, err := state.GetProfile(context.Background(), "direct") if err != nil { t.Fatal(err) } client, err := llm.NewOpenAICompatibleClient(llm.OpenAICompatibleConfig{}) if err != nil { t.Fatal(err) } _, err = client.Generate(context.Background(), domain.GenerateRequest{ Prompt: domain.RenderedPrompt{Messages: []domain.RenderedMessage{{Role: "user", Content: "hello"}}}, Target: *profile.ResolvedTarget, TargetPresence: profile.TargetPresence, }) if err != nil { t.Fatal(err) } payload := <-payloads if payload["temperature"] != float64(0) || payload["max_tokens"] != float64(0) { t.Fatalf("explicit zeros were omitted from outbound request: %+v", payload) } if _, exists := payload["top_p"]; exists { t.Fatalf("explicit null top_p was sent: %+v", payload) } }