From 1f8320f9e812cfedd650a9db4244462712101d49 Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Thu, 3 Nov 2022 15:50:29 +0100 Subject: [PATCH] check empty collections for optional attributes --- cty/convert/conversion_collection.go | 6 +- cty/convert/public_test.go | 120 +++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) diff --git a/cty/convert/conversion_collection.go b/cty/convert/conversion_collection.go index 5b52d02d..05399c9a 100644 --- a/cty/convert/conversion_collection.go +++ b/cty/convert/conversion_collection.go @@ -190,7 +190,7 @@ func conversionTupleToSet(tupleType cty.Type, setEty cty.Type, unsafe bool) conv if len(tupleEtys) == 0 { // Empty tuple short-circuit return func(val cty.Value, path cty.Path) (cty.Value, error) { - return cty.SetValEmpty(setEty), nil + return cty.SetValEmpty(setEty.WithoutOptionalAttributesDeep()), nil } } @@ -280,7 +280,7 @@ func conversionTupleToList(tupleType cty.Type, listEty cty.Type, unsafe bool) co if len(tupleEtys) == 0 { // Empty tuple short-circuit return func(val cty.Value, path cty.Path) (cty.Value, error) { - return cty.ListValEmpty(listEty), nil + return cty.ListValEmpty(listEty.WithoutOptionalAttributesDeep()), nil } } @@ -372,7 +372,7 @@ func conversionObjectToMap(objectType cty.Type, mapEty cty.Type, unsafe bool) co if len(objectAtys) == 0 { // Empty object short-circuit return func(val cty.Value, path cty.Path) (cty.Value, error) { - return cty.MapValEmpty(mapEty), nil + return cty.MapValEmpty(mapEty.WithoutOptionalAttributesDeep()), nil } } diff --git a/cty/convert/public_test.go b/cty/convert/public_test.go index a980fd35..97f4f71f 100644 --- a/cty/convert/public_test.go +++ b/cty/convert/public_test.go @@ -1268,6 +1268,126 @@ func TestConvert(t *testing.T) { })}, ), }, + // We should strip optional attributes out of empty sets, maps, lists, + // and tuples. + { + Value: cty.ListValEmpty(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Type: cty.Set(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.SetValEmpty(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }, + { + Value: cty.EmptyTupleVal, + Type: cty.Set(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.SetValEmpty(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }, + { + Value: cty.SetValEmpty(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Type: cty.List(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.ListValEmpty(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }, + { + Value: cty.EmptyTupleVal, + Type: cty.List(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.ListValEmpty(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }, + { + Value: cty.EmptyObjectVal, + Type: cty.Map(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.MapValEmpty(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }, + { + Value: cty.MapValEmpty(cty.String), + Type: cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"}), + Want: cty.ObjectVal(map[string]cty.Value{ + "a": cty.NullVal(cty.String), + }), + }, + // We should strip optional attributes out of null sets, maps, lists, + // and tuples. + { + Value: cty.NullVal(cty.List(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"}))), + Type: cty.Set(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.NullVal(cty.Set(cty.Object(map[string]cty.Type{ + "a": cty.String, + }))), + }, + { + Value: cty.NullVal(cty.EmptyTuple), + Type: cty.Set(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.NullVal(cty.Set(cty.Object(map[string]cty.Type{ + "a": cty.String, + }))), + }, + { + Value: cty.NullVal(cty.Set(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"}))), + Type: cty.List(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.NullVal(cty.List(cty.Object(map[string]cty.Type{ + "a": cty.String, + }))), + }, + { + Value: cty.NullVal(cty.EmptyTuple), + Type: cty.List(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.NullVal(cty.List(cty.Object(map[string]cty.Type{ + "a": cty.String, + }))), + }, + { + Value: cty.NullVal(cty.EmptyObject), + Type: cty.Map(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.NullVal(cty.Map(cty.Object(map[string]cty.Type{ + "a": cty.String, + }))), + }, + { + Value: cty.NullVal(cty.Map(cty.String)), + Type: cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"}), + Want: cty.NullVal(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }, // We should strip optional attributes out of null values in sets, maps, // lists and tuples. {