github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/legacy/helper/schema/field_writer_map_test.go (about) 1 package schema 2 3 import ( 4 "reflect" 5 "testing" 6 ) 7 8 func TestMapFieldWriter_impl(t *testing.T) { 9 var _ FieldWriter = new(MapFieldWriter) 10 } 11 12 func TestMapFieldWriter(t *testing.T) { 13 schema := map[string]*Schema{ 14 "bool": &Schema{Type: TypeBool}, 15 "int": &Schema{Type: TypeInt}, 16 "string": &Schema{Type: TypeString}, 17 "list": &Schema{ 18 Type: TypeList, 19 Elem: &Schema{Type: TypeString}, 20 }, 21 "listInt": &Schema{ 22 Type: TypeList, 23 Elem: &Schema{Type: TypeInt}, 24 }, 25 "listResource": &Schema{ 26 Type: TypeList, 27 Optional: true, 28 Computed: true, 29 Elem: &Resource{ 30 Schema: map[string]*Schema{ 31 "value": &Schema{ 32 Type: TypeInt, 33 Optional: true, 34 }, 35 }, 36 }, 37 }, 38 "map": &Schema{Type: TypeMap}, 39 "set": &Schema{ 40 Type: TypeSet, 41 Elem: &Schema{Type: TypeInt}, 42 Set: func(a interface{}) int { 43 return a.(int) 44 }, 45 }, 46 "setDeep": &Schema{ 47 Type: TypeSet, 48 Elem: &Resource{ 49 Schema: map[string]*Schema{ 50 "index": &Schema{Type: TypeInt}, 51 "value": &Schema{Type: TypeString}, 52 }, 53 }, 54 Set: func(a interface{}) int { 55 return a.(map[string]interface{})["index"].(int) 56 }, 57 }, 58 } 59 60 cases := map[string]struct { 61 Addr []string 62 Value interface{} 63 Err bool 64 Out map[string]string 65 }{ 66 "noexist": { 67 []string{"noexist"}, 68 42, 69 true, 70 map[string]string{}, 71 }, 72 73 "bool": { 74 []string{"bool"}, 75 false, 76 false, 77 map[string]string{ 78 "bool": "false", 79 }, 80 }, 81 82 "int": { 83 []string{"int"}, 84 42, 85 false, 86 map[string]string{ 87 "int": "42", 88 }, 89 }, 90 91 "string": { 92 []string{"string"}, 93 "42", 94 false, 95 map[string]string{ 96 "string": "42", 97 }, 98 }, 99 100 "string nil": { 101 []string{"string"}, 102 nil, 103 false, 104 map[string]string{ 105 "string": "", 106 }, 107 }, 108 109 "list of resources": { 110 []string{"listResource"}, 111 []interface{}{ 112 map[string]interface{}{ 113 "value": 80, 114 }, 115 }, 116 false, 117 map[string]string{ 118 "listResource.#": "1", 119 "listResource.0.value": "80", 120 }, 121 }, 122 123 "list of resources empty": { 124 []string{"listResource"}, 125 []interface{}{}, 126 false, 127 map[string]string{ 128 "listResource.#": "0", 129 }, 130 }, 131 132 "list of resources nil": { 133 []string{"listResource"}, 134 nil, 135 false, 136 map[string]string{ 137 "listResource.#": "0", 138 }, 139 }, 140 141 "list of strings": { 142 []string{"list"}, 143 []interface{}{"foo", "bar"}, 144 false, 145 map[string]string{ 146 "list.#": "2", 147 "list.0": "foo", 148 "list.1": "bar", 149 }, 150 }, 151 152 "list element": { 153 []string{"list", "0"}, 154 "string", 155 true, 156 map[string]string{}, 157 }, 158 159 "map": { 160 []string{"map"}, 161 map[string]interface{}{"foo": "bar"}, 162 false, 163 map[string]string{ 164 "map.%": "1", 165 "map.foo": "bar", 166 }, 167 }, 168 169 "map delete": { 170 []string{"map"}, 171 nil, 172 false, 173 map[string]string{ 174 "map": "", 175 }, 176 }, 177 178 "map element": { 179 []string{"map", "foo"}, 180 "bar", 181 true, 182 map[string]string{}, 183 }, 184 185 "set": { 186 []string{"set"}, 187 []interface{}{1, 2, 5}, 188 false, 189 map[string]string{ 190 "set.#": "3", 191 "set.1": "1", 192 "set.2": "2", 193 "set.5": "5", 194 }, 195 }, 196 197 "set nil": { 198 []string{"set"}, 199 nil, 200 false, 201 map[string]string{ 202 "set.#": "0", 203 }, 204 }, 205 206 "set typed nil": { 207 []string{"set"}, 208 func() *Set { return nil }(), 209 false, 210 map[string]string{ 211 "set.#": "0", 212 }, 213 }, 214 215 "set resource": { 216 []string{"setDeep"}, 217 []interface{}{ 218 map[string]interface{}{ 219 "index": 10, 220 "value": "foo", 221 }, 222 map[string]interface{}{ 223 "index": 50, 224 "value": "bar", 225 }, 226 }, 227 false, 228 map[string]string{ 229 "setDeep.#": "2", 230 "setDeep.10.index": "10", 231 "setDeep.10.value": "foo", 232 "setDeep.50.index": "50", 233 "setDeep.50.value": "bar", 234 }, 235 }, 236 237 "set element": { 238 []string{"set", "5"}, 239 5, 240 true, 241 map[string]string{}, 242 }, 243 244 "full object": { 245 nil, 246 map[string]interface{}{ 247 "string": "foo", 248 "list": []interface{}{"foo", "bar"}, 249 }, 250 false, 251 map[string]string{ 252 "string": "foo", 253 "list.#": "2", 254 "list.0": "foo", 255 "list.1": "bar", 256 }, 257 }, 258 } 259 260 for name, tc := range cases { 261 w := &MapFieldWriter{Schema: schema} 262 err := w.WriteField(tc.Addr, tc.Value) 263 if err != nil != tc.Err { 264 t.Fatalf("%s: err: %s", name, err) 265 } 266 267 actual := w.Map() 268 if !reflect.DeepEqual(actual, tc.Out) { 269 t.Fatalf("%s: bad: %#v", name, actual) 270 } 271 } 272 } 273 274 func TestMapFieldWriterCleanSet(t *testing.T) { 275 schema := map[string]*Schema{ 276 "setDeep": &Schema{ 277 Type: TypeSet, 278 Elem: &Resource{ 279 Schema: map[string]*Schema{ 280 "index": &Schema{Type: TypeInt}, 281 "value": &Schema{Type: TypeString}, 282 }, 283 }, 284 Set: func(a interface{}) int { 285 return a.(map[string]interface{})["index"].(int) 286 }, 287 }, 288 } 289 290 values := []struct { 291 Addr []string 292 Value interface{} 293 Out map[string]string 294 }{ 295 { 296 []string{"setDeep"}, 297 []interface{}{ 298 map[string]interface{}{ 299 "index": 10, 300 "value": "foo", 301 }, 302 map[string]interface{}{ 303 "index": 50, 304 "value": "bar", 305 }, 306 }, 307 map[string]string{ 308 "setDeep.#": "2", 309 "setDeep.10.index": "10", 310 "setDeep.10.value": "foo", 311 "setDeep.50.index": "50", 312 "setDeep.50.value": "bar", 313 }, 314 }, 315 { 316 []string{"setDeep"}, 317 []interface{}{ 318 map[string]interface{}{ 319 "index": 20, 320 "value": "baz", 321 }, 322 map[string]interface{}{ 323 "index": 60, 324 "value": "qux", 325 }, 326 }, 327 map[string]string{ 328 "setDeep.#": "2", 329 "setDeep.20.index": "20", 330 "setDeep.20.value": "baz", 331 "setDeep.60.index": "60", 332 "setDeep.60.value": "qux", 333 }, 334 }, 335 { 336 []string{"setDeep"}, 337 []interface{}{ 338 map[string]interface{}{ 339 "index": 30, 340 "value": "one", 341 }, 342 map[string]interface{}{ 343 "index": 70, 344 "value": "two", 345 }, 346 }, 347 map[string]string{ 348 "setDeep.#": "2", 349 "setDeep.30.index": "30", 350 "setDeep.30.value": "one", 351 "setDeep.70.index": "70", 352 "setDeep.70.value": "two", 353 }, 354 }, 355 } 356 357 w := &MapFieldWriter{Schema: schema} 358 359 for n, tc := range values { 360 err := w.WriteField(tc.Addr, tc.Value) 361 if err != nil { 362 t.Fatalf("%d: err: %s", n, err) 363 } 364 365 actual := w.Map() 366 if !reflect.DeepEqual(actual, tc.Out) { 367 t.Fatalf("%d: bad: %#v", n, actual) 368 } 369 } 370 } 371 372 func TestMapFieldWriterCleanList(t *testing.T) { 373 schema := map[string]*Schema{ 374 "listDeep": &Schema{ 375 Type: TypeList, 376 Elem: &Resource{ 377 Schema: map[string]*Schema{ 378 "thing1": &Schema{Type: TypeString}, 379 "thing2": &Schema{Type: TypeString}, 380 }, 381 }, 382 }, 383 } 384 385 values := []struct { 386 Addr []string 387 Value interface{} 388 Out map[string]string 389 }{ 390 { 391 // Base list 392 []string{"listDeep"}, 393 []interface{}{ 394 map[string]interface{}{ 395 "thing1": "a", 396 "thing2": "b", 397 }, 398 map[string]interface{}{ 399 "thing1": "c", 400 "thing2": "d", 401 }, 402 map[string]interface{}{ 403 "thing1": "e", 404 "thing2": "f", 405 }, 406 map[string]interface{}{ 407 "thing1": "g", 408 "thing2": "h", 409 }, 410 }, 411 map[string]string{ 412 "listDeep.#": "4", 413 "listDeep.0.thing1": "a", 414 "listDeep.0.thing2": "b", 415 "listDeep.1.thing1": "c", 416 "listDeep.1.thing2": "d", 417 "listDeep.2.thing1": "e", 418 "listDeep.2.thing2": "f", 419 "listDeep.3.thing1": "g", 420 "listDeep.3.thing2": "h", 421 }, 422 }, 423 { 424 // Remove an element 425 []string{"listDeep"}, 426 []interface{}{ 427 map[string]interface{}{ 428 "thing1": "a", 429 "thing2": "b", 430 }, 431 map[string]interface{}{ 432 "thing1": "c", 433 "thing2": "d", 434 }, 435 map[string]interface{}{ 436 "thing1": "e", 437 "thing2": "f", 438 }, 439 }, 440 map[string]string{ 441 "listDeep.#": "3", 442 "listDeep.0.thing1": "a", 443 "listDeep.0.thing2": "b", 444 "listDeep.1.thing1": "c", 445 "listDeep.1.thing2": "d", 446 "listDeep.2.thing1": "e", 447 "listDeep.2.thing2": "f", 448 }, 449 }, 450 { 451 // Rewrite with missing keys. This should normally not be necessary, as 452 // hopefully the writers are writing zero values as necessary, but for 453 // brevity we want to make sure that what exists in the writer is exactly 454 // what the last write looked like coming from the provider. 455 []string{"listDeep"}, 456 []interface{}{ 457 map[string]interface{}{ 458 "thing1": "a", 459 }, 460 map[string]interface{}{ 461 "thing1": "c", 462 }, 463 map[string]interface{}{ 464 "thing1": "e", 465 }, 466 }, 467 map[string]string{ 468 "listDeep.#": "3", 469 "listDeep.0.thing1": "a", 470 "listDeep.1.thing1": "c", 471 "listDeep.2.thing1": "e", 472 }, 473 }, 474 } 475 476 w := &MapFieldWriter{Schema: schema} 477 478 for n, tc := range values { 479 err := w.WriteField(tc.Addr, tc.Value) 480 if err != nil { 481 t.Fatalf("%d: err: %s", n, err) 482 } 483 484 actual := w.Map() 485 if !reflect.DeepEqual(actual, tc.Out) { 486 t.Fatalf("%d: bad: %#v", n, actual) 487 } 488 } 489 } 490 491 func TestMapFieldWriterCleanMap(t *testing.T) { 492 schema := map[string]*Schema{ 493 "map": &Schema{ 494 Type: TypeMap, 495 }, 496 } 497 498 values := []struct { 499 Value interface{} 500 Out map[string]string 501 }{ 502 { 503 // Base map 504 map[string]interface{}{ 505 "thing1": "a", 506 "thing2": "b", 507 "thing3": "c", 508 "thing4": "d", 509 }, 510 map[string]string{ 511 "map.%": "4", 512 "map.thing1": "a", 513 "map.thing2": "b", 514 "map.thing3": "c", 515 "map.thing4": "d", 516 }, 517 }, 518 { 519 // Base map 520 map[string]interface{}{ 521 "thing1": "a", 522 "thing2": "b", 523 "thing4": "d", 524 }, 525 map[string]string{ 526 "map.%": "3", 527 "map.thing1": "a", 528 "map.thing2": "b", 529 "map.thing4": "d", 530 }, 531 }, 532 } 533 534 w := &MapFieldWriter{Schema: schema} 535 536 for n, tc := range values { 537 err := w.WriteField([]string{"map"}, tc.Value) 538 if err != nil { 539 t.Fatalf("%d: err: %s", n, err) 540 } 541 542 actual := w.Map() 543 if !reflect.DeepEqual(actual, tc.Out) { 544 t.Fatalf("%d: bad: %#v", n, actual) 545 } 546 } 547 }