github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/configs/configschema/empty_value_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package configschema 5 6 import ( 7 "fmt" 8 "testing" 9 10 "github.com/apparentlymart/go-dump/dump" 11 "github.com/davecgh/go-spew/spew" 12 "github.com/zclconf/go-cty/cty" 13 ) 14 15 func TestBlockEmptyValue(t *testing.T) { 16 tests := []struct { 17 Schema *Block 18 Want cty.Value 19 }{ 20 { 21 &Block{}, 22 cty.EmptyObjectVal, 23 }, 24 { 25 &Block{ 26 Attributes: map[string]*Attribute{ 27 "str": {Type: cty.String, Required: true}, 28 }, 29 }, 30 cty.ObjectVal(map[string]cty.Value{ 31 "str": cty.NullVal(cty.String), 32 }), 33 }, 34 { 35 &Block{ 36 BlockTypes: map[string]*NestedBlock{ 37 "single": { 38 Nesting: NestingSingle, 39 Block: Block{ 40 Attributes: map[string]*Attribute{ 41 "str": {Type: cty.String, Required: true}, 42 }, 43 }, 44 }, 45 }, 46 }, 47 cty.ObjectVal(map[string]cty.Value{ 48 "single": cty.NullVal(cty.Object(map[string]cty.Type{ 49 "str": cty.String, 50 })), 51 }), 52 }, 53 { 54 &Block{ 55 BlockTypes: map[string]*NestedBlock{ 56 "group": { 57 Nesting: NestingGroup, 58 Block: Block{ 59 Attributes: map[string]*Attribute{ 60 "str": {Type: cty.String, Required: true}, 61 }, 62 }, 63 }, 64 }, 65 }, 66 cty.ObjectVal(map[string]cty.Value{ 67 "group": cty.ObjectVal(map[string]cty.Value{ 68 "str": cty.NullVal(cty.String), 69 }), 70 }), 71 }, 72 { 73 &Block{ 74 BlockTypes: map[string]*NestedBlock{ 75 "list": { 76 Nesting: NestingList, 77 Block: Block{ 78 Attributes: map[string]*Attribute{ 79 "str": {Type: cty.String, Required: true}, 80 }, 81 }, 82 }, 83 }, 84 }, 85 cty.ObjectVal(map[string]cty.Value{ 86 "list": cty.ListValEmpty(cty.Object(map[string]cty.Type{ 87 "str": cty.String, 88 })), 89 }), 90 }, 91 { 92 &Block{ 93 BlockTypes: map[string]*NestedBlock{ 94 "list_dynamic": { 95 Nesting: NestingList, 96 Block: Block{ 97 Attributes: map[string]*Attribute{ 98 "str": {Type: cty.DynamicPseudoType, Required: true}, 99 }, 100 }, 101 }, 102 }, 103 }, 104 cty.ObjectVal(map[string]cty.Value{ 105 "list_dynamic": cty.EmptyTupleVal, 106 }), 107 }, 108 { 109 &Block{ 110 BlockTypes: map[string]*NestedBlock{ 111 "map": { 112 Nesting: NestingMap, 113 Block: Block{ 114 Attributes: map[string]*Attribute{ 115 "str": {Type: cty.String, Required: true}, 116 }, 117 }, 118 }, 119 }, 120 }, 121 cty.ObjectVal(map[string]cty.Value{ 122 "map": cty.MapValEmpty(cty.Object(map[string]cty.Type{ 123 "str": cty.String, 124 })), 125 }), 126 }, 127 { 128 &Block{ 129 BlockTypes: map[string]*NestedBlock{ 130 "map_dynamic": { 131 Nesting: NestingMap, 132 Block: Block{ 133 Attributes: map[string]*Attribute{ 134 "str": {Type: cty.DynamicPseudoType, Required: true}, 135 }, 136 }, 137 }, 138 }, 139 }, 140 cty.ObjectVal(map[string]cty.Value{ 141 "map_dynamic": cty.EmptyObjectVal, 142 }), 143 }, 144 { 145 &Block{ 146 BlockTypes: map[string]*NestedBlock{ 147 "set": { 148 Nesting: NestingSet, 149 Block: Block{ 150 Attributes: map[string]*Attribute{ 151 "str": {Type: cty.String, Required: true}, 152 }, 153 }, 154 }, 155 }, 156 }, 157 cty.ObjectVal(map[string]cty.Value{ 158 "set": cty.SetValEmpty(cty.Object(map[string]cty.Type{ 159 "str": cty.String, 160 })), 161 }), 162 }, 163 } 164 165 for _, test := range tests { 166 t.Run(fmt.Sprintf("%#v", test.Schema), func(t *testing.T) { 167 got := test.Schema.EmptyValue() 168 if !test.Want.RawEquals(got) { 169 t.Errorf("wrong result\nschema: %s\ngot: %s\nwant: %s", spew.Sdump(test.Schema), dump.Value(got), dump.Value(test.Want)) 170 } 171 }) 172 } 173 } 174 175 // Attribute EmptyValue() is well covered by the Block tests above; these tests 176 // focus on the behavior with NestedType field inside an Attribute 177 func TestAttributeEmptyValue(t *testing.T) { 178 tests := []struct { 179 Schema *Attribute 180 Want cty.Value 181 }{ 182 { 183 &Attribute{}, 184 cty.NilVal, 185 }, 186 { 187 &Attribute{ 188 Type: cty.String, 189 }, 190 cty.NullVal(cty.String), 191 }, 192 { 193 &Attribute{ 194 NestedType: &Object{ 195 Nesting: NestingSingle, 196 Attributes: map[string]*Attribute{ 197 "str": {Type: cty.String, Required: true}, 198 }, 199 }, 200 }, 201 cty.NullVal(cty.Object(map[string]cty.Type{ 202 "str": cty.String, 203 })), 204 }, 205 { 206 &Attribute{ 207 NestedType: &Object{ 208 Nesting: NestingList, 209 Attributes: map[string]*Attribute{ 210 "str": {Type: cty.String, Required: true}, 211 }, 212 }, 213 }, 214 cty.NullVal(cty.List( 215 cty.Object(map[string]cty.Type{ 216 "str": cty.String, 217 }), 218 )), 219 }, 220 { 221 &Attribute{ 222 NestedType: &Object{ 223 Nesting: NestingMap, 224 Attributes: map[string]*Attribute{ 225 "str": {Type: cty.String, Required: true}, 226 }, 227 }, 228 }, 229 cty.NullVal(cty.Map( 230 cty.Object(map[string]cty.Type{ 231 "str": cty.String, 232 }), 233 )), 234 }, 235 { 236 &Attribute{ 237 NestedType: &Object{ 238 Nesting: NestingSet, 239 Attributes: map[string]*Attribute{ 240 "str": {Type: cty.String, Required: true}, 241 }, 242 }, 243 }, 244 cty.NullVal(cty.Set( 245 cty.Object(map[string]cty.Type{ 246 "str": cty.String, 247 }), 248 )), 249 }, 250 } 251 252 for _, test := range tests { 253 t.Run(fmt.Sprintf("%#v", test.Schema), func(t *testing.T) { 254 got := test.Schema.EmptyValue() 255 if !test.Want.RawEquals(got) { 256 t.Errorf("wrong result\nschema: %s\ngot: %s\nwant: %s", spew.Sdump(test.Schema), dump.Value(got), dump.Value(test.Want)) 257 } 258 }) 259 } 260 }