github.com/posener/terraform@v0.11.0-beta1.0.20171103235147-645df36af025/helper/schema/field_reader_test.go (about) 1 package schema 2 3 import ( 4 "reflect" 5 "testing" 6 ) 7 8 func TestAddrToSchema(t *testing.T) { 9 cases := map[string]struct { 10 Addr []string 11 Schema map[string]*Schema 12 Result []ValueType 13 }{ 14 "full object": { 15 []string{}, 16 map[string]*Schema{ 17 "list": &Schema{ 18 Type: TypeList, 19 Elem: &Schema{Type: TypeInt}, 20 }, 21 }, 22 []ValueType{typeObject}, 23 }, 24 25 "list": { 26 []string{"list"}, 27 map[string]*Schema{ 28 "list": &Schema{ 29 Type: TypeList, 30 Elem: &Schema{Type: TypeInt}, 31 }, 32 }, 33 []ValueType{TypeList}, 34 }, 35 36 "list.#": { 37 []string{"list", "#"}, 38 map[string]*Schema{ 39 "list": &Schema{ 40 Type: TypeList, 41 Elem: &Schema{Type: TypeInt}, 42 }, 43 }, 44 []ValueType{TypeList, TypeInt}, 45 }, 46 47 "list.0": { 48 []string{"list", "0"}, 49 map[string]*Schema{ 50 "list": &Schema{ 51 Type: TypeList, 52 Elem: &Schema{Type: TypeInt}, 53 }, 54 }, 55 []ValueType{TypeList, TypeInt}, 56 }, 57 58 "list.0 with resource": { 59 []string{"list", "0"}, 60 map[string]*Schema{ 61 "list": &Schema{ 62 Type: TypeList, 63 Elem: &Resource{ 64 Schema: map[string]*Schema{ 65 "field": &Schema{Type: TypeString}, 66 }, 67 }, 68 }, 69 }, 70 []ValueType{TypeList, typeObject}, 71 }, 72 73 "list.0.field": { 74 []string{"list", "0", "field"}, 75 map[string]*Schema{ 76 "list": &Schema{ 77 Type: TypeList, 78 Elem: &Resource{ 79 Schema: map[string]*Schema{ 80 "field": &Schema{Type: TypeString}, 81 }, 82 }, 83 }, 84 }, 85 []ValueType{TypeList, typeObject, TypeString}, 86 }, 87 88 "set": { 89 []string{"set"}, 90 map[string]*Schema{ 91 "set": &Schema{ 92 Type: TypeSet, 93 Elem: &Schema{Type: TypeInt}, 94 Set: func(a interface{}) int { 95 return a.(int) 96 }, 97 }, 98 }, 99 []ValueType{TypeSet}, 100 }, 101 102 "set.#": { 103 []string{"set", "#"}, 104 map[string]*Schema{ 105 "set": &Schema{ 106 Type: TypeSet, 107 Elem: &Schema{Type: TypeInt}, 108 Set: func(a interface{}) int { 109 return a.(int) 110 }, 111 }, 112 }, 113 []ValueType{TypeSet, TypeInt}, 114 }, 115 116 "set.0": { 117 []string{"set", "0"}, 118 map[string]*Schema{ 119 "set": &Schema{ 120 Type: TypeSet, 121 Elem: &Schema{Type: TypeInt}, 122 Set: func(a interface{}) int { 123 return a.(int) 124 }, 125 }, 126 }, 127 []ValueType{TypeSet, TypeInt}, 128 }, 129 130 "set.0 with resource": { 131 []string{"set", "0"}, 132 map[string]*Schema{ 133 "set": &Schema{ 134 Type: TypeSet, 135 Elem: &Resource{ 136 Schema: map[string]*Schema{ 137 "field": &Schema{Type: TypeString}, 138 }, 139 }, 140 }, 141 }, 142 []ValueType{TypeSet, typeObject}, 143 }, 144 145 "mapElem": { 146 []string{"map", "foo"}, 147 map[string]*Schema{ 148 "map": &Schema{Type: TypeMap}, 149 }, 150 []ValueType{TypeMap, TypeString}, 151 }, 152 153 "setDeep": { 154 []string{"set", "50", "index"}, 155 map[string]*Schema{ 156 "set": &Schema{ 157 Type: TypeSet, 158 Elem: &Resource{ 159 Schema: map[string]*Schema{ 160 "index": &Schema{Type: TypeInt}, 161 "value": &Schema{Type: TypeString}, 162 }, 163 }, 164 Set: func(a interface{}) int { 165 return a.(map[string]interface{})["index"].(int) 166 }, 167 }, 168 }, 169 []ValueType{TypeSet, typeObject, TypeInt}, 170 }, 171 } 172 173 for name, tc := range cases { 174 result := addrToSchema(tc.Addr, tc.Schema) 175 types := make([]ValueType, len(result)) 176 for i, v := range result { 177 types[i] = v.Type 178 } 179 180 if !reflect.DeepEqual(types, tc.Result) { 181 t.Fatalf("%s: %#v", name, types) 182 } 183 } 184 } 185 186 // testFieldReader is a helper that should be used to verify that 187 // a FieldReader behaves properly in all the common cases. 188 func testFieldReader(t *testing.T, f func(map[string]*Schema) FieldReader) { 189 schema := map[string]*Schema{ 190 // Primitives 191 "bool": &Schema{Type: TypeBool}, 192 "float": &Schema{Type: TypeFloat}, 193 "int": &Schema{Type: TypeInt}, 194 "string": &Schema{Type: TypeString}, 195 196 // Lists 197 "list": &Schema{ 198 Type: TypeList, 199 Elem: &Schema{Type: TypeString}, 200 }, 201 "listInt": &Schema{ 202 Type: TypeList, 203 Elem: &Schema{Type: TypeInt}, 204 }, 205 "listMap": &Schema{ 206 Type: TypeList, 207 Elem: &Schema{ 208 Type: TypeMap, 209 }, 210 }, 211 212 // Maps 213 "map": &Schema{Type: TypeMap}, 214 "mapInt": &Schema{ 215 Type: TypeMap, 216 Elem: TypeInt, 217 }, 218 "mapFloat": &Schema{ 219 Type: TypeMap, 220 Elem: TypeFloat, 221 }, 222 "mapBool": &Schema{ 223 Type: TypeMap, 224 Elem: TypeBool, 225 }, 226 227 // Sets 228 "set": &Schema{ 229 Type: TypeSet, 230 Elem: &Schema{Type: TypeInt}, 231 Set: func(a interface{}) int { 232 return a.(int) 233 }, 234 }, 235 "setDeep": &Schema{ 236 Type: TypeSet, 237 Elem: &Resource{ 238 Schema: map[string]*Schema{ 239 "index": &Schema{Type: TypeInt}, 240 "value": &Schema{Type: TypeString}, 241 }, 242 }, 243 Set: func(a interface{}) int { 244 return a.(map[string]interface{})["index"].(int) 245 }, 246 }, 247 "setEmpty": &Schema{ 248 Type: TypeSet, 249 Elem: &Schema{Type: TypeInt}, 250 Set: func(a interface{}) int { 251 return a.(int) 252 }, 253 }, 254 } 255 256 cases := map[string]struct { 257 Addr []string 258 Result FieldReadResult 259 Err bool 260 }{ 261 "noexist": { 262 []string{"boolNOPE"}, 263 FieldReadResult{ 264 Value: nil, 265 Exists: false, 266 Computed: false, 267 }, 268 false, 269 }, 270 271 "bool": { 272 []string{"bool"}, 273 FieldReadResult{ 274 Value: true, 275 Exists: true, 276 Computed: false, 277 }, 278 false, 279 }, 280 281 "float": { 282 []string{"float"}, 283 FieldReadResult{ 284 Value: 3.1415, 285 Exists: true, 286 Computed: false, 287 }, 288 false, 289 }, 290 291 "int": { 292 []string{"int"}, 293 FieldReadResult{ 294 Value: 42, 295 Exists: true, 296 Computed: false, 297 }, 298 false, 299 }, 300 301 "string": { 302 []string{"string"}, 303 FieldReadResult{ 304 Value: "string", 305 Exists: true, 306 Computed: false, 307 }, 308 false, 309 }, 310 311 "list": { 312 []string{"list"}, 313 FieldReadResult{ 314 Value: []interface{}{ 315 "foo", 316 "bar", 317 }, 318 Exists: true, 319 Computed: false, 320 }, 321 false, 322 }, 323 324 "listInt": { 325 []string{"listInt"}, 326 FieldReadResult{ 327 Value: []interface{}{ 328 21, 329 42, 330 }, 331 Exists: true, 332 Computed: false, 333 }, 334 false, 335 }, 336 337 "map": { 338 []string{"map"}, 339 FieldReadResult{ 340 Value: map[string]interface{}{ 341 "foo": "bar", 342 "bar": "baz", 343 }, 344 Exists: true, 345 Computed: false, 346 }, 347 false, 348 }, 349 350 "mapInt": { 351 []string{"mapInt"}, 352 FieldReadResult{ 353 Value: map[string]interface{}{ 354 "one": 1, 355 "two": 2, 356 }, 357 Exists: true, 358 Computed: false, 359 }, 360 false, 361 }, 362 363 "mapFloat": { 364 []string{"mapFloat"}, 365 FieldReadResult{ 366 Value: map[string]interface{}{ 367 "oneDotTwo": 1.2, 368 }, 369 Exists: true, 370 Computed: false, 371 }, 372 false, 373 }, 374 375 "mapBool": { 376 []string{"mapBool"}, 377 FieldReadResult{ 378 Value: map[string]interface{}{ 379 "True": true, 380 "False": false, 381 }, 382 Exists: true, 383 Computed: false, 384 }, 385 false, 386 }, 387 388 "mapelem": { 389 []string{"map", "foo"}, 390 FieldReadResult{ 391 Value: "bar", 392 Exists: true, 393 Computed: false, 394 }, 395 false, 396 }, 397 398 "set": { 399 []string{"set"}, 400 FieldReadResult{ 401 Value: []interface{}{10, 50}, 402 Exists: true, 403 Computed: false, 404 }, 405 false, 406 }, 407 408 "setDeep": { 409 []string{"setDeep"}, 410 FieldReadResult{ 411 Value: []interface{}{ 412 map[string]interface{}{ 413 "index": 10, 414 "value": "foo", 415 }, 416 map[string]interface{}{ 417 "index": 50, 418 "value": "bar", 419 }, 420 }, 421 Exists: true, 422 Computed: false, 423 }, 424 false, 425 }, 426 427 "setEmpty": { 428 []string{"setEmpty"}, 429 FieldReadResult{ 430 Value: []interface{}{}, 431 Exists: false, 432 }, 433 false, 434 }, 435 } 436 437 for name, tc := range cases { 438 r := f(schema) 439 out, err := r.ReadField(tc.Addr) 440 if err != nil != tc.Err { 441 t.Fatalf("%s: err: %s", name, err) 442 } 443 if s, ok := out.Value.(*Set); ok { 444 // If it is a set, convert to a list so its more easily checked. 445 out.Value = s.List() 446 } 447 if !reflect.DeepEqual(tc.Result, out) { 448 t.Fatalf("%s: bad: %#v", name, out) 449 } 450 } 451 }