diff --git a/internal/plans/objchange/objchange_test.go b/internal/plans/objchange/objchange_test.go index cc169248ba..4922b99967 100644 --- a/internal/plans/objchange/objchange_test.go +++ b/internal/plans/objchange/objchange_test.go @@ -2893,3 +2893,139 @@ var testAttributes = map[string]*configschema.Attribute{ Required: true, }, } + +func TestPrepareComputedBlocks(t *testing.T) { + attrs := map[string]*configschema.Attribute{ + "optional": {Type: cty.String, Optional: true}, + "nested_computed": { + NestedType: &configschema.Object{ + Nesting: configschema.NestingMap, + Attributes: map[string]*configschema.Attribute{ + "optional": {Type: cty.String, Optional: true}, + "computed": {Type: cty.List(cty.Object(map[string]cty.Type{"attr": cty.String})), Optional: true}, + }, + }, + Optional: true, + Computed: true, + }, + } + + schema := &configschema.Block{ + Attributes: attrs, + BlockTypes: map[string]*configschema.NestedBlock{ + "single": { + Block: configschema.Block{ + Attributes: attrs, + }, + Nesting: configschema.NestingSingle, + }, + "group": { + Block: configschema.Block{ + Attributes: attrs, + }, + Nesting: configschema.NestingGroup, + }, + "list": { + Block: configschema.Block{ + Attributes: attrs, + }, + Nesting: configschema.NestingList, + }, + "set": { + Block: configschema.Block{ + Attributes: attrs, + }, + Nesting: configschema.NestingSet, + }, + "map": { + Block: configschema.Block{ + Attributes: attrs, + }, + Nesting: configschema.NestingMap, + }, + "single_computed": { + Block: configschema.Block{ + Attributes: attrs, + Computed: true, + }, + Nesting: configschema.NestingSingle, + }, + "list_computed": { + Block: configschema.Block{ + Attributes: attrs, + Computed: true, + }, + Nesting: configschema.NestingList, + }, + "set_computed": { + Block: configschema.Block{ + Attributes: attrs, + Computed: true, + }, + Nesting: configschema.NestingSet, + }, + "map_computed": { + Block: configschema.Block{ + Attributes: attrs, + Computed: true, + }, + Nesting: configschema.NestingMap, + }, + }, + } + + objVal := cty.ObjectVal(map[string]cty.Value{ + "optional": cty.NullVal(cty.String), + "nested_computed": cty.MapValEmpty(cty.Object(map[string]cty.Type{ + "optional": cty.String, + "computed": cty.List(cty.Object(map[string]cty.Type{"attr": cty.String})), + })), + }) + objTy := objVal.Type() + + config := cty.ObjectVal(map[string]cty.Value{ + "optional": cty.NullVal(cty.String), + "nested_computed": cty.MapValEmpty(cty.Object(map[string]cty.Type{ + "optional": cty.String, + "computed": cty.List(cty.Object(map[string]cty.Type{"attr": cty.String})), + })), + + "single": cty.NullVal(objTy), + "group": objVal, + "list": cty.ListValEmpty(objTy), + "set": cty.SetValEmpty(objTy), + "map": cty.MapValEmpty(objTy), + "single_computed": cty.NullVal(objTy), + "list_computed": cty.ListValEmpty(objTy), + "set_computed": cty.SetValEmpty(objTy), + "map_computed": cty.MapValEmpty(objTy), + }) + + want := cty.ObjectVal(map[string]cty.Value{ + // no nested objects should change + "optional": cty.NullVal(cty.String), + "nested_computed": cty.MapValEmpty(cty.Object(map[string]cty.Type{ + "optional": cty.String, + "computed": cty.List(cty.Object(map[string]cty.Type{"attr": cty.String})), + })), + + // non-computed empty values are unchanged + "single": cty.NullVal(objTy), + "group": objVal, + "list": cty.ListValEmpty(objTy), + "set": cty.SetValEmpty(objTy), + "map": cty.MapValEmpty(objTy), + + // All computed blocks are null + "single_computed": cty.NullVal(objTy), + "list_computed": cty.NullVal(cty.List(objTy)), + "set_computed": cty.NullVal(cty.Set(objTy)), + "map_computed": cty.NullVal(cty.Map(objTy)), + }) + + got := PrepareComputedBlocks(schema, config) + + if !got.RawEquals(want) { + t.Error(cmp.Diff(ctydebug.ValueString(got), ctydebug.ValueString(want))) + } +}