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  }