package engine import ( "testing" "go.maximumdirect.net/configkit/internal/document" ) type historyBudgetSimpleConfig struct { Value string } type historyBudgetRecord struct { Value string Credential Secret } type historyBudgetLayeredConfig struct { Parent historyBudgetRecord Child historyBudgetRecord } func retainedInspectionNodeCountForTest(inspection *Inspection) int { seen := make(map[*document.Node]struct{}) model := inspection.history stack := []*document.Node{model.baseline, model.final, inspection.final} for _, payload := range model.sourcePayloads { if payload.kind == historySourceApplicationPayload { stack = append(stack, payload.application.value) } } for _, payload := range model.inheritancePayloads { for _, operation := range payload.operations { stack = append(stack, operation.parent, operation.effective) } } for _, payload := range model.cliPayloads { if payload.kind == historySourceApplicationPayload { stack = append(stack, payload.application.value) } } if model.preCLICheckpoint != nil { stack = append(stack, model.preCLICheckpoint.root) } if model.postCLICheckpoint != nil { stack = append(stack, model.postCLICheckpoint.root) } if model.resolutionPayload != nil { for _, snapshot := range model.resolutionPayload.snapshots { stack = append(stack, snapshot.before, snapshot.after) } } for len(stack) != 0 { last := len(stack) - 1 node := stack[last] stack = stack[:last] if node == nil { continue } if _, exists := seen[node]; exists { continue } seen[node] = struct{}{} for _, entry := range node.Mapping { stack = append(stack, entry.Value) } stack = append(stack, node.Sequence...) } return len(seen) } func TestLoadHistoryBudgetUsesExactRetainedNodeCount(t *testing.T) { load := func(historyLimit int, validations *int) (*Loaded[historyBudgetSimpleConfig], error) { return loadWithSecretLookupLimit( Bytes("main", []byte("value: retained\n")), testSecretBinding(), func(string) (string, bool) { return "", false }, historyLimit, Options[historyBudgetSimpleConfig]{Definition: Definition[historyBudgetSimpleConfig]{ Validate: func(*historyBudgetSimpleConfig, *Validation) { *validations++ }, }}, ) } var baselineValidations int baseline, err := load(10000, &baselineValidations) if err != nil { t.Fatalf("baseline load: %v", err) } want := retainedInspectionNodeCountForTest(baseline.Inspection) if want == 0 { t.Fatal("independent retained-tree count was empty") } var exactValidations int loaded, err := load(want, &exactValidations) if err != nil || loaded == nil { t.Fatalf("load at exact retained-node count %d: result=%v error=%v", want, loaded, err) } if got := retainedInspectionNodeCountForTest(loaded.Inspection); got != want { t.Fatalf("retained node count = %d, want %d", got, want) } if exactValidations != 1 { t.Fatalf("validation calls at exact count = %d, want 1", exactValidations) } var rejectedValidations int loaded, err = load(want-1, &rejectedValidations) if loaded != nil || !hasHistoryLimitDiagnostic(t, err) { t.Fatalf("load below retained-node count: result=%v error=%v", loaded, err) } if rejectedValidations != 0 { t.Fatalf("validation ran before history rejection: %d calls", rejectedValidations) } } func TestHistoryNodeBudgetIncludesFinalInspectionProjection(t *testing.T) { final := &document.Node{Kind: document.Mapping, Mapping: []document.Entry{{ Key: "value", Value: &document.Node{Kind: document.String, Text: "final"}, }}} builder := newHistoryBuilder() model := builder.freeze() inspection := &Inspection{history: model, metadata: Metadata{historyModel: model}, final: final} counter := newRetainedNodeCounter(2) admitted := addInspectionHistory(counter, inspection) if !admitted || counter.count != 2 { t.Fatalf("final inspection projection was not counted exactly: admitted=%t count=%d", admitted, counter.count) } counter = newRetainedNodeCounter(1) if addInspectionHistory(counter, inspection) { t.Fatal("final inspection projection did not consume the node budget") } } func TestLayeredHistoryBudgetRejectsBeforeSecretsAndValidation(t *testing.T) { type callbackCounts struct { lookups int validations int } makeRequest := func(counts *callbackCounts) loadRequest[historyBudgetLayeredConfig] { return loadRequest[historyBudgetLayeredConfig]{ main: loadInput{source: Bytes("main", []byte("child:\n extends: parent\n"))}, underlays: []loadGroup{{inputs: []loadInput{{source: Bytes("underlay", []byte( "parent:\n value: inherited\n credential: HISTORY_BUDGET_SECRET\n", ))}}}}, overrides: []Override{{Path: Keys("child", "value"), Value: "cli", Flag: "--child-value"}}, definition: Definition[historyBudgetLayeredConfig]{ Resolve: func(configuration *historyBudgetLayeredConfig, resolution *Resolution) error { configuration.Child.Value += "-resolved" resolution.RecordNormalization(Keys("child", "value"), "normalize child") resolution.RecordDerivedDefault(Keys("child"), "record enclosing child state") return nil }, Validate: func(*historyBudgetLayeredConfig, *Validation) { counts.validations++ }, }, } } lookup := func(counts *callbackCounts) secretLookup { return func(name string) (string, bool) { counts.lookups++ if name != "HISTORY_BUDGET_SECRET" { t.Errorf("secret lookup name = %q", name) } return "resolved-secret", true } } baselineCounts := &callbackCounts{} baseline, err := loadGroupedWithSecretLookupLimit(makeRequest(baselineCounts), testSecretBinding(), lookup(baselineCounts), 10000) if err != nil { t.Fatalf("baseline grouped load: %v", err) } want := retainedInspectionNodeCountForTest(baseline.Inspection) if want == 0 { t.Fatal("independent retained-tree count was empty") } if baseline.Inspection.history == nil || baseline.Inspection.metadata.historyModel != baseline.Inspection.history || len(baseline.Inspection.history.inheritancePayloads) == 0 { t.Fatal("layered load did not publish its shared inheritance evidence owner") } resolution := baseline.Inspection.history.resolutionPayload if resolution == nil || len(resolution.snapshots) != 2 || len(resolution.replayGroups) == 0 { t.Fatalf("layered load did not retain overlapping original resolution evidence: %#v", resolution) } resolutionPaths := make(map[string]bool, len(resolution.snapshots)) for _, snapshot := range resolution.snapshots { resolutionPaths[snapshot.change.Path.String()] = true } if !resolutionPaths["/child"] || !resolutionPaths["/child/value"] { t.Fatalf("layered load resolution snapshots have paths %v, want /child and /child/value", resolutionPaths) } group := resolution.replayGroups[0] groupRecords := make(map[int]bool, len(group.originalRecordIDs)) for _, id := range group.originalRecordIDs { groupRecords[id] = true } if len(groupRecords) != 2 || !groupRecords[0] || !groupRecords[1] || group.change.Path.String() != "/child" { t.Fatalf("layered load did not group both overlapping original records: %#v", group) } exactCounts := &callbackCounts{} loaded, err := loadGroupedWithSecretLookupLimit(makeRequest(exactCounts), testSecretBinding(), lookup(exactCounts), want) if err != nil || loaded == nil { t.Fatalf("grouped load at exact retained-node count %d: result=%v error=%v", want, loaded, err) } if got := retainedInspectionNodeCountForTest(loaded.Inspection); got != want { t.Fatalf("grouped retained node count = %d, want %d", got, want) } if loaded.Config.Child.Value != "cli-resolved" || exactCounts.lookups != 1 || exactCounts.validations != 1 { t.Fatalf("grouped lifecycle result=%#v callbacks=%#v", loaded.Config, exactCounts) } rejectedCounts := &callbackCounts{} loaded, err = loadGroupedWithSecretLookupLimit(makeRequest(rejectedCounts), testSecretBinding(), lookup(rejectedCounts), want-1) if loaded != nil || !hasHistoryLimitDiagnostic(t, err) { t.Fatalf("grouped load below retained-node count: result=%v error=%v", loaded, err) } if rejectedCounts.lookups != 0 || rejectedCounts.validations != 0 { t.Fatalf("callbacks ran before history rejection: %#v", rejectedCounts) } } func TestPreparedInheritanceEvidenceSharesOwnerAndDetachesPublicViews(t *testing.T) { input := parseCompositionDocument(t, "inheritance", "parent: {value: shared}\nchild: {extends: parent}\n") expanded, diagnostics := expandInheritanceWithOrigins(input, nil, defaultProjectionLimits()) if len(diagnostics) != 0 { t.Fatal(diagnostics) } baseline := &document.Node{Kind: document.Mapping} builder := newHistoryBuilder() builder.observeBaseline(baseline) builder.setScratch(input) builder.observeInheritanceEvidence(expanded.operations) builder.observePreCLICheckpoint(expanded.root, expanded.origins) builder.observePostCLICheckpoint(expanded.root, expanded.origins) builder.prefixReady = true metadata := Metadata{historyBuilder: builder} resolved := resolvedLoad[historyBudgetSimpleConfig]{ metadata: metadata, final: expanded.root, } counter := newRetainedNodeCounter(100) inspection, ok := prepareInspectionHistory(resolved, counter) if !ok { t.Fatal("preparation rejected the shared evidence owner") } if inspection.history == nil || inspection.metadata.historyModel != inspection.history || len(inspection.history.inheritancePayloads) != 1 { t.Fatalf("history owners = inspection %p, metadata %p, inheritance payloads %d", inspection.history, inspection.metadata.historyModel, len(inspection.history.inheritancePayloads)) } path := Keys("child", "value") first := inspection.Metadata().History(path) if len(first) == 0 { t.Fatal("metadata projection omitted inherited history") } first[0].Origin.Locations[0].SourceID = "mutated metadata result" first[0].Dependencies[0].segments[0].key = "mutated metadata dependency" if explanation, found := inspection.Explain(path); !found || len(explanation.History) == 0 || explanation.History[0].Origin.Locations[0].SourceID == "mutated metadata result" { t.Fatalf("metadata result mutation leaked into explanation: %#v, %v", explanation, found) } explanation, _ := inspection.Explain(path) explanation.History[0].Origin.Locations[0].SourceID = "mutated explanation result" second := inspection.Metadata().History(path) if second[0].Origin.Locations[0].SourceID == "mutated explanation result" || second[0].Dependencies[0].String() == "/mutated metadata dependency" { t.Fatalf("explanation mutation leaked into metadata: %#v", second) } } func hasHistoryLimitDiagnostic(t *testing.T, err error) bool { t.Helper() if err == nil { return false } loadErr, ok := err.(*LoadError) if !ok { t.Fatalf("error type = %T, want *LoadError", err) } for _, diagnostic := range loadErr.Diagnostics() { if diagnostic.Code == CodeHistoryLimitExceeded { return true } } return false }