github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/command/jsonplan/plan_test.go (about) 1 package jsonplan 2 3 import ( 4 "encoding/json" 5 "reflect" 6 "testing" 7 8 "github.com/google/go-cmp/cmp" 9 "github.com/zclconf/go-cty/cty" 10 ) 11 12 func TestOmitUnknowns(t *testing.T) { 13 tests := []struct { 14 Input cty.Value 15 Want cty.Value 16 }{ 17 { 18 cty.StringVal("hello"), 19 cty.StringVal("hello"), 20 }, 21 { 22 cty.NullVal(cty.String), 23 cty.NullVal(cty.String), 24 }, 25 { 26 cty.UnknownVal(cty.String), 27 cty.NilVal, 28 }, 29 { 30 cty.ListValEmpty(cty.String), 31 cty.EmptyTupleVal, 32 }, 33 { 34 cty.ListVal([]cty.Value{cty.StringVal("hello")}), 35 cty.TupleVal([]cty.Value{cty.StringVal("hello")}), 36 }, 37 { 38 cty.ListVal([]cty.Value{cty.NullVal(cty.String)}), 39 cty.TupleVal([]cty.Value{cty.NullVal(cty.String)}), 40 }, 41 { 42 cty.ListVal([]cty.Value{cty.UnknownVal(cty.String)}), 43 cty.TupleVal([]cty.Value{cty.NullVal(cty.String)}), 44 }, 45 { 46 cty.ListVal([]cty.Value{cty.StringVal("hello")}), 47 cty.TupleVal([]cty.Value{cty.StringVal("hello")}), 48 }, 49 // 50 { 51 cty.ListVal([]cty.Value{ 52 cty.StringVal("hello"), 53 cty.UnknownVal(cty.String)}), 54 cty.TupleVal([]cty.Value{ 55 cty.StringVal("hello"), 56 cty.NullVal(cty.String), 57 }), 58 }, 59 { 60 cty.MapVal(map[string]cty.Value{ 61 "hello": cty.True, 62 "world": cty.UnknownVal(cty.Bool), 63 }), 64 cty.ObjectVal(map[string]cty.Value{ 65 "hello": cty.True, 66 }), 67 }, 68 { 69 cty.TupleVal([]cty.Value{ 70 cty.StringVal("alpha"), 71 cty.UnknownVal(cty.String), 72 cty.StringVal("charlie"), 73 }), 74 cty.TupleVal([]cty.Value{ 75 cty.StringVal("alpha"), 76 cty.NullVal(cty.String), 77 cty.StringVal("charlie"), 78 }), 79 }, 80 { 81 cty.SetVal([]cty.Value{ 82 cty.StringVal("dev"), 83 cty.StringVal("foo"), 84 cty.StringVal("stg"), 85 cty.UnknownVal(cty.String), 86 }), 87 cty.TupleVal([]cty.Value{ 88 cty.StringVal("dev"), 89 cty.StringVal("foo"), 90 cty.StringVal("stg"), 91 cty.NullVal(cty.String), 92 }), 93 }, 94 { 95 cty.SetVal([]cty.Value{ 96 cty.ObjectVal(map[string]cty.Value{ 97 "a": cty.UnknownVal(cty.String), 98 }), 99 cty.ObjectVal(map[string]cty.Value{ 100 "a": cty.StringVal("known"), 101 }), 102 }), 103 cty.TupleVal([]cty.Value{ 104 cty.ObjectVal(map[string]cty.Value{ 105 "a": cty.StringVal("known"), 106 }), 107 cty.EmptyObjectVal, 108 }), 109 }, 110 } 111 112 for _, test := range tests { 113 got := omitUnknowns(test.Input) 114 if !reflect.DeepEqual(got, test.Want) { 115 t.Errorf( 116 "wrong result\ninput: %#v\ngot: %#v\nwant: %#v", 117 test.Input, got, test.Want, 118 ) 119 } 120 } 121 } 122 123 func TestUnknownAsBool(t *testing.T) { 124 tests := []struct { 125 Input cty.Value 126 Want cty.Value 127 }{ 128 { 129 cty.StringVal("hello"), 130 cty.False, 131 }, 132 { 133 cty.NullVal(cty.String), 134 cty.False, 135 }, 136 { 137 cty.UnknownVal(cty.String), 138 cty.True, 139 }, 140 141 { 142 cty.NullVal(cty.DynamicPseudoType), 143 cty.False, 144 }, 145 { 146 cty.NullVal(cty.Object(map[string]cty.Type{"test": cty.String})), 147 cty.False, 148 }, 149 { 150 cty.DynamicVal, 151 cty.True, 152 }, 153 154 { 155 cty.ListValEmpty(cty.String), 156 cty.EmptyTupleVal, 157 }, 158 { 159 cty.ListVal([]cty.Value{cty.StringVal("hello")}), 160 cty.TupleVal([]cty.Value{cty.False}), 161 }, 162 { 163 cty.ListVal([]cty.Value{cty.NullVal(cty.String)}), 164 cty.TupleVal([]cty.Value{cty.False}), 165 }, 166 { 167 cty.ListVal([]cty.Value{cty.UnknownVal(cty.String)}), 168 cty.TupleVal([]cty.Value{cty.True}), 169 }, 170 { 171 cty.SetValEmpty(cty.String), 172 cty.EmptyTupleVal, 173 }, 174 { 175 cty.SetVal([]cty.Value{cty.StringVal("hello")}), 176 cty.TupleVal([]cty.Value{cty.False}), 177 }, 178 { 179 cty.SetVal([]cty.Value{cty.NullVal(cty.String)}), 180 cty.TupleVal([]cty.Value{cty.False}), 181 }, 182 { 183 cty.SetVal([]cty.Value{cty.UnknownVal(cty.String)}), 184 cty.TupleVal([]cty.Value{cty.True}), 185 }, 186 { 187 cty.EmptyTupleVal, 188 cty.EmptyTupleVal, 189 }, 190 { 191 cty.TupleVal([]cty.Value{cty.StringVal("hello")}), 192 cty.TupleVal([]cty.Value{cty.False}), 193 }, 194 { 195 cty.TupleVal([]cty.Value{cty.NullVal(cty.String)}), 196 cty.TupleVal([]cty.Value{cty.False}), 197 }, 198 { 199 cty.TupleVal([]cty.Value{cty.UnknownVal(cty.String)}), 200 cty.TupleVal([]cty.Value{cty.True}), 201 }, 202 { 203 cty.MapValEmpty(cty.String), 204 cty.EmptyObjectVal, 205 }, 206 { 207 cty.MapVal(map[string]cty.Value{"greeting": cty.StringVal("hello")}), 208 cty.EmptyObjectVal, 209 }, 210 { 211 cty.MapVal(map[string]cty.Value{"greeting": cty.NullVal(cty.String)}), 212 cty.EmptyObjectVal, 213 }, 214 { 215 cty.MapVal(map[string]cty.Value{"greeting": cty.UnknownVal(cty.String)}), 216 cty.ObjectVal(map[string]cty.Value{"greeting": cty.True}), 217 }, 218 { 219 cty.EmptyObjectVal, 220 cty.EmptyObjectVal, 221 }, 222 { 223 cty.ObjectVal(map[string]cty.Value{"greeting": cty.StringVal("hello")}), 224 cty.EmptyObjectVal, 225 }, 226 { 227 cty.ObjectVal(map[string]cty.Value{"greeting": cty.NullVal(cty.String)}), 228 cty.EmptyObjectVal, 229 }, 230 { 231 cty.ObjectVal(map[string]cty.Value{"greeting": cty.UnknownVal(cty.String)}), 232 cty.ObjectVal(map[string]cty.Value{"greeting": cty.True}), 233 }, 234 { 235 cty.SetVal([]cty.Value{ 236 cty.ObjectVal(map[string]cty.Value{ 237 "a": cty.UnknownVal(cty.String), 238 }), 239 cty.ObjectVal(map[string]cty.Value{ 240 "a": cty.StringVal("known"), 241 }), 242 }), 243 cty.TupleVal([]cty.Value{ 244 cty.EmptyObjectVal, 245 cty.ObjectVal(map[string]cty.Value{ 246 "a": cty.True, 247 }), 248 }), 249 }, 250 { 251 cty.SetVal([]cty.Value{ 252 cty.MapValEmpty(cty.String), 253 cty.MapVal(map[string]cty.Value{ 254 "a": cty.StringVal("known"), 255 }), 256 cty.MapVal(map[string]cty.Value{ 257 "a": cty.UnknownVal(cty.String), 258 }), 259 }), 260 cty.TupleVal([]cty.Value{ 261 cty.EmptyObjectVal, 262 cty.ObjectVal(map[string]cty.Value{ 263 "a": cty.True, 264 }), 265 cty.EmptyObjectVal, 266 }), 267 }, 268 } 269 270 for _, test := range tests { 271 got := unknownAsBool(test.Input) 272 if !reflect.DeepEqual(got, test.Want) { 273 t.Errorf( 274 "wrong result\ninput: %#v\ngot: %#v\nwant: %#v", 275 test.Input, got, test.Want, 276 ) 277 } 278 } 279 } 280 281 func TestEncodePaths(t *testing.T) { 282 tests := map[string]struct { 283 Input cty.PathSet 284 Want json.RawMessage 285 }{ 286 "empty set": { 287 cty.NewPathSet(), 288 json.RawMessage(nil), 289 }, 290 "index path with string and int steps": { 291 cty.NewPathSet(cty.IndexStringPath("boop").IndexInt(0)), 292 json.RawMessage(`[["boop",0]]`), 293 }, 294 "get attr path with one step": { 295 cty.NewPathSet(cty.GetAttrPath("triggers")), 296 json.RawMessage(`[["triggers"]]`), 297 }, 298 "multiple paths of different types": { 299 cty.NewPathSet( 300 cty.GetAttrPath("alpha").GetAttr("beta").GetAttr("gamma"), 301 cty.GetAttrPath("triggers").IndexString("name"), 302 cty.IndexIntPath(0).IndexInt(1).IndexInt(2).IndexInt(3), 303 ), 304 json.RawMessage(`[["alpha","beta","gamma"],["triggers","name"],[0,1,2,3]]`), 305 }, 306 } 307 308 for name, test := range tests { 309 t.Run(name, func(t *testing.T) { 310 got, err := encodePaths(test.Input) 311 if err != nil { 312 t.Fatalf("unexpected error: %s", err) 313 } 314 if !cmp.Equal(got, test.Want) { 315 t.Errorf("wrong result:\n %v\n", cmp.Diff(got, test.Want)) 316 } 317 }) 318 } 319 } 320 321 func deepObjectValue(depth int) cty.Value { 322 v := cty.ObjectVal(map[string]cty.Value{ 323 "a": cty.StringVal("a"), 324 "b": cty.NumberIntVal(2), 325 "c": cty.True, 326 "d": cty.UnknownVal(cty.String), 327 }) 328 329 result := v 330 331 for i := 0; i < depth; i++ { 332 result = cty.ObjectVal(map[string]cty.Value{ 333 "a": result, 334 "b": result, 335 "c": result, 336 }) 337 } 338 339 return result 340 } 341 342 func BenchmarkUnknownAsBool_2(b *testing.B) { 343 value := deepObjectValue(2) 344 for n := 0; n < b.N; n++ { 345 unknownAsBool(value) 346 } 347 } 348 349 func BenchmarkUnknownAsBool_3(b *testing.B) { 350 value := deepObjectValue(3) 351 for n := 0; n < b.N; n++ { 352 unknownAsBool(value) 353 } 354 } 355 356 func BenchmarkUnknownAsBool_5(b *testing.B) { 357 value := deepObjectValue(5) 358 for n := 0; n < b.N; n++ { 359 unknownAsBool(value) 360 } 361 } 362 363 func BenchmarkUnknownAsBool_7(b *testing.B) { 364 value := deepObjectValue(7) 365 for n := 0; n < b.N; n++ { 366 unknownAsBool(value) 367 } 368 } 369 370 func BenchmarkUnknownAsBool_9(b *testing.B) { 371 value := deepObjectValue(9) 372 for n := 0; n < b.N; n++ { 373 unknownAsBool(value) 374 } 375 }