Test normalized configuration inspection and provenance
This commit is contained in:
@@ -81,6 +81,34 @@ func TestConfigurationInspectionDiffIgnoresSourceHistory(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigurationInspectionDiffUsesNormalizedValues(t *testing.T) {
|
||||
inspect := func(endpoint string) promptkit.ConfigurationInspection {
|
||||
t.Helper()
|
||||
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{Source: configkit.Mapping("backend", map[string]any{
|
||||
"backends": []any{map[string]any{"id": "local", "endpoint": endpoint}},
|
||||
})}}}}}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
view, err := engine.InspectConfiguration()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return view
|
||||
}
|
||||
left := inspect(" HTTPS://example.invalid/v1 ")
|
||||
equal := inspect("https://example.invalid/v1")
|
||||
differences, err := left.Diff(equal)
|
||||
if err != nil || len(differences) != 0 {
|
||||
t.Fatalf("normalized diff = %+v, %v", differences, err)
|
||||
}
|
||||
changed := inspect("https://other.invalid/v1")
|
||||
differences, err = left.Diff(changed)
|
||||
if err != nil || len(differences) != 1 || differences[0].Path.String() != "/backends" {
|
||||
t.Fatalf("changed diff = %+v, %v", differences, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigurationInspectionDiffReportsPresenceAndSequences(t *testing.T) {
|
||||
left := comparisonInspectionFrom(t, "before", "same-model", map[string]any{
|
||||
"sequence": []any{"earlier", "unchanged"},
|
||||
|
||||
@@ -21,7 +21,7 @@ func TestConfigurationInspectionReportsLiteralKeysAndRedactedHistory(t *testing.
|
||||
Underlays: []configkit.Underlay{
|
||||
{Inputs: []configkit.Input{{Source: configkit.Mapping("defaults", map[string]any{
|
||||
"backends": []any{map[string]any{
|
||||
"id": "local", "endpoint": "https://example.invalid/v1", "api_key_env": "OPTIONAL_KEY",
|
||||
"id": "local", "endpoint": " HTTPS://example.invalid/v1 ", "api_key_env": "OPTIONAL_KEY",
|
||||
"extra_params": map[string]any{"token": "private-sentinel", "visible": "public-value"},
|
||||
}},
|
||||
"collections": map[string]any{"literal": map[string]any{
|
||||
@@ -64,6 +64,11 @@ func TestConfigurationInspectionReportsLiteralKeysAndRedactedHistory(t *testing.
|
||||
t.Fatalf("literal-key path = %q", inheritedPath)
|
||||
}
|
||||
secretPath := configkit.Keys("backends").Index(0).Key("extra_params").Key("token")
|
||||
endpointPath := configkit.Keys("backends").Index(0).Key("endpoint")
|
||||
endpoint, found := view.Explain(endpointPath)
|
||||
if !found || !strings.Contains(endpoint.Effective.YAML, "https://example.invalid/v1") || strings.Contains(fmt.Sprintf("%+v", view.Metadata().History(endpointPath)), "private-sentinel") {
|
||||
t.Fatalf("normalized endpoint explanation = %+v", endpoint)
|
||||
}
|
||||
secret, found := view.Explain(secretPath)
|
||||
if !found || !secret.Effective.Redacted || strings.Contains(secret.Effective.YAML, "private-sentinel") {
|
||||
t.Fatalf("credential-shaped provider value was not redacted: (%+v, %t)", secret, found)
|
||||
|
||||
@@ -221,6 +221,10 @@ Scope: focused configuration tests and existing public inspection/diff tests.
|
||||
Validation: focused configuration, public inspection/diff, preparation, and
|
||||
execution tests. All new tests use deterministic offline sources/collaborators.
|
||||
|
||||
Completion: focused tests cover recorded target dependencies, imported content
|
||||
origins, invalid identities, normalized-value diffs, and sensitive inspection.
|
||||
Configuration, engine, and public API tests pass on Go 1.27.0.
|
||||
|
||||
## Stage 6: Align Documentation And Verify The Sprint
|
||||
|
||||
Scope: current contract/implementation documentation and final integration.
|
||||
|
||||
@@ -117,3 +117,36 @@ func TestPromptResolutionRecordsMessageFields(t *testing.T) {
|
||||
t.Fatal("null input metadata was not retained")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolutionRecordsTargetDependencies(t *testing.T) {
|
||||
backend := func(id string) map[string]any {
|
||||
return map[string]any{"id": id, "endpoint": " HTTPS://example.invalid/v1 ", "concurrency_limit": 2, "queue_capacity": nil}
|
||||
}
|
||||
state, err := load(mapping("targets", map[string]any{
|
||||
"backends": []any{backend("root")},
|
||||
"collections": map[string]any{"scoped": map[string]any{"backends": []any{backend("local")}}},
|
||||
}), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, base := range []configkit.Path{configkit.Keys("backends").Index(0), configkit.Keys("collections", "scoped", "backends").Index(0)} {
|
||||
endpoint, ok := state.result.Explain(base.Key("endpoint"))
|
||||
if !ok || !strings.Contains(endpoint.Effective.YAML, "https://example.invalid/v1") {
|
||||
t.Fatalf("endpoint explanation: %+v", endpoint)
|
||||
}
|
||||
history := state.result.Metadata().History(base.Key("queue_capacity"))
|
||||
found := false
|
||||
for _, change := range history {
|
||||
if change.Origin.Operation == configkit.ChangeDerivedDefault {
|
||||
for _, dependency := range change.Dependencies {
|
||||
if dependency.String() == base.Key("concurrency_limit").String() {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("missing queue dependency: %+v", history)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +153,50 @@ func TestIdentifiedResourcesRejectDuplicateStrictPeers(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidIdentitiesWithNormalizableFieldsAreRejected(t *testing.T) {
|
||||
for _, kind := range []string{"backends", "profiles", "prompts"} {
|
||||
for _, id := range []string{" ", "bad/id"} {
|
||||
t.Run(kind+"/"+id, func(t *testing.T) {
|
||||
record := map[string]any{"id": id}
|
||||
switch kind {
|
||||
case "backends":
|
||||
record["endpoint"] = " HTTPS://example.invalid/v1 "
|
||||
record["concurrency_limit"] = 1
|
||||
case "profiles":
|
||||
record["service_tier"] = " standard "
|
||||
case "prompts":
|
||||
record["description"] = " padded "
|
||||
}
|
||||
_, err := load(mapping("invalid", map[string]any{kind: []any{record}}), nil)
|
||||
if err == nil || strings.Contains(strings.ToLower(err.Error()), "unrecorded") {
|
||||
t.Fatalf("invalid identity error = %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDuplicateIdentitiesWithNormalizableFieldsAreRejected(t *testing.T) {
|
||||
for _, kind := range []string{"backends", "profiles", "prompts"} {
|
||||
t.Run(kind, func(t *testing.T) {
|
||||
record := map[string]any{"id": "same"}
|
||||
switch kind {
|
||||
case "backends":
|
||||
record["endpoint"] = " HTTPS://example.invalid/v1 "
|
||||
record["concurrency_limit"] = 1
|
||||
case "profiles":
|
||||
record["service_tier"] = " standard "
|
||||
case "prompts":
|
||||
record["description"] = " padded "
|
||||
}
|
||||
_, err := load(mapping("duplicates", map[string]any{kind: []any{record, record}}), nil)
|
||||
if err == nil || strings.Contains(strings.ToLower(err.Error()), "unrecorded") {
|
||||
t.Fatalf("duplicate identity error = %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFinalIdentitiesAreCheckedAfterApplicationResolution(t *testing.T) {
|
||||
for _, kind := range []string{"backends", "profiles", "prompts"} {
|
||||
for _, namespace := range []string{"", "*"} {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
func TestLoadCapturesInheritedImportedContent(t *testing.T) {
|
||||
files := fstest.MapFS{
|
||||
"app/main.yaml": {Data: []byte("config:\n imports:\n - path: ../catalog/base.yaml\n required: true\ncollections:\n docs:\n prompts:\n - id: child\n extends: {id: base}\n other:\n prompts:\n - id: child\n messages:\n - role: user\n content_file: ./body.md\n output:\n format: text\n validation_mode: none\n")},
|
||||
"app/main.yaml": {Data: []byte("config:\n imports:\n - path: ../catalog/base.yaml\n required: true\ncollections:\n docs:\n prompts:\n - id: child\n extends: {id: base}\n description: ' description '\n other:\n prompts:\n - id: child\n messages:\n - role: user\n content_file: ./body.md\n output:\n format: text\n validation_mode: none\n")},
|
||||
"app/body.md": {Data: []byte("Replacement {{.name}}")},
|
||||
"catalog/base.yaml": {Data: []byte("collections:\n docs:\n release_version: r1\n prompts:\n - id: base\n description: ' description '\n session_id: ' session '\n inputs:\n - name: ' document '\n content_type: ' text/plain '\n description: ' document source '\n messages:\n - role: ' USER '\n cache_control:\n type: ' ephemeral '\n ttl: ' 1h '\n content_file: ./body.md\n output:\n format: text\n validation_mode: basic\n")},
|
||||
"catalog/body.md": {Data: []byte("Captured {{.name}}")},
|
||||
|
||||
Reference in New Issue
Block a user