121 lines
4.4 KiB
Go
121 lines
4.4 KiB
Go
package configkit_test
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
configkit "gitea.maximumdirect.net/eric/ConfigKit"
|
|
)
|
|
|
|
func TestPublicHistoricalPathsEnumerateContextualShapes(t *testing.T) {
|
|
loaded, err := configkit.Load[map[string]any](configkit.Bytes("main", []byte(
|
|
"retired: {child: 1}\nshape: {'0': base}\n'a/b~': {'': 2}\n",
|
|
)), configkit.Options[map[string]any]{Overrides: []configkit.Override{
|
|
{Path: configkit.Keys("retired"), Value: nil, Flag: "--retired"},
|
|
{Path: configkit.Keys("shape"), Value: []any{"replacement"}, Flag: "--shape"},
|
|
}})
|
|
if err != nil {
|
|
t.Fatalf("Load: %v", err)
|
|
}
|
|
|
|
metadata := loaded.Metadata()
|
|
paths := metadata.HistoricalPaths()
|
|
got := make([]string, len(paths))
|
|
for index, path := range paths {
|
|
got[index] = path.String()
|
|
if len(metadata.History(path)) == 0 {
|
|
t.Errorf("enumerated path %s has no history", path)
|
|
}
|
|
}
|
|
want := []string{"", "/a~1b~0", "/a~1b~0/", "/retired", "/retired/child", "/shape", "/shape/0"}
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("historical paths = %v, want sorted unique pointers %v", got, want)
|
|
}
|
|
if _, ok := metadata.Lookup(paths[4]); ok {
|
|
t.Fatal("removed descendant remains effective")
|
|
}
|
|
if _, ok := metadata.Lookup(paths[6]); !ok {
|
|
t.Fatal("enumerated numeric path did not follow the effective sequence shape")
|
|
}
|
|
if len(metadata.History(paths[6])) == 0 {
|
|
t.Fatal("enumerated numeric path lost history")
|
|
}
|
|
assertPublicShapeHistory(t, metadata, configkit.LayerCLI)
|
|
if _, ok := metadata.Lookup(configkit.Keys("shape", "0")); ok {
|
|
t.Fatal("mapping-key path resolved against the effective sequence")
|
|
}
|
|
if len((configkit.Metadata{}).HistoricalPaths()) != 0 {
|
|
t.Fatal("zero metadata contains historical paths")
|
|
}
|
|
if (configkit.Metadata{}).History(configkit.Keys("shape")) != nil {
|
|
t.Fatal("zero metadata contains history")
|
|
}
|
|
|
|
paths[1] = configkit.Keys("mutated")
|
|
if again := metadata.HistoricalPaths(); !reflect.DeepEqual(pathStrings(again), want) {
|
|
t.Fatalf("returned path slice mutated retained metadata: %v", pathStrings(again))
|
|
}
|
|
}
|
|
|
|
func TestPublicHistoryUsesResolutionShapeAttribution(t *testing.T) {
|
|
loaded, err := configkit.Load[map[string]any](configkit.Bytes("main", []byte("shape: {'0': base}\n")), configkit.Options[map[string]any]{
|
|
Definition: configkit.Definition[map[string]any]{
|
|
Resolve: func(configuration *map[string]any, resolution *configkit.Resolution) error {
|
|
(*configuration)["shape"] = []any{"replacement"}
|
|
resolution.RecordNormalization(configkit.Keys("shape"), "replace numeric mapping key")
|
|
return nil
|
|
},
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Load: %v", err)
|
|
}
|
|
assertPublicShapeHistory(t, loaded.Metadata(), configkit.LayerResolution)
|
|
}
|
|
|
|
func assertPublicShapeHistory(t *testing.T, metadata configkit.Metadata, operationLayer configkit.Layer) {
|
|
t.Helper()
|
|
|
|
keyPath := configkit.Keys("shape", "0")
|
|
indexPath := configkit.Keys("shape").Index(0)
|
|
keyHistory := metadata.History(keyPath)
|
|
indexHistory := metadata.History(indexPath)
|
|
if len(keyHistory) == 0 || len(indexHistory) == 0 {
|
|
t.Fatalf("explicit shape histories = key %#v, index %#v", keyHistory, indexHistory)
|
|
}
|
|
var keyDefinition, keyReplacement, indexReplacement bool
|
|
for _, change := range keyHistory {
|
|
keyDefinition = keyDefinition || change.Origin.Layer == configkit.LayerMain
|
|
keyReplacement = keyReplacement || change.Origin.Layer == operationLayer && change.Path.String() == "/shape"
|
|
}
|
|
for _, change := range indexHistory {
|
|
if change.Origin.Layer == configkit.LayerMain {
|
|
t.Fatalf("introduced index inherited mapping-key history: %#v", indexHistory)
|
|
}
|
|
indexReplacement = indexReplacement || change.Origin.Layer == operationLayer && change.Path.String() == "/shape"
|
|
for _, previous := range change.Previous {
|
|
if previous.Layer == configkit.LayerMain {
|
|
t.Fatalf("introduced index inherited mapping-key previous origin: %#v", change)
|
|
}
|
|
}
|
|
}
|
|
if !keyDefinition || !keyReplacement || !indexReplacement {
|
|
t.Fatalf("shape histories missed applicable definitions or replacement: key %#v, index %#v", keyHistory, indexHistory)
|
|
}
|
|
parsed, err := configkit.ParsePath("/shape/0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if parsedHistory := metadata.History(parsed); len(parsedHistory) == 0 {
|
|
t.Fatal("parsed numeric query lost contextual history")
|
|
}
|
|
}
|
|
|
|
func pathStrings(paths []configkit.Path) []string {
|
|
result := make([]string, len(paths))
|
|
for index, path := range paths {
|
|
result[index] = path.String()
|
|
}
|
|
return result
|
|
}
|