91 lines
3.3 KiB
Go
91 lines
3.3 KiB
Go
package engine
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"gitea.maximumdirect.net/eric/ConfigKit/internal/document"
|
|
)
|
|
|
|
func TestRecursiveMappingMergePreservesValuesPathsAndInputs(t *testing.T) {
|
|
type expectedNode struct {
|
|
path Path
|
|
kind document.Kind
|
|
text string
|
|
entries int
|
|
}
|
|
tests := []struct {
|
|
name, base, incoming string
|
|
want []expectedNode
|
|
events []string
|
|
}{
|
|
{
|
|
name: "nested mappings", base: "shared: {kept: base, changed: old}\n", incoming: "shared: {changed: new, added: child}\n",
|
|
want: []expectedNode{
|
|
{path: Keys("shared"), kind: document.Mapping, entries: 3},
|
|
{path: Keys("shared", "kept"), kind: document.String, text: "base"},
|
|
{path: Keys("shared", "changed"), kind: document.String, text: "new"},
|
|
{path: Keys("shared", "added"), kind: document.String, text: "child"},
|
|
},
|
|
events: []string{"combine:/shared", "replace:/shared/changed", "add:/shared/added"},
|
|
},
|
|
{
|
|
name: "sequence replacement", base: "value: [old]\n", incoming: "value: []\n",
|
|
want: []expectedNode{{path: Keys("value"), kind: document.Sequence}},
|
|
events: []string{"replace:/value"},
|
|
},
|
|
{
|
|
name: "scalar replacement", base: "value: old\n", incoming: "value: new\n",
|
|
want: []expectedNode{{path: Keys("value"), kind: document.String, text: "new"}},
|
|
events: []string{"replace:/value"},
|
|
},
|
|
{
|
|
name: "null replacement", base: "value: old\n", incoming: "value: null\n",
|
|
want: []expectedNode{{path: Keys("value"), kind: document.Null}},
|
|
events: []string{"replace:/value"},
|
|
},
|
|
{
|
|
name: "empty mapping retains children", base: "shared: {kept: base}\n", incoming: "shared: {}\n",
|
|
want: []expectedNode{
|
|
{path: Keys("shared"), kind: document.Mapping, entries: 1},
|
|
{path: Keys("shared", "kept"), kind: document.String, text: "base"},
|
|
},
|
|
events: []string{"combine:/shared"},
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
base := parseCompositionDocument(t, "source-1", test.base)
|
|
incoming := parseCompositionDocument(t, "source-2", test.incoming)
|
|
baseBefore, incomingBefore := document.Clone(base), document.Clone(incoming)
|
|
owned := document.Clone(base)
|
|
var events []string
|
|
mergeRecursiveMappings(owned, incoming, Path{}, new(mappingIndex), recursiveMergeHooks{
|
|
added: func(path Path, _ *document.Node) { events = append(events, "add:"+path.String()) },
|
|
combined: func(path Path, _ *document.Node) {
|
|
events = append(events, "combine:"+path.String())
|
|
},
|
|
replaced: func(path Path, _, _ *document.Node) {
|
|
events = append(events, "replace:"+path.String())
|
|
},
|
|
})
|
|
if !reflect.DeepEqual(events, test.events) {
|
|
t.Fatalf("merge events = %#v, want %#v", events, test.events)
|
|
}
|
|
for _, expected := range test.want {
|
|
node, found := documentAtPath(owned, expected.path)
|
|
if !found || node.Kind != expected.kind || node.Text != expected.text || len(node.Mapping) != expected.entries {
|
|
t.Errorf("merged %s = %#v, found %v", expected.path.String(), node, found)
|
|
}
|
|
}
|
|
if !reflect.DeepEqual(base, baseBefore) || !reflect.DeepEqual(incoming, incomingBefore) {
|
|
t.Fatal("merge changed an input")
|
|
}
|
|
owned.Mapping[0].Value.Location.SourceID = "changed"
|
|
if !reflect.DeepEqual(base, baseBefore) || !reflect.DeepEqual(incoming, incomingBefore) {
|
|
t.Fatal("merged result aliases an input")
|
|
}
|
|
})
|
|
}
|
|
}
|