package engine import "testing" func TestCLIHistoryFollowsInheritanceAndPrecedesResolution(t *testing.T) { t.Parallel() for _, test := range []struct { name string layered, records, equal, resolve bool }{ {name: "ordinary mapping"}, {name: "layered mapping equal with resolution", layered: true, equal: true, resolve: true}, {name: "ordinary records equal", records: true, equal: true}, {name: "layered records with resolution", layered: true, records: true, resolve: true}, } { t.Run(test.name, func(t *testing.T) { body := "base: {value: parent}\nchild: {extends: base, value: authored}\n" query, parent := Keys("child", "value"), Keys("base", "value") cliValue := "cli" if test.equal { cliValue = "authored" } override := Override{Path: query, Value: cliValue, Flag: "--value"} if test.records { body = "configkit:\n sequences: [{destination: [items], key: id}]\nitems: [{id: base, value: parent}, {id: child, extends: {id: base}}]\n" query, parent = Keys("items").Index(1).Key("value"), Keys("items").Index(0).Key("value") if test.equal { cliValue = "parent" } override = Override{Path: Keys("items"), Value: []any{map[string]any{"id": "base", "value": "parent"}, map[string]any{"id": "child", "value": cliValue}}, Flag: "--items"} } definition := Definition[map[string]any]{} if test.resolve { definition.Resolve = func(value *map[string]any, resolution *Resolution) error { recorded := query if test.records { (*value)["items"].([]any)[1].(map[string]any)["value"] = "resolved" recorded = Keys("items") } else { (*value)["child"].(map[string]any)["value"] = "resolved" } resolution.Record(recorded, ChangeNormalization, "normalize after CLI", parent) return nil } } source := Bytes("source", []byte(body)) var loaded *testResult[map[string]any] var err error if test.layered { loaded, err = testGroupedLoad(loadRequest[map[string]any]{main: loadInput{source: source}, definition: definition, overrides: []Override{override}}) } else { loaded, err = testLoad(source, Options[map[string]any]{Definition: definition, Overrides: []Override{override}}) } if err != nil { t.Fatal(err) } history := loaded.Metadata().History(query) inherited, cli, resolved := false, false, false for _, change := range history { if change.Origin.Operation == ChangeInheritance { if cli { t.Fatal("inheritance reported after CLI") } inherited = true } else if change.Origin.Layer == LayerBase && cli { t.Fatal("source definition reappeared after CLI") } if change.Origin.Layer == LayerCLI { if !inherited || resolved { t.Fatal("CLI reported outside its lifecycle phase") } cli = true } if change.Origin.Layer == LayerResolution { if !cli { t.Fatal("resolution reported before CLI") } resolved = true if len(change.Dependencies) != 1 || change.Dependencies[0].String() != parent.String() { t.Fatalf("resolution dependencies = %#v", change.Dependencies) } } } if !inherited || !cli || resolved != test.resolve { t.Fatalf("missing lifecycle history: %#v", history) } info, _ := loaded.Metadata().Lookup(query) if history[len(history)-1].Origin.Layer != info.Origin.Layer { t.Fatal("last history origin disagrees with effective metadata") } }) } }