211 lines
7.6 KiB
Go
211 lines
7.6 KiB
Go
package engine
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"gitea.maximumdirect.net/eric/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{})
|
|
stack := []*document.Node{inspection.baseline, inspection.input, inspection.final, inspection.preCLI}
|
|
for _, application := range inspection.applications {
|
|
stack = append(stack, application.value)
|
|
}
|
|
for _, application := range inspection.postDecodeApps {
|
|
stack = append(stack, application.value)
|
|
}
|
|
for _, snapshot := range inspection.resolution {
|
|
stack = append(stack, snapshot.before, snapshot.after)
|
|
}
|
|
for _, snapshot := range inspection.resolutionReplay {
|
|
stack = append(stack, snapshot.before, snapshot.after)
|
|
}
|
|
for _, operation := range inspection.inheritance {
|
|
stack = append(stack, operation.parent, operation.effective)
|
|
}
|
|
for _, operation := range inspection.metadata.inheritance {
|
|
stack = append(stack, operation.parent, operation.effective)
|
|
}
|
|
|
|
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 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.Record(Keys("child", "value"), ChangeNormalization, "normalize child")
|
|
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 len(baseline.Inspection.inheritance) == 0 || len(baseline.Inspection.metadata.inheritance) == 0 {
|
|
t.Fatal("layered load did not retain both inheritance evidence copies")
|
|
}
|
|
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 TestPreparedInheritanceEvidenceOwnsDistinctTrees(t *testing.T) {
|
|
root := &document.Node{Kind: document.Mapping, Mapping: []document.Entry{{Key: "value", Value: &document.Node{Kind: document.String, Text: "shared"}}}}
|
|
resolved := resolvedLoad[historyBudgetSimpleConfig]{
|
|
inheritance: &inheritanceScope{operations: []inheritanceOperation{{parent: root, effective: root}}},
|
|
}
|
|
counter := newRetainedNodeCounter(8)
|
|
inspection, ok := prepareInspectionHistory(resolved, counter)
|
|
if !ok {
|
|
t.Fatal("preparation rejected the exact size of the distinct retained copies")
|
|
}
|
|
if len(inspection.inheritance) != 1 || len(inspection.metadata.inheritance) != 1 {
|
|
t.Fatalf("inheritance copies = inspection %#v, metadata %#v", inspection.inheritance, inspection.metadata.inheritance)
|
|
}
|
|
inspectionOperation := inspection.inheritance[0]
|
|
metadataOperation := inspection.metadata.inheritance[0]
|
|
if inspectionOperation.parent == metadataOperation.parent || inspectionOperation.effective == metadataOperation.effective || counter.count != 8 {
|
|
t.Fatalf("separate inheritance copies were not counted independently: inspection=(%p, %p) metadata=(%p, %p) count=%d", inspectionOperation.parent, inspectionOperation.effective, metadataOperation.parent, metadataOperation.effective, counter.count)
|
|
}
|
|
}
|
|
|
|
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 == CodeExplainLimitExceeded {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|