Verify identified resource composition and inheritance

This commit is contained in:
2026-11-02 12:47:25 +00:00
parent afcfae2aea
commit dbc345e566
3 changed files with 343 additions and 50 deletions

View File

@@ -647,6 +647,13 @@ configuration fixtures not yet converted.
Validation: real-loader tests assert effective behavior and structured diagnostic
identity/paths as appropriate, not complete upstream error wording or ordering.
Completion: loader fixtures now exercise identified lists, inherited records,
strict duplicates, invalid identities and parent references, all six registered
destinations, final identity enforcement, layered upsert/append/replace, and
request completion of partial profiles. The focused real-loader composition,
target, validation, and syntax tests passed on Go 1.27.0. Header and remaining
adapter fixtures are handled in the next assignment.
## Stage 14: Complete Header, Origin, And Adapter Fixture Coverage
Scope: remaining `internal/configuration` prompt, inspection, listing, and

View File

@@ -1,6 +1,7 @@
package configuration
import (
"context"
"errors"
"strings"
"testing"
@@ -33,6 +34,265 @@ func TestLoadIdentifiedResourceLists(t *testing.T) {
}
}
func TestIdentifiedResourcesComposeAcrossNamespacesAndKinds(t *testing.T) {
resources := func() map[string]any {
return map[string]any{
"backends": []any{
map[string]any{"id": "shared", "endpoint": "https://example.invalid/v1"},
map[string]any{"id": "child", "extends": map[string]any{"id": "shared"}},
},
"profiles": []any{
map[string]any{"id": "shared", "model": "model"},
map[string]any{"id": "child", "extends": map[string]any{"id": "shared"}},
},
"prompts": []any{
map[string]any{"id": "shared", "messages": []any{map[string]any{"role": "user", "content": "inherited"}},
"output": map[string]any{"format": "text", "validation_mode": "basic"}},
map[string]any{"id": "child", "extends": map[string]any{"id": "shared"}},
},
}
}
values := resources()
values["collections"] = map[string]any{"*": resources(), "123": resources()}
state, err := load(mapping("identified namespaces", values), nil)
if err != nil {
t.Fatal(err)
}
for _, prefix := range []string{"", "*/", "123/"} {
backend, err := state.registry.GetBackend(prefix + "child")
if err != nil || backend.ID != prefix+"child" || backend.Endpoint != "https://example.invalid/v1" {
t.Fatalf("inherited backend %q = %+v, %v", prefix, backend, err)
}
profile, err := state.GetProfileIdentity(context.Background(), prefix+"child")
if err != nil || profile != prefix+"child" {
t.Fatalf("inherited profile %q = %q, %v", prefix, profile, err)
}
definition, _, err := state.prompt(prefix + "child")
if err != nil || definition.ID != prefix+"child" || len(definition.Templates) != 1 || definition.Templates[0].Content != "inherited" {
t.Fatalf("inherited prompt %q = %+v, %v", prefix, definition, err)
}
}
}
func TestIdentifiedResourcesRejectInvalidInheritance(t *testing.T) {
for _, kind := range []string{"backends", "profiles", "prompts"} {
for name, records := range map[string][]any{
"missing": {map[string]any{"id": "child", "extends": map[string]any{"id": "missing"}}},
"self": {map[string]any{"id": "child", "extends": map[string]any{"id": "child"}}},
"cycle": {
map[string]any{"id": "first", "extends": map[string]any{"id": "second"}},
map[string]any{"id": "second", "extends": map[string]any{"id": "first"}},
},
} {
t.Run(kind+"/"+name, func(t *testing.T) {
_, err := load(mapping("invalid inheritance", map[string]any{kind: records}), nil)
var loadErr *configkit.LoadError
if !errors.As(err, &loadErr) {
t.Fatalf("load error = %v, want an upstream inheritance diagnostic", err)
}
for _, diagnostic := range loadErr.Diagnostics() {
if diagnostic.Code == configkit.CodeInheritanceMissing || diagnostic.Code == configkit.CodeInheritanceCycle {
return
}
}
t.Fatalf("missing inheritance diagnostic: %+v", loadErr.Diagnostics())
})
}
}
}
func TestIdentifiedResourcesRejectInvalidLocalIDs(t *testing.T) {
for _, kind := range []string{"backends", "profiles", "prompts"} {
for _, test := range []struct {
name string
record map[string]any
}{
{name: "missing", record: map[string]any{}},
{name: "null", record: map[string]any{"id": nil}},
{name: "non-string", record: map[string]any{"id": 42}},
{name: "blank", record: map[string]any{"id": " "}},
{name: "slash", record: map[string]any{"id": "not/local"}},
} {
t.Run(kind+"/"+test.name, func(t *testing.T) {
_, err := load(mapping("invalid resource ID", map[string]any{kind: []any{test.record}}), nil)
var loadErr *configkit.LoadError
if !errors.As(err, &loadErr) || len(loadErr.Diagnostics()) == 0 {
t.Fatalf("load error = %v, want a path-aware error", err)
}
})
}
}
}
func TestIdentifiedResourcesRejectDuplicateStrictPeers(t *testing.T) {
for _, kind := range []string{"backends", "profiles", "prompts"} {
for _, namespace := range []string{"", "*"} {
t.Run(kind+"/"+namespace, func(t *testing.T) {
values := func() map[string]any {
records := []any{map[string]any{"id": "duplicate"}}
if namespace == "" {
return map[string]any{kind: records}
}
return map[string]any{"collections": map[string]any{namespace: map[string]any{kind: records}}}
}
_, err := load(configkit.Input{Source: configkit.NoSource()}, []configkit.Underlay{{Inputs: []configkit.Input{
mapping("first", values()), mapping("second", values()),
}}})
var loadErr *configkit.LoadError
if !errors.As(err, &loadErr) {
t.Fatalf("load error = %v, want an upstream duplicate diagnostic", err)
}
for _, diagnostic := range loadErr.Diagnostics() {
if diagnostic.Code == configkit.CodeComposeConflict {
return
}
}
t.Fatalf("missing duplicate conflict: %+v", loadErr.Diagnostics())
})
}
}
}
func TestFinalIdentitiesAreCheckedAfterApplicationResolution(t *testing.T) {
for _, kind := range []string{"backends", "profiles", "prompts"} {
for _, namespace := range []string{"", "*"} {
t.Run(kind+"/"+namespace, func(t *testing.T) {
definition := configurationDefinition(&loaded{})
definition.Resolve = func(config *document, resolution *configkit.Resolution) error {
path := configkit.Keys(kind)
if namespace == "" {
switch kind {
case "backends":
config.Backends = []backendConfig{{ID: "same"}, {ID: "same"}}
case "profiles":
config.Profiles = []profileConfig{{ID: "same"}, {ID: "same"}}
case "prompts":
config.Prompts = []promptConfig{{ID: "same"}, {ID: "same"}}
}
} else {
collection := collectionConfig{}
switch kind {
case "backends":
collection.Backends = []backendConfig{{ID: "same"}, {ID: "same"}}
case "profiles":
collection.Profiles = []profileConfig{{ID: "same"}, {ID: "same"}}
case "prompts":
collection.Prompts = []promptConfig{{ID: "same"}, {ID: "same"}}
}
config.Collections = map[string]collectionConfig{namespace: collection}
path = configkit.Keys("collections", namespace, kind)
}
resolution.RecordNormalization(path, "supply resolved records")
return nil
}
input := configkit.Input{Source: configkit.NoSource()}
if namespace != "" {
input = mapping("existing collection", map[string]any{"collections": map[string]any{
namespace: map[string]any{kind: []any{}},
}})
}
_, err := configkit.LoadLayered(input, configkit.LayeredOptions[document]{Definition: definition})
var loadErr *configkit.LoadError
if !errors.As(err, &loadErr) {
t.Fatalf("load error = %v, want a final identity diagnostic", err)
}
for _, diagnostic := range loadErr.Diagnostics() {
if diagnostic.Code == configkit.CodeSequenceConflict {
return
}
}
t.Fatalf("missing final identity conflict: %+v", loadErr.Diagnostics())
})
}
}
}
func TestIdentifiedResourceLayerOperations(t *testing.T) {
base := mapping("base profiles", map[string]any{"profiles": []any{
map[string]any{"id": "first", "model": "original", "service_tier": "standard"},
map[string]any{"id": "second", "model": "retained"},
}})
for _, test := range []struct {
name string
mode string
records []any
models map[string]string
}{
{name: "whole record upsert", records: []any{map[string]any{"id": "first", "model": "updated"}}, models: map[string]string{"first": "updated", "second": "retained"}},
{name: "empty upsert", records: []any{}, models: map[string]string{"first": "original", "second": "retained"}},
{name: "append", mode: "append", records: []any{map[string]any{"id": "third", "model": "added"}}, models: map[string]string{"first": "original", "second": "retained", "third": "added"}},
{name: "replace", mode: "replace", records: []any{map[string]any{"id": "third", "model": "replacement"}}, models: map[string]string{"third": "replacement"}},
{name: "clear", mode: "replace", records: []any{}, models: map[string]string{}},
} {
t.Run(test.name, func(t *testing.T) {
values := map[string]any{"profiles": test.records}
if test.mode != "" {
values["config"] = map[string]any{"sequences": []any{map[string]any{
"destination": []any{"profiles"}, "mode": test.mode,
}}}
}
state, err := load(mapping("overlay profiles", values), []configkit.Underlay{{Inputs: []configkit.Input{base}}})
if err != nil {
t.Fatal(err)
}
profiles := indexedProfiles(&state.result.Config)
if len(profiles) != len(test.models) {
t.Fatalf("profiles = %+v, want IDs and models %+v", profiles, test.models)
}
for id, model := range test.models {
profile, ok := profiles[id]
if !ok || profile.Model == nil || *profile.Model != model {
t.Fatalf("profile %q = %+v, want model %q", id, profile, model)
}
}
if test.name == "whole record upsert" && profiles["first"].ServiceTier != nil {
t.Fatalf("upsert retained a displaced field: %+v", profiles["first"])
}
})
}
}
func TestIdentifiedResourceLayersRejectDisplacedParentAndDuplicateAppend(t *testing.T) {
base := mapping("base", map[string]any{"profiles": []any{
map[string]any{"id": "shared", "model": "original"},
}})
for _, test := range []struct {
name string
values map[string]any
code configkit.Code
}{
{
name: "self extension cannot recover displaced record",
values: map[string]any{"profiles": []any{
map[string]any{"id": "shared", "extends": map[string]any{"id": "shared"}},
}},
code: configkit.CodeInheritanceCycle,
},
{
name: "append cannot duplicate an identity",
values: map[string]any{
"config": map[string]any{"sequences": []any{map[string]any{"destination": []any{"profiles"}, "mode": "append"}}},
"profiles": []any{map[string]any{"id": "shared", "model": "other"}},
},
code: configkit.CodeSequenceConflict,
},
} {
t.Run(test.name, func(t *testing.T) {
_, err := load(mapping("overlay", test.values), []configkit.Underlay{{Inputs: []configkit.Input{base}}})
var loadErr *configkit.LoadError
if !errors.As(err, &loadErr) {
t.Fatalf("load error = %v, want structured diagnostic", err)
}
for _, diagnostic := range loadErr.Diagnostics() {
if diagnostic.Code == test.code {
return
}
}
t.Fatalf("missing %s diagnostic: %+v", test.code, loadErr.Diagnostics())
})
}
}
func TestLoadChecksOptionalConfigurationVersion(t *testing.T) {
for _, test := range []struct {
name string
@@ -97,7 +357,7 @@ func TestLoadConsumesAcceptedUnderlayVersionAndValidatesHeaderlessPayload(t *tes
}
invalidFragment := mapping("headerless prompt fragment", map[string]any{
"prompts": map[string]any{"incomplete": map[string]any{"description": "still validated"}},
"prompts": []any{map[string]any{"id": "incomplete", "description": "still validated"}},
})
if _, err := load(configkit.Input{Source: configkit.NoSource()}, []configkit.Underlay{{Inputs: []configkit.Input{invalidFragment}}}); err == nil || !strings.Contains(err.Error(), "at least one message is required") {
t.Fatalf("headerless fragment validation error = %v, want final prompt validation", err)
@@ -106,30 +366,25 @@ func TestLoadConsumesAcceptedUnderlayVersionAndValidatesHeaderlessPayload(t *tes
func TestLoadComposesLiteralKeysAndEffectivePresence(t *testing.T) {
base := mapping("defaults", map[string]any{
"version": int64(1),
"backends": map[string]any{
"local.v1": map[string]any{"endpoint": "http://localhost:8080/v1", "concurrency_limit": 2},
},
"version": int64(2),
"backends": []any{map[string]any{"id": "local.v1", "endpoint": "http://localhost:8080/v1", "concurrency_limit": 2}},
"collections": map[string]any{"base": map[string]any{
"release_version": "",
"backends": map[string]any{
"local.v1": map[string]any{"endpoint": "http://localhost:8080/v1", "concurrency_limit": 3},
},
"profiles": map[string]any{
"one": map[string]any{"backend": "local.v1", "temperature": 0.8, "top_p": 0.9, "api_key_required": true,
"backends": []any{map[string]any{"id": "local.v1", "endpoint": "http://localhost:8080/v1", "concurrency_limit": 3}},
"profiles": []any{
map[string]any{"id": "one", "backend": "local.v1", "temperature": 0.8, "top_p": 0.9, "api_key_required": true,
"extra_params": map[string]any{"provider": map[string]any{"first": 1, "second": 2}}},
"child.v1": map[string]any{"extends": "one"},
"namespaced": map[string]any{"backend": "base/local.v1", "model": "collection-model"},
map[string]any{"id": "child.v1", "extends": map[string]any{"id": "one"}},
map[string]any{"id": "namespaced", "backend": "base/local.v1", "model": "collection-model"},
},
}, "invoice": map[string]any{
"release_version": "r7",
"prompts": map[string]any{
"summary": map[string]any{
"version": "v1.0",
"prompts": []any{
map[string]any{"id": "summary",
"messages": []any{map[string]any{"role": "user", "content": "Summarize."}},
"output": map[string]any{"format": "text", "validation_mode": "basic"},
},
"version": map[string]any{
map[string]any{"id": "version",
"messages": []any{map[string]any{"role": "user", "content": "Nested ID."}},
"output": map[string]any{"format": "text", "validation_mode": "basic"},
},
@@ -137,19 +392,23 @@ func TestLoadComposesLiteralKeysAndEffectivePresence(t *testing.T) {
}},
})
overlay := mapping("operator", map[string]any{
"backends": map[string]any{"local.v1": map[string]any{"queue_capacity": 0}},
"collections": map[string]any{"base": map[string]any{"profiles": map[string]any{"child.v1": map[string]any{
"backends": []any{map[string]any{"id": "local.v1", "endpoint": "http://localhost:8080/v1", "concurrency_limit": 2, "queue_capacity": 0}},
"collections": map[string]any{"base": map[string]any{"profiles": []any{map[string]any{"id": "child.v1", "extends": map[string]any{"id": "one"},
"temperature": 0, "top_p": nil, "api_key_required": false,
"extra_params": map[string]any{"provider": map[string]any{"second": 3}},
}}}},
})
loaded, err := load(mapping("main", map[string]any{"version": "1"}), []configkit.Underlay{
loaded, err := load(mapping("main", map[string]any{"version": "2"}), []configkit.Underlay{
{Inputs: []configkit.Input{base}}, {Inputs: []configkit.Input{overlay}},
})
if err != nil {
var loadErr *configkit.LoadError
if errors.As(err, &loadErr) {
t.Fatalf("load: %v; diagnostics: %+v", err, loadErr.Diagnostics())
}
t.Fatal(err)
}
profile := loaded.result.Config.Collections["base"].Profiles["child.v1"]
profile := loaded.result.Config.Collections["base"].Profiles[1]
if profile.Temperature == nil || *profile.Temperature != 0 || profile.TopP != nil || profile.APIKeyRequired == nil || *profile.APIKeyRequired {
t.Fatalf("effective values were not retained: %+v", profile)
}
@@ -160,7 +419,7 @@ func TestLoadComposesLiteralKeysAndEffectivePresence(t *testing.T) {
if provider["first"] != int64(1) || provider["second"] != int64(3) {
t.Fatalf("recursive overlay failed: %+v", provider)
}
backend := loaded.result.Config.Backends["local.v1"]
backend := loaded.result.Config.Backends[0]
if backend.QueueCapacity == nil || *backend.QueueCapacity != 0 || loaded.backends["local.v1"]["queue_capacity"] != fieldValue {
t.Fatalf("explicit zero queue capacity was lost: %+v", backend)
}
@@ -171,10 +430,10 @@ func TestLoadComposesLiteralKeysAndEffectivePresence(t *testing.T) {
if !exists || collectionProfile.ID != "base/namespaced" || collectionProfile.ResolvedTarget == nil || collectionProfile.ResolvedTarget.BackendID != "base/local.v1" {
t.Fatalf("collection profile snapshot = %+v, exists %t", collectionProfile, exists)
}
if loaded.result.Config.Collections["invoice"].Prompts["summary"].Messages[0].Content == nil {
if loaded.result.Config.Collections["invoice"].Prompts[0].Messages[0].Content == nil {
t.Fatal("literal prompt content was not decoded")
}
if loaded.result.Config.Version == nil || *loaded.result.Config.Version != "1" ||
if loaded.result.Config.Version == nil || *loaded.result.Config.Version != "2" ||
loaded.result.Config.Collections["base"].ReleaseVersion == nil || *loaded.result.Config.Collections["base"].ReleaseVersion != "" ||
loaded.result.Config.Collections["invoice"].ReleaseVersion == nil || *loaded.result.Config.Collections["invoice"].ReleaseVersion != "r7" {
t.Fatalf("root or collection version metadata was not retained: %+v", loaded.result.Config)
@@ -197,20 +456,20 @@ func TestLoadRejectsInvalidCollectionAndResourceKeys(t *testing.T) {
},
{
name: "root resource with separator",
values: map[string]any{"backends": map[string]any{
"bad/name": map[string]any{"endpoint": "https://example.test/v1"},
values: map[string]any{"backends": []any{
map[string]any{"id": "bad/name", "endpoint": "https://example.test/v1"},
}},
message: "backend key must be a nonblank local key without a slash",
message: "backend ID must be a nonblank local key without a slash",
},
{
name: "collection resource with separator",
values: map[string]any{"collections": map[string]any{"good": map[string]any{
"prompts": map[string]any{"bad/name": map[string]any{
"prompts": []any{map[string]any{"id": "bad/name",
"messages": []any{map[string]any{"role": "user", "content": "Hello."}},
"output": map[string]any{"format": "text", "validation_mode": "basic"},
}},
}}},
message: "prompt key must be a nonblank local key without a slash",
message: "prompt ID must be a nonblank local key without a slash",
},
} {
t.Run(test.name, func(t *testing.T) {
@@ -267,17 +526,17 @@ func TestLoadBackendSmokeTestsOmissionAndNull(t *testing.T) {
{name: "null", smokeTests: nil, include: true, inherited: true},
} {
t.Run(test.name, func(t *testing.T) {
backend := map[string]any{"endpoint": "https://backend.example/v1"}
backend := map[string]any{"id": "local", "endpoint": "https://backend.example/v1"}
if test.include {
backend["smoke_tests"] = test.smokeTests
}
main := mapping("backend", map[string]any{
"backends": map[string]any{"local": backend},
"backends": []any{backend},
})
var underlays []configkit.Underlay
if test.inherited {
underlays = []configkit.Underlay{{Inputs: []configkit.Input{mapping("defaults", map[string]any{
"backends": map[string]any{"local": map[string]any{
"backends": []any{map[string]any{"id": "local",
"endpoint": "https://backend.example/v1",
"smoke_tests": map[string]any{"default_profile": "inherited-profile"},
}},
@@ -287,7 +546,7 @@ func TestLoadBackendSmokeTestsOmissionAndNull(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if got := loaded.result.Config.Backends["local"].SmokeTests; got != nil {
if got := loaded.result.Config.Backends[0].SmokeTests; got != nil {
t.Fatalf("smoke_tests = %+v, want nil", got)
}
selected, err := loaded.registry.GetBackend("local")
@@ -303,7 +562,7 @@ func TestLoadBackendSmokeTestsOmissionAndNull(t *testing.T) {
func TestLoadMergesBackendSmokeTestsAndRetainsFallbacks(t *testing.T) {
base := mapping("defaults", map[string]any{
"backends": map[string]any{"local": map[string]any{
"backends": []any{map[string]any{"id": "catalog",
"endpoint": "https://backend.example/v1",
"smoke_tests": map[string]any{
"default_profile": "catalog-profile",
@@ -316,7 +575,7 @@ func TestLoadMergesBackendSmokeTestsAndRetainsFallbacks(t *testing.T) {
}},
})
overlay := mapping("operator", map[string]any{
"backends": map[string]any{"local": map[string]any{
"backends": []any{map[string]any{"id": "local", "extends": map[string]any{"id": "catalog"},
"smoke_tests": map[string]any{
"default_profile": "not-yet-listed",
"authentication": map[string]any{"kind": " NONE ", "endpoint": nil},
@@ -360,37 +619,37 @@ func TestLoadRejectsInvalidFinalBackendSmokeTests(t *testing.T) {
{
name: "blank default profile",
data: map[string]any{"default_profile": " \t "},
path: "/backends/local/smoke_tests/default_profile",
path: "/backends/0/smoke_tests/default_profile",
},
{
name: "authentication kind required",
data: map[string]any{"authentication": map[string]any{}},
path: "/backends/local/smoke_tests/authentication/kind",
path: "/backends/0/smoke_tests/authentication/kind",
},
{
name: "unknown authentication kind",
data: map[string]any{"authentication": map[string]any{"kind": "bearer"}},
path: "/backends/local/smoke_tests/authentication/kind",
path: "/backends/0/smoke_tests/authentication/kind",
},
{
name: "non-http reachability URL",
data: map[string]any{"reachability": map[string]any{"endpoint": "ftp://probe.example/ready"}},
path: "/backends/local/smoke_tests/reachability/endpoint",
path: "/backends/0/smoke_tests/reachability/endpoint",
},
{
name: "blank authentication URL",
data: map[string]any{"authentication": map[string]any{"kind": "none", "endpoint": " "}},
path: "/backends/local/smoke_tests/authentication/endpoint",
path: "/backends/0/smoke_tests/authentication/endpoint",
},
{
name: "relative authentication URL",
data: map[string]any{"authentication": map[string]any{"kind": "none", "endpoint": "/key"}},
path: "/backends/local/smoke_tests/authentication/endpoint",
path: "/backends/0/smoke_tests/authentication/endpoint",
},
} {
t.Run(test.name, func(t *testing.T) {
_, err := load(mapping("backend", map[string]any{
"backends": map[string]any{"local": map[string]any{
"backends": []any{map[string]any{"id": "local",
"endpoint": "https://backend.example/v1",
"smoke_tests": test.data,
}},
@@ -455,33 +714,33 @@ func TestLoadRejectsStrictGroupConflict(t *testing.T) {
func TestLoadValidatesOnlyFinalDomainValues(t *testing.T) {
underlay := mapping("defaults", map[string]any{
"backends": map[string]any{"local": map[string]any{"endpoint": "not a URL"}},
"profiles": map[string]any{"partial": map[string]any{"backend": "local"}},
"backends": []any{map[string]any{"id": "local", "endpoint": "not a URL"}},
"profiles": []any{map[string]any{"id": "partial", "backend": "local"}},
})
main := mapping("operator", map[string]any{"backends": map[string]any{"local": map[string]any{"endpoint": "http://localhost:8080/v1"}}})
main := mapping("operator", map[string]any{"backends": []any{map[string]any{"id": "local", "endpoint": "http://localhost:8080/v1"}}})
loaded, err := load(main, []configkit.Underlay{{Inputs: []configkit.Input{underlay}}})
if err != nil {
t.Fatalf("replaced lower-layer domain value should not fail: %v", err)
}
if loaded.result.Config.Profiles["partial"].Model != nil {
if loaded.result.Config.Profiles[0].Model != nil {
t.Fatal("unused partial profile unexpectedly gained a model")
}
_, err = load(configkit.Input{Source: configkit.NoSource()}, []configkit.Underlay{{Inputs: []configkit.Input{
mapping("invalid", map[string]any{"backends": map[string]any{"unused": map[string]any{"endpoint": "not a URL"}}}),
mapping("invalid", map[string]any{"backends": []any{map[string]any{"id": "unused", "endpoint": "not a URL"}}}),
}}})
var loadError *configkit.LoadError
if !errors.As(err, &loadError) {
t.Fatalf("expected path-aware effective backend failure, got %v", err)
}
if diagnostics := loadError.Diagnostics(); len(diagnostics) != 1 || diagnostics[0].Path.String() != "/backends/unused/endpoint" {
if diagnostics := loadError.Diagnostics(); len(diagnostics) != 1 || diagnostics[0].Path.String() != "/backends/0/endpoint" {
t.Fatalf("expected endpoint diagnostic, got %+v", diagnostics)
}
}
func TestLoadValidatesOnlyFinalBackendSmokeTestValues(t *testing.T) {
underlay := mapping("defaults", map[string]any{
"backends": map[string]any{"local": map[string]any{
"backends": []any{map[string]any{"id": "local",
"endpoint": "https://backend.example/v1",
"smoke_tests": map[string]any{
"default_profile": " ",
@@ -491,7 +750,7 @@ func TestLoadValidatesOnlyFinalBackendSmokeTestValues(t *testing.T) {
}},
})
main := mapping("operator", map[string]any{
"backends": map[string]any{"local": map[string]any{
"backends": []any{map[string]any{"id": "local", "endpoint": "https://backend.example/v1",
"smoke_tests": map[string]any{
"default_profile": "dangling-profile",
"reachability": map[string]any{"endpoint": nil},
@@ -514,7 +773,7 @@ func TestLoadValidatesOnlyFinalBackendSmokeTestValues(t *testing.T) {
}
func TestLoadKeepsSyntaxErrorsFromLowerTiers(t *testing.T) {
_, err := load(mapping("operator", map[string]any{"backends": map[string]any{"local": map[string]any{"endpoint": "http://localhost:8080"}}}),
_, err := load(mapping("operator", map[string]any{"backends": []any{map[string]any{"id": "local", "endpoint": "http://localhost:8080"}}}),
[]configkit.Underlay{{Inputs: []configkit.Input{{Source: configkit.Bytes("broken", []byte("backends: ["))}}}})
var loadError *configkit.LoadError
if !errors.As(err, &loadError) {

View File

@@ -13,6 +13,8 @@ import (
"gitea.maximumdirect.net/eric/promptkit/internal/domain"
"gitea.maximumdirect.net/eric/promptkit/internal/llm"
profilepkg "gitea.maximumdirect.net/eric/promptkit/internal/profile"
"gitea.maximumdirect.net/eric/promptkit/internal/prompt"
"gitea.maximumdirect.net/eric/promptkit/internal/usecase"
)
func TestLoadIndexesIdentifiedTargets(t *testing.T) {
@@ -40,6 +42,31 @@ func TestLoadIndexesIdentifiedTargets(t *testing.T) {
}
}
func TestRequestCompletesLoadedPartialProfile(t *testing.T) {
state, err := load(mapping("partial profile", map[string]any{
"profiles": []any{map[string]any{"id": "partial"}},
"prompts": []any{map[string]any{
"id": "example", "messages": []any{map[string]any{"role": "user", "content": "hello"}},
"output": map[string]any{"format": "text", "validation_mode": "basic"},
}},
}), nil)
if err != nil {
t.Fatal(err)
}
runner := usecase.NewRunner(state, state, nil, prompt.NewGoRenderer(), nil, nil, nil)
prepared, err := runner.Prepare(context.Background(), domain.RunRequest{
PromptID: "example", ProfileID: "partial",
Execution: &domain.ExecutionTargetOverride{Endpoint: "https://example.invalid/v1", Model: "request-model"},
})
if err != nil {
t.Fatal(err)
}
if prepared.SelectedProfileID != "partial" || prepared.EffectiveModelParams.Endpoint != "https://example.invalid/v1" ||
prepared.EffectiveModelParams.Model != "request-model" {
t.Fatalf("request did not complete the loaded profile: %+v", prepared)
}
}
func TestLoadBuildsEffectiveTargetsAfterInheritance(t *testing.T) {
state, err := load(mapping("effective-targets", map[string]any{
"backends": []any{