github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/base/fill/struct_test.go (about) 1 package fill 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "reflect" 7 "testing" 8 "time" 9 10 "github.com/qri-io/dataset" 11 "gopkg.in/yaml.v2" 12 ) 13 14 func TestStruct(t *testing.T) { 15 jsonData := `{ 16 "Name": "test_name", 17 "ProfileID": "test_profile_id", 18 "Qri": "qri:0" 19 }` 20 21 data := make(map[string]interface{}) 22 err := json.Unmarshal([]byte(jsonData), &data) 23 if err != nil { 24 panic(err) 25 } 26 27 var ds dataset.Dataset 28 err = Struct(data, &ds) 29 if err != nil { 30 panic(err) 31 } 32 33 if ds.Name != "test_name" { 34 t.Errorf("expected: ds.Name should be \"test_name\", got: %s", ds.Name) 35 } 36 if ds.ProfileID != "test_profile_id" { 37 t.Errorf("expected: ds.ProfileID should be \"test_profile_id\", got: %s", ds.ProfileID) 38 } 39 if ds.Qri != "qri:0" { 40 t.Errorf("expected: ds.Qri should be \"qri:0\", got: %s", ds.Qri) 41 } 42 } 43 44 func TestInvalidTarget(t *testing.T) { 45 jsonData := `{ 46 "Name": "test_name", 47 "ProfileID": "test_profile_id", 48 "Qri": "qri:0" 49 }` 50 51 data := make(map[string]interface{}) 52 err := json.Unmarshal([]byte(jsonData), &data) 53 if err != nil { 54 panic(err) 55 } 56 57 var n int 58 err = Struct(data, &n) 59 expect := `can only assign fields to a struct` 60 if err == nil { 61 t.Fatalf("expected: error for unknown field, but no error returned") 62 } 63 if err.Error() != expect { 64 t.Errorf("expected: expect: \"%s\", got: \"%s\"", expect, err.Error()) 65 } 66 } 67 68 func TestFillCommitTimestamp(t *testing.T) { 69 jsonData := `{ 70 "Name": "test_commit_timestamp", 71 "Commit": { 72 "Timestamp": "1999-03-31T19:30:00.000Z" 73 } 74 }` 75 76 data := make(map[string]interface{}) 77 err := json.Unmarshal([]byte(jsonData), &data) 78 if err != nil { 79 panic(err) 80 } 81 82 var ds dataset.Dataset 83 err = Struct(data, &ds) 84 if err != nil { 85 panic(err) 86 } 87 88 loc := time.FixedZone("UTC", 0) 89 expect := time.Date(1999, 03, 31, 19, 30, 0, 0, loc) 90 91 if ds.Name != "test_commit_timestamp" { 92 t.Errorf("expected: ds.Name should be \"test_name\", got: %s", ds.Name) 93 } 94 if !ds.Commit.Timestamp.Equal(expect) { 95 t.Errorf("expected: timestamp expected %s, got: %s", expect, ds.Commit.Timestamp) 96 } 97 } 98 99 func TestFillInvalidTimestamp(t *testing.T) { 100 jsonData := `{ 101 "Name": "test_commit_timestamp", 102 "Commit": { 103 "Timestamp": "1999-03__1T19:30:00.000Z" 104 } 105 }` 106 107 data := make(map[string]interface{}) 108 err := json.Unmarshal([]byte(jsonData), &data) 109 if err != nil { 110 panic(err) 111 } 112 113 var ds dataset.Dataset 114 err = Struct(data, &ds) 115 expect := `at "Commit.Timestamp": could not parse time: "1999-03__1T19:30:00.000Z"` 116 if err == nil { 117 t.Fatalf("expected: error for unknown field, but no error returned") 118 } 119 if err.Error() != expect { 120 t.Errorf("expected: expect: \"%s\", got: \"%s\"", expect, err.Error()) 121 } 122 } 123 124 func TestStructInsensitive(t *testing.T) { 125 jsonData := `{ 126 "name": "test_name", 127 "pRoFiLeId": "test_profile_id", 128 "QRI": "qri:0" 129 }` 130 131 data := make(map[string]interface{}) 132 err := json.Unmarshal([]byte(jsonData), &data) 133 if err != nil { 134 panic(err) 135 } 136 137 var ds dataset.Dataset 138 err = Struct(data, &ds) 139 if err != nil { 140 panic(err) 141 } 142 143 if ds.Name != "test_name" { 144 t.Errorf("expected: ds.Name should be \"test_name\", got: %s", ds.Name) 145 } 146 if ds.ProfileID != "test_profile_id" { 147 t.Errorf("expected: ds.ProfileID should be \"test_profile_id\", got: %s", ds.ProfileID) 148 } 149 if ds.Qri != "qri:0" { 150 t.Errorf("expected: ds.Qri should be \"qri:0\", got: %s", ds.Qri) 151 } 152 } 153 154 func TestStructBlankValue(t *testing.T) { 155 jsonData := `{ 156 "Name": "test_name", 157 "ProfileID": null, 158 "Qri": "qri:0" 159 }` 160 161 data := make(map[string]interface{}) 162 err := json.Unmarshal([]byte(jsonData), &data) 163 if err != nil { 164 panic(err) 165 } 166 167 var ds dataset.Dataset 168 err = Struct(data, &ds) 169 if err != nil { 170 panic(err) 171 } 172 173 if ds.Name != "test_name" { 174 t.Errorf("expected: ds.Name should be \"test_name\", got: %s", ds.Name) 175 } 176 if ds.ProfileID != "" { 177 t.Errorf("expected: ds.ProfileID should be \"\", got: %s", ds.ProfileID) 178 } 179 if ds.Qri != "qri:0" { 180 t.Errorf("expected: ds.Qri should be \"qri:0\", got: %s", ds.Qri) 181 } 182 } 183 184 func TestStructUnknownFields(t *testing.T) { 185 jsonData := `{ 186 "Name": "test_name", 187 "ProfileID": "test_profile_id", 188 "Qri": "qri:0", 189 "Unknown": "value" 190 }` 191 192 data := make(map[string]interface{}) 193 err := json.Unmarshal([]byte(jsonData), &data) 194 if err != nil { 195 panic(err) 196 } 197 198 var ds dataset.Dataset 199 err = Struct(data, &ds) 200 if err == nil { 201 t.Errorf("expected: error for unknown field, but no error returned") 202 } 203 204 expect := `at "Unknown": not found in struct dataset.Dataset` 205 if err.Error() != expect { 206 t.Errorf("expected: expect: \"%s\", got: \"%s\"", expect, err.Error()) 207 } 208 } 209 210 func TestStructYaml(t *testing.T) { 211 yamlData := `name: test_name 212 profileID: test_profile_id 213 qri: qri:0 214 ` 215 216 data := make(map[string]interface{}) 217 err := yaml.Unmarshal([]byte(yamlData), &data) 218 if err != nil { 219 panic(err) 220 } 221 222 var ds dataset.Dataset 223 err = Struct(data, &ds) 224 if err != nil { 225 panic(err) 226 } 227 228 if ds.Name != "test_name" { 229 t.Errorf("expected: ds.Name should be \"test_name\", got: %s", ds.Name) 230 } 231 if ds.ProfileID != "test_profile_id" { 232 t.Errorf("expected: ds.ProfileID should be \"test_profile_id\", got: %s", ds.ProfileID) 233 } 234 if ds.Qri != "qri:0" { 235 t.Errorf("expected: ds.Qri should be \"qri:0\", got: %s", ds.Qri) 236 } 237 } 238 239 type Collection struct { 240 More map[string]interface{} 241 Name string 242 Age int 243 IsOn bool 244 Xpos float64 245 Ptr *int 246 Dict map[string]string 247 List []string 248 Blob []byte 249 Sub SubElement 250 Big int64 251 Ubig uint64 252 Pair [2]int 253 Cat string `json:"kitten"` 254 Dog string `json:"puppy,omitempty"` 255 } 256 257 type SubElement struct { 258 Num int 259 Things *map[string]string 260 Any interface{} 261 Text string 262 } 263 264 func (c *Collection) SetArbitrary(key string, val interface{}) error { 265 if c.More == nil { 266 c.More = make(map[string]interface{}) 267 } 268 c.More[key] = val 269 return nil 270 } 271 272 func TestFillArbitrarySetter(t *testing.T) { 273 jsonData := `{ 274 "Name": "Alice", 275 "Age": 42, 276 "Unknown": "value" 277 }` 278 279 data := make(map[string]interface{}) 280 err := json.Unmarshal([]byte(jsonData), &data) 281 if err != nil { 282 panic(err) 283 } 284 285 var c Collection 286 err = Struct(data, &c) 287 if err != nil { 288 panic(err) 289 } 290 291 if c.Name != "Alice" { 292 t.Errorf("expected: c.Name should be \"Alice\", got: %s", c.Name) 293 } 294 if c.Age != 42 { 295 t.Errorf("expected: c.Age should be 42, got: %d", c.Age) 296 } 297 if c.More["Unknown"] != "value" { 298 t.Errorf("expected: c.More[\"Unknown\"] should be \"value\", got: %s", c.More["Unknown"]) 299 } 300 } 301 302 func TestFillBoolean(t *testing.T) { 303 jsonData := `{ 304 "Name": "Bob", 305 "IsOn": true 306 }` 307 308 data := make(map[string]interface{}) 309 err := json.Unmarshal([]byte(jsonData), &data) 310 if err != nil { 311 panic(err) 312 } 313 314 var c Collection 315 err = Struct(data, &c) 316 if err != nil { 317 panic(err) 318 } 319 320 if c.Name != "Bob" { 321 t.Errorf("expected: c.Name should be \"Bob\", got: %s", c.Name) 322 } 323 if c.IsOn != true { 324 t.Errorf("expected: c.IsOn should be true, got: %v", c.IsOn) 325 } 326 } 327 328 func TestFillFloatingPoint(t *testing.T) { 329 jsonData := `{ 330 "Name": "Carol", 331 "Xpos": 6.283 332 }` 333 334 data := make(map[string]interface{}) 335 err := json.Unmarshal([]byte(jsonData), &data) 336 if err != nil { 337 panic(err) 338 } 339 340 var c Collection 341 err = Struct(data, &c) 342 if err != nil { 343 panic(err) 344 } 345 346 if c.Name != "Carol" { 347 t.Errorf("expected: c.Name should be \"Carol\", got: %s", c.Name) 348 } 349 if c.Xpos != 6.283 { 350 t.Errorf("expected: c.Xpos should be 6.283, got: %v", c.Xpos) 351 } 352 } 353 354 func TestFillInt64(t *testing.T) { 355 jsonData := `{ 356 "Big": 1234567890123456789, 357 "Ubig": 9934567890123456789 358 }` 359 360 data := make(map[string]interface{}) 361 err := json.Unmarshal([]byte(jsonData), &data) 362 if err != nil { 363 panic(err) 364 } 365 366 var c Collection 367 err = Struct(data, &c) 368 if err != nil { 369 panic(err) 370 } 371 372 if c.Big != 1234567890123456768 { 373 t.Errorf("expected: c.Big should be 1234567890123456768, got: %d", c.Big) 374 } 375 if c.Ubig != 9934567890123456512 { 376 t.Errorf("expected: c.Ubig should be 9934567890123456512, got: %d", c.Ubig) 377 } 378 } 379 380 func TestFillArray(t *testing.T) { 381 jsonData := `{ 382 "Pair": [3,4] 383 }` 384 385 data := make(map[string]interface{}) 386 err := json.Unmarshal([]byte(jsonData), &data) 387 if err != nil { 388 panic(err) 389 } 390 391 var c Collection 392 err = Struct(data, &c) 393 if err != nil { 394 panic(err) 395 } 396 397 if len(c.Pair) != 2 { 398 t.Errorf("expected: c.Pair should have two elements, got: %d", len(c.Pair)) 399 } 400 if c.Pair[0] != 3 { 401 t.Errorf("expected: c.Pair[0] should be 3, got: %d", c.Pair[0]) 402 } 403 if c.Pair[1] != 4 { 404 t.Errorf("expected: c.Pair[1] should be 4, got: %d", c.Pair[1]) 405 } 406 } 407 408 func TestFillArrayLengthError(t *testing.T) { 409 jsonData := `{ 410 "Pair": [3,4,5] 411 }` 412 413 data := make(map[string]interface{}) 414 err := json.Unmarshal([]byte(jsonData), &data) 415 if err != nil { 416 panic(err) 417 } 418 419 var c Collection 420 err = Struct(data, &c) 421 if err == nil { 422 t.Errorf("expected: error for wrong length, but no error returned") 423 } 424 425 expect := `at "Pair": need array of size 2, got size 3` 426 if err.Error() != expect { 427 t.Errorf("expected: expect: \"%s\", got: \"%s\"", expect, err.Error()) 428 } 429 } 430 431 func TestFillMetaKeywords(t *testing.T) { 432 jsonData := `{ 433 "Keywords": [ 434 "Test0", 435 "Test1", 436 "Test2" 437 ] 438 }` 439 440 data := make(map[string]interface{}) 441 err := json.Unmarshal([]byte(jsonData), &data) 442 if err != nil { 443 panic(err) 444 } 445 446 var meta dataset.Meta 447 err = Struct(data, &meta) 448 if err != nil { 449 panic(err) 450 } 451 452 expect := []string{"Test0", "Test1", "Test2"} 453 if !reflect.DeepEqual(meta.Keywords, expect) { 454 t.Errorf("expected: c.Keywords should expect: %s, got: %s", expect, meta.Keywords) 455 } 456 } 457 458 func TestFillMetaCitations(t *testing.T) { 459 jsonData := `{ 460 "Citations": [ 461 { 462 "Name": "A website", 463 "URL": "http://example.com", 464 "Email": "me@example.com" 465 } 466 ] 467 }` 468 469 data := make(map[string]interface{}) 470 err := json.Unmarshal([]byte(jsonData), &data) 471 if err != nil { 472 panic(err) 473 } 474 475 var meta dataset.Meta 476 err = Struct(data, &meta) 477 if err != nil { 478 panic(err) 479 } 480 481 expect := dataset.Meta{ 482 Citations: []*dataset.Citation{ 483 &dataset.Citation{ 484 Name: "A website", 485 URL: "http://example.com", 486 Email: "me@example.com", 487 }, 488 }, 489 } 490 if !reflect.DeepEqual(meta, expect) { 491 t.Errorf("expected: c.Keywords should expect: %s, got: %s", expect.Keywords, meta.Keywords) 492 } 493 } 494 495 func TestFillMapStringToString(t *testing.T) { 496 jsonData := `{ 497 "Dict": { 498 "cat": "meow", 499 "dog": "bark", 500 "eel": "zap" 501 } 502 }` 503 data := make(map[string]interface{}) 504 err := json.Unmarshal([]byte(jsonData), &data) 505 if err != nil { 506 panic(err) 507 } 508 509 var c Collection 510 err = Struct(data, &c) 511 if err != nil { 512 panic(err) 513 } 514 515 if len(c.Dict) != 3 { 516 t.Error("expected 3 elements in Dict") 517 } 518 if c.Dict["cat"] != "meow" { 519 t.Error("expected: Dict[\"cat\"] == \"meow\"") 520 } 521 } 522 523 func TestStringSlice(t *testing.T) { 524 jsonData := `{ 525 "List": ["a","b","c"] 526 }` 527 data := make(map[string]interface{}) 528 err := json.Unmarshal([]byte(jsonData), &data) 529 if err != nil { 530 panic(err) 531 } 532 533 var c Collection 534 err = Struct(data, &c) 535 if err != nil { 536 panic(err) 537 } 538 539 if len(c.List) != 3 { 540 t.Error("expected 3 elements in List") 541 } 542 if c.List[0] != "a" { 543 t.Error("expected: List[0] == \"a\"") 544 } 545 } 546 547 func TestByteSlice(t *testing.T) { 548 jsonData := `{ 549 "blob": "abcd" 550 }` 551 data := make(map[string]interface{}) 552 err := json.Unmarshal([]byte(jsonData), &data) 553 if err != nil { 554 panic(err) 555 } 556 557 var c Collection 558 err = Struct(data, &c) 559 if err != nil { 560 panic(err) 561 } 562 563 if len(c.Blob) != 4 { 564 t.Error("expected size 4 for Blob") 565 } 566 if bytes.Compare(c.Blob, []byte("abcd")) != 0 { 567 t.Error("expected: Blob == \"abcd\"") 568 } 569 570 // Binary data may also be assigned from a slice of bytes 571 data = map[string]interface{}{ 572 "blob": []byte{0x01, 0x02, 0x03, 0x04, 0x05}, 573 } 574 c = Collection{} 575 err = Struct(data, &c) 576 if err != nil { 577 panic(err) 578 } 579 580 if len(c.Blob) != 5 { 581 t.Error("expected size 5 for Blob") 582 } 583 if bytes.Compare(c.Blob, []byte{0x01, 0x02, 0x03, 0x04, 0x05}) != 0 { 584 t.Error("expected: Blob == \"\\x01, \\x02, \\x03, \\x04, \\x05\"") 585 } 586 587 // Binary data can't be assigned an integer, that's an error 588 data = map[string]interface{}{ 589 "blob": 3456, 590 } 591 c = Collection{} 592 err = Struct(data, &c) 593 expect := `at "Blob": need type byte slice, value 3456` 594 if err == nil { 595 t.Fatalf("expected: error for wrong type, but no error returned") 596 } 597 if err.Error() != expect { 598 t.Errorf("expected: expect: \"%s\", got: \"%s\"", expect, err.Error()) 599 } 600 } 601 602 func TestNilStringSlice(t *testing.T) { 603 jsonData := `{ 604 "List": null 605 }` 606 data := make(map[string]interface{}) 607 err := json.Unmarshal([]byte(jsonData), &data) 608 if err != nil { 609 panic(err) 610 } 611 612 var c Collection 613 err = Struct(data, &c) 614 if err != nil { 615 panic(err) 616 } 617 618 if c.List != nil { 619 t.Error("expected null List") 620 } 621 } 622 623 func TestNilMap(t *testing.T) { 624 jsonData := `{ 625 "Dict": null 626 }` 627 data := make(map[string]interface{}) 628 err := json.Unmarshal([]byte(jsonData), &data) 629 if err != nil { 630 panic(err) 631 } 632 633 var c Collection 634 err = Struct(data, &c) 635 if err != nil { 636 panic(err) 637 } 638 639 if c.Dict != nil { 640 t.Error("expected null Dict") 641 } 642 } 643 644 func TestNilPointer(t *testing.T) { 645 jsonData := `{ 646 "Ptr": null 647 }` 648 data := make(map[string]interface{}) 649 err := json.Unmarshal([]byte(jsonData), &data) 650 if err != nil { 651 panic(err) 652 } 653 654 var c Collection 655 err = Struct(data, &c) 656 if err != nil { 657 panic(err) 658 } 659 660 if c.Ptr != nil { 661 t.Error("expected null Ptr") 662 } 663 } 664 665 func TestFillErrorMessageOnWrongType(t *testing.T) { 666 jsonData := `{ 667 "Age": "abc" 668 }` 669 670 data := make(map[string]interface{}) 671 err := json.Unmarshal([]byte(jsonData), &data) 672 if err != nil { 673 panic(err) 674 } 675 676 var c Collection 677 err = Struct(data, &c) 678 if err == nil { 679 t.Errorf("expected error, did not get an error") 680 } 681 expect := `at "Age": need int, got string: "abc"` 682 if err.Error() != expect { 683 t.Errorf("expected error: \"%s\", got: \"%s\"", expect, err.Error()) 684 } 685 } 686 687 func TestFillErrorMessageOnWrongSubfield(t *testing.T) { 688 jsonData := `{ 689 "Sub": { 690 "Num": false 691 } 692 }` 693 694 data := make(map[string]interface{}) 695 err := json.Unmarshal([]byte(jsonData), &data) 696 if err != nil { 697 panic(err) 698 } 699 700 var c Collection 701 err = Struct(data, &c) 702 if err == nil { 703 t.Errorf("expected error, did not get an error") 704 } 705 expect := `at "Sub.Num": need int, got bool: false` 706 if err.Error() != expect { 707 t.Errorf("expected error: \"%s\", got: \"%s\"", expect, err.Error()) 708 } 709 } 710 711 func TestFillMulitpleErrors(t *testing.T) { 712 jsonData := `{ 713 "Age": "abc", 714 "Sub": { 715 "Num": false 716 } 717 }` 718 719 data := make(map[string]interface{}) 720 err := json.Unmarshal([]byte(jsonData), &data) 721 if err != nil { 722 panic(err) 723 } 724 725 var c Collection 726 err = Struct(data, &c) 727 if err == nil { 728 t.Errorf("expected error, did not get an error") 729 } 730 expect := `at "Age": need int, got string: "abc" 731 at "Sub.Num": need int, got bool: false` 732 if err.Error() != expect { 733 t.Errorf("expected error: \"%s\", got: \"%s\"", expect, err.Error()) 734 } 735 } 736 737 func TestFillAttrName(t *testing.T) { 738 jsonData := `{ 739 "kitten": "meow", 740 "puppy": "bark" 741 }` 742 743 // json Unmarshal will look at field tags to get json keys 744 var c Collection 745 err := json.Unmarshal([]byte(jsonData), &c) 746 if err != nil { 747 panic(err) 748 } 749 750 if c.Cat != "meow" { 751 t.Errorf("exepcted: c.Cat should be \"meow\", got %s", c.Cat) 752 } 753 if c.Dog != "bark" { 754 t.Errorf("exepcted: c.Dog should be \"bark\", got %s", c.Dog) 755 } 756 757 // fill Struct should do the same thing, looking at field tags 758 data := make(map[string]interface{}) 759 err = json.Unmarshal([]byte(jsonData), &data) 760 if err != nil { 761 panic(err) 762 } 763 764 c = Collection{} 765 err = Struct(data, &c) 766 if err != nil { 767 panic(err) 768 } 769 770 if c.Cat != "meow" { 771 t.Errorf("exepcted: c.Cat should be \"meow\", got %s", c.Cat) 772 } 773 if c.Dog != "bark" { 774 t.Errorf("exepcted: c.Dog should be \"bark\", got %s", c.Dog) 775 } 776 if len(c.More) != 0 { 777 t.Errorf("expected: no unused keys, got %v", c.More) 778 } 779 } 780 781 func TestFillSubSection(t *testing.T) { 782 jsonData := `{ 783 "Sub": { 784 "Num": 7 785 } 786 }` 787 788 data := make(map[string]interface{}) 789 err := json.Unmarshal([]byte(jsonData), &data) 790 if err != nil { 791 panic(err) 792 } 793 794 var c Collection 795 err = Struct(data, &c) 796 if err != nil { 797 panic(err) 798 } 799 800 if c.Sub.Num != 7 { 801 t.Errorf("expected: c.Sub.Num should be 7, got: %d", c.Sub.Num) 802 } 803 } 804 805 func TestFillPointerToMap(t *testing.T) { 806 jsonData := `{ 807 "Things": { 808 "a": "apple", 809 "b": "banana" 810 } 811 }` 812 813 data := make(map[string]interface{}) 814 err := json.Unmarshal([]byte(jsonData), &data) 815 if err != nil { 816 panic(err) 817 } 818 819 var s SubElement 820 err = Struct(data, &s) 821 if err != nil { 822 panic(err) 823 } 824 825 if s.Things == nil { 826 t.Errorf("expected: s.Things should be non-nil") 827 } 828 if (*s.Things)["a"] != "apple" { 829 t.Errorf("expected: s.Things[\"a\"] should be \"apple\"") 830 } 831 if (*s.Things)["b"] != "banana" { 832 t.Errorf("expected: s.Things[\"b\"] should be \"banana\"") 833 } 834 } 835 836 func TestFillInterface(t *testing.T) { 837 // Any can be a float 838 jsonData := `{ 839 "Any": 123.4 840 }` 841 data := make(map[string]interface{}) 842 err := json.Unmarshal([]byte(jsonData), &data) 843 if err != nil { 844 panic(err) 845 } 846 847 var s SubElement 848 err = Struct(data, &s) 849 if err != nil { 850 panic(err) 851 } 852 853 if s.Any != 123.4 { 854 t.Errorf("expected: s.Any should be 123, got %v of %s", s.Any, reflect.TypeOf(s.Any)) 855 } 856 857 // Any can be a string 858 jsonData = `{ 859 "Any": "abc" 860 }` 861 data = make(map[string]interface{}) 862 err = json.Unmarshal([]byte(jsonData), &data) 863 if err != nil { 864 panic(err) 865 } 866 867 s = SubElement{} 868 err = Struct(data, &s) 869 if err != nil { 870 panic(err) 871 } 872 873 if s.Any != "abc" { 874 t.Errorf("expected: s.Any should be \"abc\", got %v of %s", s.Any, reflect.TypeOf(s.Any)) 875 } 876 } 877 878 func TestFillYamlFields(t *testing.T) { 879 yamlData := ` 880 name: abc 881 age: 42 882 xpos: 3.51 883 big: 1234567890123456 884 ` 885 data := make(map[string]interface{}) 886 err := yaml.Unmarshal([]byte(yamlData), &data) 887 if err != nil { 888 panic(err) 889 } 890 891 var c Collection 892 err = Struct(data, &c) 893 if err != nil { 894 panic(err) 895 } 896 897 if c.Name != "abc" { 898 t.Errorf("expected: c.Name should be \"abc\", got: %s", c.Name) 899 } 900 if c.Age != 42 { 901 t.Errorf("expected: c.Name should be 42, got: %d", c.Age) 902 } 903 if c.Xpos != 3.51 { 904 t.Errorf("expected: c.Xpos should be 3.51, got: %f", c.Xpos) 905 } 906 if c.Big != 1234567890123456 { 907 t.Errorf("expected: c.Big should be 1234567890123456, got: %d", c.Big) 908 } 909 } 910 911 func TestFillYamlMap(t *testing.T) { 912 yamlData := ` 913 name: more 914 dict: 915 a: apple 916 b: banana 917 sub: 918 num: 7 919 things: 920 c: cat 921 d: dog 922 ` 923 data := make(map[string]interface{}) 924 err := yaml.Unmarshal([]byte(yamlData), &data) 925 if err != nil { 926 panic(err) 927 } 928 929 var c Collection 930 err = Struct(data, &c) 931 if err != nil { 932 panic(err) 933 } 934 935 if c.Name != "more" { 936 t.Errorf("expected: c.Name should be \"abc\", got: %s", c.Name) 937 } 938 if len(c.Dict) != 2 { 939 t.Errorf("expected: len(c.Dict) should be 2, got: %d", len(c.Dict)) 940 } 941 if c.Dict["a"] != "apple" { 942 t.Errorf("expected: c.Dict[\"a\"] should be \"apple\", got: %s", c.Dict["a"]) 943 } 944 if c.Dict["b"] != "banana" { 945 t.Errorf("expected: c.Dict[\"b\"] should be \"banana\", got: %s", c.Dict["b"]) 946 } 947 948 if c.Sub.Num != 7 { 949 t.Errorf("expected: c.Sub.Num should be 7, got: %d", c.Sub.Num) 950 } 951 if len(*c.Sub.Things) != 2 { 952 t.Errorf("expected: len(c.Sub.Things) should be 2, got: %d", len(*c.Sub.Things)) 953 } 954 if (*c.Sub.Things)["c"] != "cat" { 955 t.Errorf("expected: c.Sub.Things[\"c\"] should be \"cat\", got: %s", (*c.Sub.Things)["c"]) 956 } 957 if (*c.Sub.Things)["d"] != "dog" { 958 t.Errorf("expected: c.Sub.Things[\"d\"] should be \"dog\", got: %s", (*c.Sub.Things)["d"]) 959 } 960 } 961 962 func TestFillYamlMapsHaveStringKeys(t *testing.T) { 963 yamlData := ` 964 name: schema 965 sub: 966 any: 967 type: object 968 inner: 969 e: eel 970 f: frog 971 ` 972 data := make(map[string]interface{}) 973 err := yaml.Unmarshal([]byte(yamlData), &data) 974 if err != nil { 975 panic(err) 976 } 977 978 var c Collection 979 err = Struct(data, &c) 980 if err != nil { 981 panic(err) 982 } 983 984 if c.Name != "schema" { 985 t.Errorf("expected: c.Name should be \"schema\", got: %s", c.Name) 986 } 987 m, ok := c.Sub.Any.(map[string]interface{}) 988 if !ok { 989 t.Fatalf("expected: c.Sub.Any should be a map[string]interface{}, got: %s", 990 reflect.TypeOf(c.Sub.Any)) 991 } 992 if m["type"] != "object" { 993 t.Errorf("expected: c.Sub.Any[\"type\"] should be \"object\", got: %d", m["type"]) 994 } 995 996 // This is asserting that maps within data structures also have string keys, despite 997 // the fact that YAML deserialized this, and YAML always uses interface{} keys. 998 m, ok = m["inner"].(map[string]interface{}) 999 if !ok { 1000 t.Fatalf("expected: Inner should be a map[string]interface{}, got: %s", 1001 reflect.TypeOf(m["inner"])) 1002 } 1003 if m["e"] != "eel" { 1004 t.Errorf("expected: c.Sub.Any[\"e\"] should be \"eel\", got: %d", m["e"]) 1005 } 1006 if m["f"] != "frog" { 1007 t.Errorf("expected: c.Sub.Any[\"f\"] should be \"frog\", got: %d", m["f"]) 1008 } 1009 }