Apply nested collection operations when copying mappings
This commit is contained in:
106
internal/engine/collection_ancestor_test.go
Normal file
106
internal/engine/collection_ancestor_test.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
)
|
||||
|
||||
func TestNestedCollectionInitializationIsIndependentOfAncestorPresence(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, ancestor := range []string{"{}", "group: {}", "group: null"} {
|
||||
for _, test := range []struct {
|
||||
mode, key, value string
|
||||
valid bool
|
||||
}{
|
||||
{mode: "append", value: "[{id: a}]"},
|
||||
{mode: "upsert", value: "[{id: a}]"},
|
||||
{mode: "append", value: "[]"},
|
||||
{mode: "upsert", value: "[]"},
|
||||
{mode: "append", key: ", key: id", value: "{}"},
|
||||
{mode: "upsert", key: ", key: id", value: "null"},
|
||||
{mode: "append", key: ", key: id", value: "[{id: a}]", valid: true},
|
||||
{mode: "upsert", key: ", key: id", value: "[]", valid: true},
|
||||
} {
|
||||
t.Run(fmt.Sprintf("%s/%s/%s/%s", ancestor, test.mode, test.key, test.value), func(t *testing.T) {
|
||||
main := "configkit:\n sequences: [{destination: [group, items], mode: " + test.mode + test.key + "}]\ngroup: {items: " + test.value + "}\n"
|
||||
loaded, err := testGroupedLoad(loadRequest[map[string]any]{
|
||||
main: loadInput{source: Bytes("main", []byte(main))},
|
||||
underlays: []loadGroup{{inputs: []loadInput{{source: Bytes("lower", []byte(ancestor))}}}},
|
||||
})
|
||||
if test.valid {
|
||||
if err != nil || loaded == nil {
|
||||
t.Fatalf("valid initialization failed: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
var loadErr *LoadError
|
||||
if !errors.As(err, &loadErr) || loaded != nil {
|
||||
t.Fatalf("invalid collection operation succeeded: %#v, %v", loaded, err)
|
||||
}
|
||||
diagnostics := loadErr.Diagnostics()
|
||||
if len(diagnostics) != 1 || diagnostics[0].Code != CodeSequenceInvalid || diagnostics[0].Path.String() != "/group/items" {
|
||||
t.Fatalf("operation diagnostics = %#v", diagnostics)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddedAncestorTransfersNestedRecordPolicies(t *testing.T) {
|
||||
t.Parallel()
|
||||
type record struct {
|
||||
ID string `yaml:"id"`
|
||||
Steps []map[string]any `yaml:"steps"`
|
||||
}
|
||||
type config struct {
|
||||
Group struct {
|
||||
Items []record `yaml:"items"`
|
||||
} `yaml:"group"`
|
||||
}
|
||||
files := fstest.MapFS{
|
||||
"main.yml": {Data: []byte(`configkit:
|
||||
sequences: [{destination: [group, items], key: id}]
|
||||
imports: [{path: base.yml, destination: [group, items], placement: sequence-item}]
|
||||
group:
|
||||
items: [{id: child, extends: {id: base}, steps: [{name: child}]}]
|
||||
`)},
|
||||
"base.yml": {Data: []byte("configkit:\n sequences: [{destination: [steps], key: name}]\nid: base\nsteps: [{name: base}]\n")},
|
||||
}
|
||||
loaded, err := testGroupedLoad(loadRequest[config]{
|
||||
main: loadInput{source: NewFilesystem("catalog", files).File("main.yml"), imports: true},
|
||||
underlays: []loadGroup{{inputs: []loadInput{{source: Bytes("lower", []byte("{}"))}}}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, item := range loaded.Config.Group.Items {
|
||||
if item.ID == "child" {
|
||||
if len(item.Steps) != 2 || item.Steps[0]["name"] != "base" || item.Steps[1]["name"] != "child" {
|
||||
t.Fatalf("record-local identity was lost when adding its ancestor: %#v", item.Steps)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Fatal("missing child record")
|
||||
}
|
||||
|
||||
func TestInheritanceChecksCollectionOperationUnderAddedAncestor(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := testLoad[map[string]any](Bytes("inheritance", []byte(`configkit:
|
||||
sequences: [{destination: [child, group, items], mode: append}]
|
||||
base: {}
|
||||
child:
|
||||
extends: base
|
||||
group: {items: [{id: a}]}
|
||||
`)))
|
||||
var loadErr *LoadError
|
||||
if !errors.As(err, &loadErr) {
|
||||
t.Fatalf("missing nested operation error: %v", err)
|
||||
}
|
||||
diagnostics := loadErr.Diagnostics()
|
||||
if len(diagnostics) != 1 || diagnostics[0].Code != CodeSequenceInvalid || diagnostics[0].Path.String() != "/child/group/items" {
|
||||
t.Fatalf("nested inheritance operation diagnostics = %#v", diagnostics)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user