Limit inheritance policy work to the relevant scope
This commit is contained in:
111
internal/engine/inheritance_policy_index_test.go
Normal file
111
internal/engine/inheritance_policy_index_test.go
Normal file
@@ -0,0 +1,111 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user