github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/configs/hcl2shim/values_equiv_test.go (about) 1 package hcl2shim 2 3 import ( 4 "fmt" 5 "math/big" 6 "testing" 7 8 "github.com/zclconf/go-cty/cty" 9 ) 10 11 func TestValuesSDKEquivalent(t *testing.T) { 12 piBig, _, err := big.ParseFloat("3.14159265358979323846264338327950288419716939937510582097494459", 10, 512, big.ToZero) 13 if err != nil { 14 t.Fatal(err) 15 } 16 pi64, _ := piBig.Float64() 17 18 tests := []struct { 19 A, B cty.Value 20 Want bool 21 }{ 22 // Strings 23 { 24 cty.StringVal("hello"), 25 cty.StringVal("hello"), 26 true, 27 }, 28 { 29 cty.StringVal("hello"), 30 cty.StringVal("world"), 31 false, 32 }, 33 { 34 cty.StringVal("hello"), 35 cty.StringVal(""), 36 false, 37 }, 38 { 39 cty.NullVal(cty.String), 40 cty.StringVal(""), 41 true, 42 }, 43 44 // Numbers 45 { 46 cty.NumberIntVal(1), 47 cty.NumberIntVal(1), 48 true, 49 }, 50 { 51 cty.NumberIntVal(1), 52 cty.NumberIntVal(2), 53 false, 54 }, 55 { 56 cty.NumberIntVal(1), 57 cty.Zero, 58 false, 59 }, 60 { 61 cty.NullVal(cty.Number), 62 cty.Zero, 63 true, 64 }, 65 { 66 cty.NumberVal(piBig), 67 cty.Zero, 68 false, 69 }, 70 { 71 cty.NumberFloatVal(pi64), 72 cty.Zero, 73 false, 74 }, 75 { 76 cty.NumberFloatVal(pi64), 77 cty.NumberVal(piBig), 78 true, 79 }, 80 81 // Bools 82 { 83 cty.True, 84 cty.True, 85 true, 86 }, 87 { 88 cty.True, 89 cty.False, 90 false, 91 }, 92 { 93 cty.NullVal(cty.Bool), 94 cty.False, 95 true, 96 }, 97 98 // Mixed primitives 99 { 100 cty.StringVal("hello"), 101 cty.False, 102 false, 103 }, 104 { 105 cty.StringVal(""), 106 cty.False, 107 true, 108 }, 109 { 110 cty.NumberIntVal(0), 111 cty.False, 112 true, 113 }, 114 { 115 cty.StringVal(""), 116 cty.NumberIntVal(0), 117 true, 118 }, 119 { 120 cty.NullVal(cty.Bool), 121 cty.NullVal(cty.Number), 122 true, 123 }, 124 { 125 cty.StringVal(""), 126 cty.NullVal(cty.Number), 127 true, 128 }, 129 130 // Lists 131 { 132 cty.ListValEmpty(cty.String), 133 cty.ListValEmpty(cty.String), 134 true, 135 }, 136 { 137 cty.ListValEmpty(cty.String), 138 cty.NullVal(cty.List(cty.String)), 139 true, 140 }, 141 { 142 cty.ListVal([]cty.Value{cty.StringVal("hello")}), 143 cty.ListVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("hello")}), 144 false, 145 }, 146 { 147 cty.ListVal([]cty.Value{cty.StringVal("hello")}), 148 cty.ListValEmpty(cty.String), 149 false, 150 }, 151 { 152 cty.ListVal([]cty.Value{cty.StringVal("hello")}), 153 cty.ListVal([]cty.Value{cty.StringVal("hello")}), 154 true, 155 }, 156 { 157 cty.ListVal([]cty.Value{cty.StringVal("hello")}), 158 cty.ListVal([]cty.Value{cty.StringVal("world")}), 159 false, 160 }, 161 { 162 cty.ListVal([]cty.Value{cty.NullVal(cty.String)}), 163 cty.ListVal([]cty.Value{cty.StringVal("")}), 164 true, 165 }, 166 167 // Tuples 168 { 169 cty.EmptyTupleVal, 170 cty.EmptyTupleVal, 171 true, 172 }, 173 { 174 cty.EmptyTupleVal, 175 cty.NullVal(cty.EmptyTuple), 176 true, 177 }, 178 { 179 cty.TupleVal([]cty.Value{cty.StringVal("hello")}), 180 cty.TupleVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("hello")}), 181 false, 182 }, 183 { 184 cty.TupleVal([]cty.Value{cty.StringVal("hello")}), 185 cty.EmptyTupleVal, 186 false, 187 }, 188 { 189 cty.TupleVal([]cty.Value{cty.StringVal("hello")}), 190 cty.TupleVal([]cty.Value{cty.StringVal("hello")}), 191 true, 192 }, 193 { 194 cty.TupleVal([]cty.Value{cty.StringVal("hello")}), 195 cty.TupleVal([]cty.Value{cty.StringVal("world")}), 196 false, 197 }, 198 { 199 cty.TupleVal([]cty.Value{cty.NullVal(cty.String)}), 200 cty.TupleVal([]cty.Value{cty.StringVal("")}), 201 true, 202 }, 203 204 // Sets 205 { 206 cty.SetValEmpty(cty.String), 207 cty.SetValEmpty(cty.String), 208 true, 209 }, 210 { 211 cty.SetValEmpty(cty.String), 212 cty.NullVal(cty.Set(cty.String)), 213 true, 214 }, 215 { 216 cty.SetVal([]cty.Value{cty.StringVal("hello")}), 217 cty.SetValEmpty(cty.String), 218 false, 219 }, 220 { 221 cty.SetVal([]cty.Value{cty.StringVal("hello")}), 222 cty.SetVal([]cty.Value{cty.StringVal("hello")}), 223 true, 224 }, 225 { 226 cty.SetVal([]cty.Value{cty.StringVal("hello")}), 227 cty.SetVal([]cty.Value{cty.StringVal("world")}), 228 false, 229 }, 230 { 231 cty.SetVal([]cty.Value{cty.NullVal(cty.String)}), 232 cty.SetVal([]cty.Value{cty.StringVal("")}), 233 true, 234 }, 235 { 236 cty.SetVal([]cty.Value{ 237 cty.NullVal(cty.String), 238 cty.StringVal(""), 239 }), 240 cty.SetVal([]cty.Value{ 241 cty.NullVal(cty.String), 242 }), 243 false, // because the element count is different 244 }, 245 { 246 cty.SetVal([]cty.Value{ 247 cty.ObjectVal(map[string]cty.Value{ 248 "a": cty.StringVal(""), 249 "b": cty.StringVal(""), 250 }), 251 cty.ObjectVal(map[string]cty.Value{ 252 "a": cty.NullVal(cty.String), 253 "b": cty.StringVal(""), 254 }), 255 }), 256 cty.SetVal([]cty.Value{ 257 cty.ObjectVal(map[string]cty.Value{ 258 "a": cty.StringVal(""), 259 "b": cty.StringVal(""), 260 }), 261 cty.ObjectVal(map[string]cty.Value{ 262 "a": cty.StringVal(""), 263 "b": cty.NullVal(cty.String), 264 }), 265 }), 266 true, 267 }, 268 { 269 cty.SetVal([]cty.Value{ 270 cty.ObjectVal(map[string]cty.Value{ 271 "a": cty.StringVal("boop"), 272 "b": cty.StringVal(""), 273 }), 274 cty.ObjectVal(map[string]cty.Value{ 275 "a": cty.NullVal(cty.String), 276 "b": cty.StringVal(""), 277 }), 278 }), 279 cty.SetVal([]cty.Value{ 280 cty.ObjectVal(map[string]cty.Value{ 281 "a": cty.StringVal("beep"), 282 "b": cty.StringVal(""), 283 }), 284 cty.ObjectVal(map[string]cty.Value{ 285 "a": cty.StringVal(""), 286 "b": cty.NullVal(cty.String), 287 }), 288 }), 289 false, 290 }, 291 { 292 cty.SetVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{ 293 "list": cty.ListValEmpty(cty.String), 294 "list_block": cty.ListVal([]cty.Value{ 295 cty.ObjectVal(map[string]cty.Value{ 296 "unused": cty.StringVal(""), 297 }), 298 }), 299 })}), 300 cty.SetVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{ 301 "list": cty.ListValEmpty(cty.String), 302 "list_block": cty.ListVal([]cty.Value{ 303 cty.ObjectVal(map[string]cty.Value{ 304 "unused": cty.NullVal(cty.String), 305 }), 306 }), 307 })}), 308 true, 309 }, 310 311 // Maps 312 { 313 cty.MapValEmpty(cty.String), 314 cty.MapValEmpty(cty.String), 315 true, 316 }, 317 { 318 cty.MapValEmpty(cty.String), 319 cty.NullVal(cty.Map(cty.String)), 320 true, 321 }, 322 { 323 cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello")}), 324 cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello"), "hey": cty.StringVal("hello")}), 325 false, 326 }, 327 { 328 cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello")}), 329 cty.MapValEmpty(cty.String), 330 false, 331 }, 332 { 333 cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello")}), 334 cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello")}), 335 true, 336 }, 337 { 338 cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello")}), 339 cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("world")}), 340 false, 341 }, 342 { 343 cty.MapVal(map[string]cty.Value{"hi": cty.NullVal(cty.String)}), 344 cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("")}), 345 true, 346 }, 347 348 // Objects 349 { 350 cty.EmptyObjectVal, 351 cty.EmptyObjectVal, 352 true, 353 }, 354 { 355 cty.EmptyObjectVal, 356 cty.NullVal(cty.EmptyObject), 357 true, 358 }, 359 { 360 cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello")}), 361 cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello"), "hey": cty.StringVal("hello")}), 362 false, 363 }, 364 { 365 cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello")}), 366 cty.EmptyObjectVal, 367 false, 368 }, 369 { 370 cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello")}), 371 cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello")}), 372 true, 373 }, 374 { 375 cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello")}), 376 cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("world")}), 377 false, 378 }, 379 { 380 cty.ObjectVal(map[string]cty.Value{"hi": cty.NullVal(cty.String)}), 381 cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("")}), 382 true, 383 }, 384 385 // Unknown values 386 { 387 cty.UnknownVal(cty.String), 388 cty.UnknownVal(cty.String), 389 true, 390 }, 391 { 392 cty.StringVal("hello"), 393 cty.UnknownVal(cty.String), 394 false, 395 }, 396 { 397 cty.StringVal(""), 398 cty.UnknownVal(cty.String), 399 false, 400 }, 401 { 402 cty.NullVal(cty.String), 403 cty.UnknownVal(cty.String), 404 false, 405 }, 406 } 407 408 run := func(t *testing.T, a, b cty.Value, want bool) { 409 got := ValuesSDKEquivalent(a, b) 410 411 if got != want { 412 t.Errorf("wrong result\nfor: %#v ≈ %#v\ngot %#v, but want %#v", a, b, got, want) 413 } 414 } 415 416 for _, test := range tests { 417 t.Run(fmt.Sprintf("%#v ≈ %#v", test.A, test.B), func(t *testing.T) { 418 run(t, test.A, test.B, test.Want) 419 }) 420 // This function is symmetrical, so we'll also test in reverse so 421 // we don't need to manually copy all of the test cases. (But this does 422 // mean that one failure normally becomes two, of course!) 423 if !test.A.RawEquals(test.B) { 424 t.Run(fmt.Sprintf("%#v ≈ %#v", test.B, test.A), func(t *testing.T) { 425 run(t, test.B, test.A, test.Want) 426 }) 427 } 428 } 429 }