package engine import ( "fmt" "strings" "testing" ) func TestInheritancePolicyIndexKeepsSemanticScopesAndOwnedTemplates(t *testing.T) { policy := collectionPolicy{identityFields: []string{"id"}, identityPresent: true} nested := collectionPolicyScope{} nested.set(Keys("group", "base", "items"), policy) outer := policy record := newCollectionRecordPolicy() record.scope = nested outer.setRecordPolicyAt(0, record) scope := collectionPolicyScope{} scope.set(Keys("records"), outer) scope.set(Keys("numeric", "0", "items"), policy) index := newInheritancePolicyIndex(scope) first := index.localize(Keys("records").Index(0).Key("group")) second := index.localize(Keys("records").Index(0).Key("group")) if len(first.collections) != 1 || len(second.collections) != 1 { t.Fatal("record-owned scope was not localized") } entry := first.collections["/base/items"] entry.policy.identityFields[0] = "changed" if second.collections["/base/items"].policy.identityFields[0] != "id" || nested.collections["/group/base/items"].policy.identityFields[0] != "id" { t.Fatal("localized policy shares mutable template state") } if len(index.localize(Keys("records", "0")).collections) != 0 || len(index.localize(Keys("numeric").Index(0)).collections) != 0 { t.Fatal("mapping keys and sequence indexes were conflated") } if len(index.localize(Keys("numeric", "0")).collections) != 1 { t.Fatal("numeric mapping key did not retain its policy") } left := index.localize(Keys("records")) right := index.localize(Keys("records")) leftOwner := left.collections[""].policy.recordOrder[0] rightOwner := right.collections[""].policy.recordOrder[0] if leftOwner == rightOwner || leftOwner == record.owner || rightOwner == record.owner { t.Fatal("independent templates share a record owner") } } func TestInheritancePolicyIndexReplacesOnlyTheChangedScope(t *testing.T) { scope := collectionPolicyScope{} policy := collectionPolicy{explicitMode: sequenceModeAppend, explicitModePresent: true} for index := range 128 { scope.set(Keys(fmt.Sprintf("group-%03d", index), "pending"), policy) } index := newInheritancePolicyIndex(scope) changed := Keys("group-064") if len(index.absoluteScope(changed).collections) != 1 { t.Fatal("scope includes unrelated groups") } replacement := collectionPolicyScope{} replacement.set(changed.Key("introduced"), policy) index.replace(&scope, changed, replacement) if len(scope.collections) != 128 { t.Fatal("replacement lost unrelated pending declarations") } local := index.localize(changed) if _, found := local.collections["/introduced"]; !found || len(local.collections) != 1 { t.Fatal("retired policy survived or introduced policy was not indexed") } index.replace(&scope, changed, collectionPolicyScope{}) if len(index.localize(changed).collections) != 0 || len(scope.collections) != 127 { t.Fatal("descendant retirement did not update the table and index together") } if len(index.localize(Keys("group-065")).collections) != 1 { t.Fatal("retirement changed another scope") } } func TestInheritanceWideIndependentYamlCollectionScopes(t *testing.T) { var body strings.Builder body.WriteString("configkit:\n sequences:\n") for index := range 64 { fmt.Fprintf(&body, " - {destination: [groups, group-%03d, base, items], key: id, mode: append}\n", index) } body.WriteString("groups:\n") for index := range 64 { fmt.Fprintf(&body, " group-%03d:\n base: {items: [{id: shared, value: parent}]}\n child: {extends: base, items: [{id: shared, value: child}]}\n", index) } type item struct { ID string `yaml:"id"` Value string `yaml:"value"` } type definition struct { Items []item `yaml:"items"` } type config struct { Groups map[string]map[string]definition `yaml:"groups"` } loaded, err := testLoad[config](Bytes("wide-inheritance", []byte(body.String()))) if err != nil { t.Fatal(err) } metadata := loaded.Metadata() for name, group := range loaded.Config.Groups { if len(group["base"].Items) != 1 || group["base"].Items[0].Value != "parent" || len(group["child"].Items) != 1 || group["child"].Items[0].Value != "child" { t.Fatalf("independent scope %s composed incorrectly: %#v", name, group) } path := Keys("groups", name, "child", "items").Index(0).Key("value") if info, exists := metadata.Lookup(path); !exists || !info.Explicit || info.Origin.Layer != LayerBase { t.Fatalf("inherited destination lost source metadata at %s", path) } } }