package engine import ( "errors" "testing" ) func TestResolutionAuditsOrdinaryListFields(t *testing.T) { type item struct { Count int `yaml:"count"` Enabled bool `yaml:"enabled"` Nested []*int `yaml:"nested"` } type config struct { Items []item `yaml:"items"` } for _, test := range []struct { name string other, resize bool wantPath string }{ {name: "covered field"}, {name: "uncovered field", other: true, wantPath: "/items/0/enabled"}, {name: "length change", resize: true, wantPath: "/items"}, } { t.Run(test.name, func(t *testing.T) { result, err := testLoad(Bytes("items", []byte("items: [{count: 3, enabled: true, nested: [null]}]\n")), Options[config]{Definition: Definition[config]{ Resolve: func(value *config, r *Resolution) error { value.Items[0].Count = 0 r.RecordNormalization(Keys("items").Index(0).Key("count"), "clear count") if test.other { value.Items[0].Enabled = false } if test.resize { value.Items = append(value.Items, item{}) } return nil }, }}) if test.wantPath == "" { if err != nil || result.Config.Items[0].Count != 0 { t.Fatalf("result = %#v, error = %v", result, err) } return } var failure *LoadError if !errors.As(err, &failure) { t.Fatalf("error = %v", err) } found := false for _, diagnostic := range failure.Diagnostics() { if diagnostic.Code == CodeResolveUnrecordedChange && diagnostic.Path.String() == test.wantPath { found = true } } if !found { t.Fatalf("diagnostics = %#v", failure.Diagnostics()) } }) } } func TestResolutionComparisonKeepsDiffAtomic(t *testing.T) { before := parseCompositionDocument(t, "before", "items: [{values: [true, null]}]") after := parseCompositionDocument(t, "after", "items: [{values: [false, 0]}]") deltas := compareResolutionValues(before, after) if len(deltas) != 2 || deltas[0].path.String() != "/items/0/values/0" || deltas[1].path.String() != "/items/0/values/1" { t.Fatalf("resolution deltas = %#v", deltas) } atomic := compareConfigurationValues(before, after) if len(atomic) != 1 || atomic[0].path.String() != "/items" { t.Fatalf("atomic deltas = %#v", atomic) } }