Files
configkit/internal/engine/resolution_correspondence_test.go

74 lines
3.5 KiB
Go
Raw Normal View History

package engine
import "testing"
func TestResolutionCollectionCorrespondence(t *testing.T) {
policy, diagnostics := compileSequenceIdentityPolicy([]sequenceIdentityRegistration{{
selector: sequenceIdentitySelector{literalSequenceSelector("items")}, identityFields: []string{"id"},
}})
if len(diagnostics) != 0 {
t.Fatal(diagnostics)
}
for _, test := range []struct {
name, before, after string
eligible, structural bool
finalIndex, entryIndex int
matched bool
}{
{"swap", "items: [{id: a}, {id: b}]", "items: [{id: b}, {id: a}]", true, true, 0, 1, true},
{"insert", "items: [{id: a}]", "items: [{id: b}, {id: a}]", true, true, 0, 0, false},
{"remove", "items: [{id: a}, {id: b}]", "items: [{id: b}]", true, true, 0, 1, true},
{"same", "items: [{id: a}]", "items: [{id: a}]", true, false, 0, 0, true},
{"duplicate", "items: [{id: a}, {id: a}]", "items: [{id: a}]", false, false, 0, 0, true},
{"missing", "items: [{name: a}]", "items: [{id: a}]", false, false, 0, 0, true},
{"identity replacement", "items: [{id: a}]", "items: [{id: b}]", true, true, 0, 0, false},
{"invalid final", "items: [{id: a}]", "items: [bad]", false, false, 0, 0, true},
} {
t.Run(test.name, func(t *testing.T) {
before := parseCompositionDocument(t, "before", test.before)
after := parseCompositionDocument(t, "after", test.after)
matching := buildResolutionCorrespondence(before, after, policy)
collection := matching.collections["/items"]
if collection.eligible != test.eligible || collection.structural != test.structural {
t.Fatalf("collection = %#v", collection)
}
entry, ok := matching.entryPath(Keys("items").Index(test.finalIndex).Key("value"))
if ok != test.matched || (ok && entry.String() != Keys("items").Index(test.entryIndex).Key("value").String()) {
t.Fatalf("entry = %s, matched = %t", entry.String(), ok)
}
})
}
}
func TestResolutionCorrespondenceDynamicCompoundIdentities(t *testing.T) {
policy, diagnostics := compileSequenceIdentityPolicy([]sequenceIdentityRegistration{{
selector: sequenceIdentitySelector{literalSequenceSelector("groups"), anyMappingSequenceSelector(), literalSequenceSelector("items")},
identityFields: []string{"id", "kind"},
}})
if len(diagnostics) != 0 {
t.Fatal(diagnostics)
}
before := parseCompositionDocument(t, "before", "groups: {alpha: {items: [{id: 1, kind: x}, {id: '1', kind: x}]}, empty: {items: []}}")
after := parseCompositionDocument(t, "after", "groups: {alpha: {items: [{id: '1', kind: x}, {id: 1.0, kind: x}]}, empty: {items: []}}")
matching := buildResolutionCorrespondence(before, after, policy)
retained := matching.clone()
changed := matching.collections["/groups/alpha/items"]
changed.finalToEntry[0] = 0
matching.collections["/groups/alpha/items"] = changed
if entry, ok := retained.entryPath(Keys("groups", "alpha", "items").Index(0)); !ok || entry.String() != "/groups/alpha/items/1" {
t.Fatalf("retained correspondence shares mutable indexes: %s, %t", entry.String(), ok)
}
matching = retained
if empty := matching.collections["/groups/empty/items"]; !empty.eligible || empty.structural {
t.Fatalf("empty = %#v", empty)
}
path, ok := matching.entryPath(Keys("groups", "alpha", "items").Index(0).Key("missing"))
if !ok || path.String() != "/groups/alpha/items/1/missing" {
t.Fatalf("entry = %s, %t", path.String(), ok)
}
wrongShape, ok := matching.entryPath(Keys("groups").Index(0).Key("items").Index(0))
if !ok || wrongShape.String() != "/groups/0/items/0" {
t.Fatalf("mapping shape = %s, %t", wrongShape.String(), ok)
}
}