github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/g/struct_test.go (about)

     1  package g_test
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/angenalZZZ/gofunc/f"
     6  	"github.com/angenalZZZ/gofunc/g"
     7  	"reflect"
     8  	"testing"
     9  	"time"
    10  )
    11  
    12  func TestMapNonStruct(t *testing.T) {
    13  	foo := []string{"foo"}
    14  
    15  	defer func() {
    16  		err := recover()
    17  		if err == nil {
    18  			t.Error("Passing a non struct into Map should panic")
    19  		}
    20  	}()
    21  
    22  	// this should panic. We are going to recover and and test it
    23  	_ = g.Maps(foo)
    24  }
    25  
    26  func TestStructIndexes(t *testing.T) {
    27  	type C struct {
    28  		something int
    29  		Props     map[string]interface{}
    30  	}
    31  
    32  	defer func() {
    33  		err := recover()
    34  		if err != nil {
    35  			fmt.Printf("err %+v\n", err)
    36  			t.Error("Using mixed indexes should not panic")
    37  		}
    38  	}()
    39  
    40  	// They should not panic
    41  	_ = g.Maps(&C{})
    42  	_ = g.Fields(&C{})
    43  	_ = g.Values(&C{})
    44  	_ = g.IsZero(&C{})
    45  	_ = g.HasZero(&C{})
    46  }
    47  
    48  func TestMap(t *testing.T) {
    49  	var T = struct {
    50  		A string
    51  		B int
    52  		C bool
    53  	}{
    54  		A: "a-value",
    55  		B: 2,
    56  		C: true,
    57  	}
    58  
    59  	a := g.Maps(T)
    60  
    61  	if typ := reflect.TypeOf(a).Kind(); typ != reflect.Map {
    62  		t.Errorf("Map should return a map type, got: %v", typ)
    63  	}
    64  
    65  	// we have three fields
    66  	if len(a) != 3 {
    67  		t.Errorf("Map should return a map of len 3, got: %d", len(a))
    68  	}
    69  
    70  	for _, val := range []interface{}{"a-value", 2, true} {
    71  		if !f.MapValuesContains(a, val) {
    72  			t.Errorf("Map should have the value %v", val)
    73  		}
    74  	}
    75  
    76  }
    77  
    78  func TestMap_Tag(t *testing.T) {
    79  	var T = struct {
    80  		A string `struct:"x"`
    81  		B int    `struct:"y"`
    82  		C bool   `struct:"z"`
    83  	}{
    84  		A: "a-value",
    85  		B: 2,
    86  		C: true,
    87  	}
    88  
    89  	a := g.Maps(T)
    90  
    91  	for _, key := range []string{"x", "y", "z"} {
    92  		if !f.MapKeysContains(a, key) {
    93  			t.Errorf("Map should have the key %v", key)
    94  		}
    95  	}
    96  
    97  }
    98  
    99  func TestMap_CustomTag(t *testing.T) {
   100  	var T = struct {
   101  		A string `json:"x"`
   102  		B int    `json:"y"`
   103  		C bool   `json:"z"`
   104  		D struct {
   105  			E string `json:"jkl"`
   106  		} `json:"nested"`
   107  	}{
   108  		A: "a-value",
   109  		B: 2,
   110  		C: true,
   111  	}
   112  	T.D.E = "e-value"
   113  
   114  	s := g.NewStruct(T)
   115  	s.TagName = "json"
   116  
   117  	a := s.Maps()
   118  
   119  	inMap := func(key interface{}) bool {
   120  		for k := range a {
   121  			if reflect.DeepEqual(k, key) {
   122  				return true
   123  			}
   124  		}
   125  		return false
   126  	}
   127  
   128  	for _, key := range []string{"x", "y", "z"} {
   129  		if !inMap(key) {
   130  			t.Errorf("Map should have the key %v", key)
   131  		}
   132  	}
   133  
   134  	nested, ok := a["nested"].(map[string]interface{})
   135  	if !ok {
   136  		t.Fatalf("Map should contain the D field that is tagged as 'nested'")
   137  	}
   138  
   139  	e, ok := nested["jkl"].(string)
   140  	if !ok {
   141  		t.Fatalf("Map should contain the D.E field that is tagged as 'jkl'")
   142  	}
   143  
   144  	if e != "e-value" {
   145  		t.Errorf("D.E field should be equal to 'e-value', got: '%v'", e)
   146  	}
   147  
   148  }
   149  
   150  func TestMap_MultipleCustomTag(t *testing.T) {
   151  	var A = struct {
   152  		X string `aa:"ax"`
   153  	}{"a_value"}
   154  
   155  	aStruct := g.NewStruct(A)
   156  	aStruct.TagName = "aa"
   157  
   158  	var B = struct {
   159  		X string `bb:"bx"`
   160  	}{"b_value"}
   161  
   162  	bStruct := g.NewStruct(B)
   163  	bStruct.TagName = "bb"
   164  
   165  	a, b := aStruct.Maps(), bStruct.Maps()
   166  	if !reflect.DeepEqual(a, map[string]interface{}{"ax": "a_value"}) {
   167  		t.Error("Map should have field ax with value a_value")
   168  	}
   169  
   170  	if !reflect.DeepEqual(b, map[string]interface{}{"bx": "b_value"}) {
   171  		t.Error("Map should have field bx with value b_value")
   172  	}
   173  }
   174  
   175  func TestMap_OmitEmpty(t *testing.T) {
   176  	type A struct {
   177  		Name  string
   178  		Value string    `struct:",omitempty"`
   179  		Time  time.Time `struct:",omitempty"`
   180  	}
   181  	a := A{}
   182  
   183  	m := g.Maps(a)
   184  
   185  	_, ok := m["Value"].(map[string]interface{})
   186  	if ok {
   187  		t.Error("Map should not contain the Value field that is tagged as omitempty")
   188  	}
   189  
   190  	_, ok = m["Time"].(map[string]interface{})
   191  	if ok {
   192  		t.Error("Map should not contain the Time field that is tagged as omitempty")
   193  	}
   194  }
   195  
   196  func TestMap_OmitNested(t *testing.T) {
   197  	type A struct {
   198  		Name  string
   199  		Value string
   200  		Time  time.Time `struct:",omitnested"`
   201  	}
   202  	a := A{Time: time.Now()}
   203  
   204  	type B struct {
   205  		Desc string
   206  		A    A
   207  	}
   208  	b := &B{A: a}
   209  
   210  	m := g.Maps(b)
   211  
   212  	in, ok := m["A"].(map[string]interface{})
   213  	if !ok {
   214  		t.Error("Map nested struct is not available in the map")
   215  	}
   216  
   217  	// should not happen
   218  	if _, ok := in["Time"].(map[string]interface{}); ok {
   219  		t.Error("Map nested struct should omit recursiving parsing of Time")
   220  	}
   221  
   222  	if _, ok := in["Time"].(time.Time); !ok {
   223  		t.Error("Map nested struct should stop parsing of Time at is current value")
   224  	}
   225  }
   226  
   227  func TestMap_Nested(t *testing.T) {
   228  	type A struct {
   229  		Name string
   230  	}
   231  	a := &A{Name: "example"}
   232  
   233  	type B struct {
   234  		A *A
   235  	}
   236  	b := &B{A: a}
   237  
   238  	m := g.Maps(b)
   239  
   240  	if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map {
   241  		t.Errorf("Map should return a map type, got: %v", typ)
   242  	}
   243  
   244  	in, ok := m["A"].(map[string]interface{})
   245  	if !ok {
   246  		t.Error("Map nested struct is not available in the map")
   247  	}
   248  
   249  	if name := in["Name"].(string); name != "example" {
   250  		t.Errorf("Map nested struct's name field should give example, got: %s", name)
   251  	}
   252  }
   253  
   254  func TestMap_NestedMapWithStructValues(t *testing.T) {
   255  	type A struct {
   256  		Name string
   257  	}
   258  
   259  	type B struct {
   260  		A map[string]*A
   261  	}
   262  
   263  	a := &A{Name: "example"}
   264  
   265  	b := &B{
   266  		A: map[string]*A{
   267  			"example_key": a,
   268  		},
   269  	}
   270  
   271  	m := g.Maps(b)
   272  
   273  	if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map {
   274  		t.Errorf("Map should return a map type, got: %v", typ)
   275  	}
   276  
   277  	in, ok := m["A"].(map[string]interface{})
   278  	if !ok {
   279  		t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["A"])
   280  	}
   281  
   282  	example := in["example_key"].(map[string]interface{})
   283  	if name := example["Name"].(string); name != "example" {
   284  		t.Errorf("Map nested struct's name field should give example, got: %s", name)
   285  	}
   286  }
   287  
   288  func TestMap_NestedMapWithStringValues(t *testing.T) {
   289  	type B struct {
   290  		Foo map[string]string
   291  	}
   292  
   293  	type A struct {
   294  		B *B
   295  	}
   296  
   297  	b := &B{
   298  		Foo: map[string]string{
   299  			"example_key": "example",
   300  		},
   301  	}
   302  
   303  	a := &A{B: b}
   304  
   305  	m := g.Maps(a)
   306  
   307  	if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map {
   308  		t.Errorf("Map should return a map type, got: %v", typ)
   309  	}
   310  
   311  	in, ok := m["B"].(map[string]interface{})
   312  	if !ok {
   313  		t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["B"])
   314  	}
   315  
   316  	foo := in["Foo"].(map[string]string)
   317  	if name := foo["example_key"]; name != "example" {
   318  		t.Errorf("Map nested struct's name field should give example, got: %s", name)
   319  	}
   320  }
   321  func TestMap_NestedMapWithInterfaceValues(t *testing.T) {
   322  	type B struct {
   323  		Foo map[string]interface{}
   324  	}
   325  
   326  	type A struct {
   327  		B *B
   328  	}
   329  
   330  	b := &B{
   331  		Foo: map[string]interface{}{
   332  			"example_key": "example",
   333  		},
   334  	}
   335  
   336  	a := &A{B: b}
   337  
   338  	m := g.Maps(a)
   339  
   340  	if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map {
   341  		t.Errorf("Map should return a map type, got: %v", typ)
   342  	}
   343  
   344  	in, ok := m["B"].(map[string]interface{})
   345  	if !ok {
   346  		t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["B"])
   347  	}
   348  
   349  	foo := in["Foo"].(map[string]interface{})
   350  	if name := foo["example_key"]; name != "example" {
   351  		t.Errorf("Map nested struct's name field should give example, got: %s", name)
   352  	}
   353  }
   354  
   355  func TestMap_NestedMapWithSliceIntValues(t *testing.T) {
   356  	type B struct {
   357  		Foo map[string][]int
   358  	}
   359  
   360  	type A struct {
   361  		B *B
   362  	}
   363  
   364  	b := &B{
   365  		Foo: map[string][]int{
   366  			"example_key": {80},
   367  		},
   368  	}
   369  
   370  	a := &A{B: b}
   371  
   372  	m := g.Maps(a)
   373  
   374  	if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map {
   375  		t.Errorf("Map should return a map type, got: %v", typ)
   376  	}
   377  
   378  	in, ok := m["B"].(map[string]interface{})
   379  	if !ok {
   380  		t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["B"])
   381  	}
   382  
   383  	foo := in["Foo"].(map[string][]int)
   384  	if name := foo["example_key"]; name[0] != 80 {
   385  		t.Errorf("Map nested struct's name field should give example, got: %v", name)
   386  	}
   387  }
   388  
   389  func TestMap_NestedMapWithSliceStructValues(t *testing.T) {
   390  	type address struct {
   391  		Country string `struct:"country"`
   392  	}
   393  
   394  	type B struct {
   395  		Foo map[string][]address
   396  	}
   397  
   398  	type A struct {
   399  		B *B
   400  	}
   401  
   402  	b := &B{
   403  		Foo: map[string][]address{
   404  			"example_key": {
   405  				{Country: "Turkey"},
   406  			},
   407  		},
   408  	}
   409  
   410  	a := &A{B: b}
   411  	m := g.Maps(a)
   412  
   413  	if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map {
   414  		t.Errorf("Map should return a map type, got: %v", typ)
   415  	}
   416  
   417  	in, ok := m["B"].(map[string]interface{})
   418  	if !ok {
   419  		t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["B"])
   420  	}
   421  
   422  	foo := in["Foo"].(map[string]interface{})
   423  
   424  	addresses := foo["example_key"].([]interface{})
   425  
   426  	addr, ok := addresses[0].(map[string]interface{})
   427  	if !ok {
   428  		t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["B"])
   429  	}
   430  
   431  	if _, exists := addr["country"]; !exists {
   432  		t.Errorf("Expecting country, but found Country")
   433  	}
   434  }
   435  
   436  func TestMap_NestedSliceWithStructValues(t *testing.T) {
   437  	type address struct {
   438  		Country string `struct:"customCountryName"`
   439  	}
   440  
   441  	type person struct {
   442  		Name      string    `struct:"name"`
   443  		Addresses []address `struct:"addresses"`
   444  	}
   445  
   446  	p := person{
   447  		Name: "test",
   448  		Addresses: []address{
   449  			{Country: "England"},
   450  			{Country: "Italy"},
   451  		},
   452  	}
   453  	mp := g.Maps(p)
   454  
   455  	mpAddresses := mp["addresses"].([]interface{})
   456  	if _, exists := mpAddresses[0].(map[string]interface{})["Country"]; exists {
   457  		t.Errorf("Expecting customCountryName, but found Country")
   458  	}
   459  
   460  	if _, exists := mpAddresses[0].(map[string]interface{})["customCountryName"]; !exists {
   461  		t.Errorf("customCountryName key not found")
   462  	}
   463  }
   464  
   465  func TestMap_NestedSliceWithPointerOfStructValues(t *testing.T) {
   466  	type address struct {
   467  		Country string `struct:"customCountryName"`
   468  	}
   469  
   470  	type person struct {
   471  		Name      string     `struct:"name"`
   472  		Addresses []*address `struct:"addresses"`
   473  	}
   474  
   475  	p := person{
   476  		Name: "test",
   477  		Addresses: []*address{
   478  			{Country: "England"},
   479  			{Country: "Italy"},
   480  		},
   481  	}
   482  	mp := g.Maps(p)
   483  
   484  	mpAddresses := mp["addresses"].([]interface{})
   485  	if _, exists := mpAddresses[0].(map[string]interface{})["Country"]; exists {
   486  		t.Errorf("Expecting customCountryName, but found Country")
   487  	}
   488  
   489  	if _, exists := mpAddresses[0].(map[string]interface{})["customCountryName"]; !exists {
   490  		t.Errorf("customCountryName key not found")
   491  	}
   492  }
   493  
   494  func TestMap_NestedSliceWithIntValues(t *testing.T) {
   495  	type person struct {
   496  		Name  string `struct:"name"`
   497  		Ports []int  `struct:"ports"`
   498  	}
   499  
   500  	p := person{
   501  		Name:  "test",
   502  		Ports: []int{80},
   503  	}
   504  	m := g.Maps(p)
   505  
   506  	ports, ok := m["ports"].([]int)
   507  	if !ok {
   508  		t.Errorf("Nested type of map should be of type []int, have %T", m["ports"])
   509  	}
   510  
   511  	if ports[0] != 80 {
   512  		t.Errorf("Map nested struct's ports field should give 80, got: %v", ports)
   513  	}
   514  }
   515  
   516  func TestMap_Anonymous(t *testing.T) {
   517  	type A struct {
   518  		Name string
   519  	}
   520  	a := &A{Name: "example"}
   521  
   522  	type B struct {
   523  		*A
   524  	}
   525  	b := &B{}
   526  	b.A = a
   527  
   528  	m := g.Maps(b)
   529  
   530  	if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map {
   531  		t.Errorf("Map should return a map type, got: %v", typ)
   532  	}
   533  
   534  	in, ok := m["A"].(map[string]interface{})
   535  	if !ok {
   536  		t.Error("Embedded struct is not available in the map")
   537  	}
   538  
   539  	if name := in["Name"].(string); name != "example" {
   540  		t.Errorf("Embedded A struct's Name field should give example, got: %s", name)
   541  	}
   542  }
   543  
   544  func TestMap_Flatnested(t *testing.T) {
   545  	type A struct {
   546  		Name string
   547  	}
   548  	a := A{Name: "example"}
   549  
   550  	type B struct {
   551  		A `struct:",flatten"`
   552  		C int
   553  	}
   554  	b := &B{C: 123}
   555  	b.A = a
   556  
   557  	m := g.Maps(b)
   558  
   559  	_, ok := m["A"].(map[string]interface{})
   560  	if ok {
   561  		t.Error("Embedded A struct with tag flatten has to be flat in the map")
   562  	}
   563  
   564  	expectedMap := map[string]interface{}{"Name": "example", "C": 123}
   565  	if !reflect.DeepEqual(m, expectedMap) {
   566  		t.Errorf("The exprected map %+v does't correspond to %+v", expectedMap, m)
   567  	}
   568  
   569  }
   570  
   571  func TestMap_FlatnestedOverwrite(t *testing.T) {
   572  	type A struct {
   573  		Name string
   574  	}
   575  	a := A{Name: "example"}
   576  
   577  	type B struct {
   578  		A    `struct:",flatten"`
   579  		Name string
   580  		C    int
   581  	}
   582  	b := &B{C: 123, Name: "bName"}
   583  	b.A = a
   584  
   585  	m := g.Maps(b)
   586  
   587  	_, ok := m["A"].(map[string]interface{})
   588  	if ok {
   589  		t.Error("Embedded A struct with tag flatten has to be flat in the map")
   590  	}
   591  
   592  	expectedMap := map[string]interface{}{"Name": "bName", "C": 123}
   593  	if !reflect.DeepEqual(m, expectedMap) {
   594  		t.Errorf("The exprected map %+v does't correspond to %+v", expectedMap, m)
   595  	}
   596  }
   597  
   598  func TestMap_TimeField(t *testing.T) {
   599  	type A struct {
   600  		CreatedAt time.Time
   601  	}
   602  
   603  	a := &A{CreatedAt: time.Now().UTC()}
   604  	m := g.Maps(a)
   605  
   606  	_, ok := m["CreatedAt"].(time.Time)
   607  	if !ok {
   608  		t.Error("Time field must be final")
   609  	}
   610  }
   611  
   612  func TestFillMap(t *testing.T) {
   613  	var T = struct {
   614  		A string
   615  		B int
   616  		C bool
   617  	}{
   618  		A: "a-value",
   619  		B: 2,
   620  		C: true,
   621  	}
   622  
   623  	a := make(map[string]interface{}, 0)
   624  	g.AsMap(T, a)
   625  
   626  	// we have three fields
   627  	if len(a) != 3 {
   628  		t.Errorf("AsMap should fill a map of len 3, got: %d", len(a))
   629  	}
   630  
   631  	inMap := func(val interface{}) bool {
   632  		for _, v := range a {
   633  			if reflect.DeepEqual(v, val) {
   634  				return true
   635  			}
   636  		}
   637  
   638  		return false
   639  	}
   640  
   641  	for _, val := range []interface{}{"a-value", 2, true} {
   642  		if !inMap(val) {
   643  			t.Errorf("AsMap should have the value %v", val)
   644  		}
   645  	}
   646  }
   647  
   648  func TestFillMap_Nil(t *testing.T) {
   649  	var T = struct {
   650  		A string
   651  		B int
   652  		C bool
   653  	}{
   654  		A: "a-value",
   655  		B: 2,
   656  		C: true,
   657  	}
   658  
   659  	defer func() {
   660  		err := recover()
   661  		if err != nil {
   662  			t.Error("AsMap should not panic if a nil map is passed")
   663  		}
   664  	}()
   665  
   666  	// nil should no
   667  	g.AsMap(T, nil)
   668  }
   669  
   670  func TestStruct(t *testing.T) {
   671  	var T = struct{}{}
   672  
   673  	if !g.IsStruct(T) {
   674  		t.Errorf("T should be a struct, got: %T", T)
   675  	}
   676  
   677  	if !g.IsStruct(&T) {
   678  		t.Errorf("T should be a struct, got: %T", T)
   679  	}
   680  
   681  }
   682  
   683  func TestValues(t *testing.T) {
   684  	var T = struct {
   685  		A string
   686  		B int
   687  		C bool
   688  	}{
   689  		A: "a-value",
   690  		B: 2,
   691  		C: true,
   692  	}
   693  
   694  	s := g.Values(T)
   695  
   696  	if typ := reflect.TypeOf(s).Kind(); typ != reflect.Slice {
   697  		t.Errorf("Values should return a slice type, got: %v", typ)
   698  	}
   699  
   700  	inSlice := func(val interface{}) bool {
   701  		for _, v := range s {
   702  			if reflect.DeepEqual(v, val) {
   703  				return true
   704  			}
   705  		}
   706  		return false
   707  	}
   708  
   709  	for _, val := range []interface{}{"a-value", 2, true} {
   710  		if !inSlice(val) {
   711  			t.Errorf("Values should have the value %v", val)
   712  		}
   713  	}
   714  }
   715  
   716  func TestValues_OmitEmpty(t *testing.T) {
   717  	type A struct {
   718  		Name  string
   719  		Value int `struct:",omitempty"`
   720  	}
   721  
   722  	a := A{Name: "example"}
   723  	s := g.Values(a)
   724  
   725  	if len(s) != 1 {
   726  		t.Errorf("Values of omitted empty fields should be not counted")
   727  	}
   728  
   729  	if s[0].(string) != "example" {
   730  		t.Errorf("Values of omitted empty fields should left the value example")
   731  	}
   732  }
   733  
   734  func TestValues_OmitNested(t *testing.T) {
   735  	type A struct {
   736  		Name  string
   737  		Value int
   738  	}
   739  
   740  	a := A{
   741  		Name:  "example",
   742  		Value: 123,
   743  	}
   744  
   745  	type B struct {
   746  		A A `struct:",omitnested"`
   747  		C int
   748  	}
   749  	b := &B{A: a, C: 123}
   750  
   751  	s := g.Values(b)
   752  
   753  	if len(s) != 2 {
   754  		t.Errorf("Values of omitted nested struct should be not counted")
   755  	}
   756  
   757  	inSlice := func(val interface{}) bool {
   758  		for _, v := range s {
   759  			if reflect.DeepEqual(v, val) {
   760  				return true
   761  			}
   762  		}
   763  		return false
   764  	}
   765  
   766  	for _, val := range []interface{}{123, a} {
   767  		if !inSlice(val) {
   768  			t.Errorf("Values should have the value %v", val)
   769  		}
   770  	}
   771  }
   772  
   773  func TestValues_Nested(t *testing.T) {
   774  	type A struct {
   775  		Name string
   776  	}
   777  	a := A{Name: "example"}
   778  
   779  	type B struct {
   780  		A A
   781  		C int
   782  	}
   783  	b := &B{A: a, C: 123}
   784  
   785  	s := g.Values(b)
   786  
   787  	inSlice := func(val interface{}) bool {
   788  		for _, v := range s {
   789  			if reflect.DeepEqual(v, val) {
   790  				return true
   791  			}
   792  		}
   793  		return false
   794  	}
   795  
   796  	for _, val := range []interface{}{"example", 123} {
   797  		if !inSlice(val) {
   798  			t.Errorf("Values should have the value %v", val)
   799  		}
   800  	}
   801  }
   802  
   803  func TestValues_Anonymous(t *testing.T) {
   804  	type A struct {
   805  		Name string
   806  	}
   807  	a := A{Name: "example"}
   808  
   809  	type B struct {
   810  		A
   811  		C int
   812  	}
   813  	b := &B{C: 123}
   814  	b.A = a
   815  
   816  	s := g.Values(b)
   817  
   818  	inSlice := func(val interface{}) bool {
   819  		for _, v := range s {
   820  			if reflect.DeepEqual(v, val) {
   821  				return true
   822  			}
   823  		}
   824  		return false
   825  	}
   826  
   827  	for _, val := range []interface{}{"example", 123} {
   828  		if !inSlice(val) {
   829  			t.Errorf("Values should have the value %v", val)
   830  		}
   831  	}
   832  }
   833  
   834  func TestNames(t *testing.T) {
   835  	var T = struct {
   836  		A string
   837  		B int
   838  		C bool
   839  	}{
   840  		A: "a-value",
   841  		B: 2,
   842  		C: true,
   843  	}
   844  
   845  	s := g.Names(T)
   846  
   847  	if len(s) != 3 {
   848  		t.Errorf("Names should return a slice of len 3, got: %d", len(s))
   849  	}
   850  
   851  	inSlice := func(val string) bool {
   852  		for _, v := range s {
   853  			if reflect.DeepEqual(v, val) {
   854  				return true
   855  			}
   856  		}
   857  		return false
   858  	}
   859  
   860  	for _, val := range []string{"A", "B", "C"} {
   861  		if !inSlice(val) {
   862  			t.Errorf("Names should have the value %v", val)
   863  		}
   864  	}
   865  }
   866  
   867  func TestFields(t *testing.T) {
   868  	var T = struct {
   869  		A string
   870  		B int
   871  		C bool
   872  	}{
   873  		A: "a-value",
   874  		B: 2,
   875  		C: true,
   876  	}
   877  
   878  	s := g.Fields(T)
   879  
   880  	if len(s) != 3 {
   881  		t.Errorf("Fields should return a slice of len 3, got: %d", len(s))
   882  	}
   883  
   884  	inSlice := func(val string) bool {
   885  		for _, v := range s {
   886  			if reflect.DeepEqual(v.Name(), val) {
   887  				return true
   888  			}
   889  		}
   890  		return false
   891  	}
   892  
   893  	for _, val := range []string{"A", "B", "C"} {
   894  		if !inSlice(val) {
   895  			t.Errorf("Fields should have the value %v", val)
   896  		}
   897  	}
   898  }
   899  
   900  func TestFields_OmitNested(t *testing.T) {
   901  	type A struct {
   902  		Name    string
   903  		Enabled bool
   904  	}
   905  	a := A{Name: "example"}
   906  
   907  	type B struct {
   908  		A      A
   909  		C      int
   910  		Value  string `struct:"-"`
   911  		Number int
   912  	}
   913  	b := &B{A: a, C: 123}
   914  
   915  	s := g.Fields(b)
   916  
   917  	if len(s) != 3 {
   918  		t.Errorf("Fields should omit nested struct. Expecting 2 got: %d", len(s))
   919  	}
   920  
   921  	inSlice := func(val interface{}) bool {
   922  		for _, v := range s {
   923  			if reflect.DeepEqual(v.Name(), val) {
   924  				return true
   925  			}
   926  		}
   927  		return false
   928  	}
   929  
   930  	for _, val := range []interface{}{"A", "C"} {
   931  		if !inSlice(val) {
   932  			t.Errorf("Fields should have the value %v", val)
   933  		}
   934  	}
   935  }
   936  
   937  func TestFields_Anonymous(t *testing.T) {
   938  	type A struct {
   939  		Name string
   940  	}
   941  	a := A{Name: "example"}
   942  
   943  	type B struct {
   944  		A
   945  		C int
   946  	}
   947  	b := &B{C: 123}
   948  	b.A = a
   949  
   950  	s := g.Fields(b)
   951  
   952  	inSlice := func(val interface{}) bool {
   953  		for _, v := range s {
   954  			if reflect.DeepEqual(v.Name(), val) {
   955  				return true
   956  			}
   957  		}
   958  		return false
   959  	}
   960  
   961  	for _, val := range []interface{}{"A", "C"} {
   962  		if !inSlice(val) {
   963  			t.Errorf("Fields should have the value %v", val)
   964  		}
   965  	}
   966  }
   967  
   968  func TestIsZero(t *testing.T) {
   969  	var T = struct {
   970  		A string
   971  		B int
   972  		C bool `struct:"-"`
   973  		D []string
   974  	}{}
   975  
   976  	ok := g.IsZero(T)
   977  	if !ok {
   978  		t.Error("IsZero should return true because none of the fields are initialized.")
   979  	}
   980  
   981  	var X = struct {
   982  		A string
   983  		F *bool
   984  	}{
   985  		A: "a-value",
   986  	}
   987  
   988  	ok = g.IsZero(X)
   989  	if ok {
   990  		t.Error("IsZero should return false because A is initialized")
   991  	}
   992  
   993  	var Y = struct {
   994  		A string
   995  		B int
   996  	}{
   997  		A: "a-value",
   998  		B: 123,
   999  	}
  1000  
  1001  	ok = g.IsZero(Y)
  1002  	if ok {
  1003  		t.Error("IsZero should return false because A and B is initialized")
  1004  	}
  1005  }
  1006  
  1007  func TestIsZero_OmitNested(t *testing.T) {
  1008  	type A struct {
  1009  		Name string
  1010  		D    string
  1011  	}
  1012  	a := A{Name: "example"}
  1013  
  1014  	type B struct {
  1015  		A A `struct:",omitnested"`
  1016  		C int
  1017  	}
  1018  	b := &B{A: a, C: 123}
  1019  
  1020  	ok := g.IsZero(b)
  1021  	if ok {
  1022  		t.Error("IsZero should return false because A, B and C are initialized")
  1023  	}
  1024  
  1025  	aZero := A{}
  1026  	bZero := &B{A: aZero}
  1027  
  1028  	ok = g.IsZero(bZero)
  1029  	if !ok {
  1030  		t.Error("IsZero should return true because neither A nor B is initialized")
  1031  	}
  1032  
  1033  }
  1034  
  1035  func TestIsZero_Nested(t *testing.T) {
  1036  	type A struct {
  1037  		Name string
  1038  		D    string
  1039  	}
  1040  	a := A{Name: "example"}
  1041  
  1042  	type B struct {
  1043  		A A
  1044  		C int
  1045  	}
  1046  	b := &B{A: a, C: 123}
  1047  
  1048  	ok := g.IsZero(b)
  1049  	if ok {
  1050  		t.Error("IsZero should return false because A, B and C are initialized")
  1051  	}
  1052  
  1053  	aZero := A{}
  1054  	bZero := &B{A: aZero}
  1055  
  1056  	ok = g.IsZero(bZero)
  1057  	if !ok {
  1058  		t.Error("IsZero should return true because neither A nor B is initialized")
  1059  	}
  1060  
  1061  }
  1062  
  1063  func TestIsZero_Anonymous(t *testing.T) {
  1064  	type A struct {
  1065  		Name string
  1066  		D    string
  1067  	}
  1068  	a := A{Name: "example"}
  1069  
  1070  	type B struct {
  1071  		A
  1072  		C int
  1073  	}
  1074  	b := &B{C: 123}
  1075  	b.A = a
  1076  
  1077  	ok := g.IsZero(b)
  1078  	if ok {
  1079  		t.Error("IsZero should return false because A, B and C are initialized")
  1080  	}
  1081  
  1082  	aZero := A{}
  1083  	bZero := &B{}
  1084  	bZero.A = aZero
  1085  
  1086  	ok = g.IsZero(bZero)
  1087  	if !ok {
  1088  		t.Error("IsZero should return true because neither A nor B is initialized")
  1089  	}
  1090  }
  1091  
  1092  func TestHasZero(t *testing.T) {
  1093  	var T = struct {
  1094  		A string
  1095  		B int
  1096  		C bool `struct:"-"`
  1097  		D []string
  1098  	}{
  1099  		A: "a-value",
  1100  		B: 2,
  1101  	}
  1102  
  1103  	ok := g.HasZero(T)
  1104  	if !ok {
  1105  		t.Error("HasZero should return true because A and B are initialized.")
  1106  	}
  1107  
  1108  	var X = struct {
  1109  		A string
  1110  		F *bool
  1111  	}{
  1112  		A: "a-value",
  1113  	}
  1114  
  1115  	ok = g.HasZero(X)
  1116  	if !ok {
  1117  		t.Error("HasZero should return true because A is initialized")
  1118  	}
  1119  
  1120  	var Y = struct {
  1121  		A string
  1122  		B int
  1123  	}{
  1124  		A: "a-value",
  1125  		B: 123,
  1126  	}
  1127  
  1128  	ok = g.HasZero(Y)
  1129  	if ok {
  1130  		t.Error("HasZero should return false because A and B is initialized")
  1131  	}
  1132  }
  1133  
  1134  func TestHasZero_OmitNested(t *testing.T) {
  1135  	type A struct {
  1136  		Name string
  1137  		D    string
  1138  	}
  1139  	a := A{Name: "example"}
  1140  
  1141  	type B struct {
  1142  		A A `struct:",omitnested"`
  1143  		C int
  1144  	}
  1145  	b := &B{A: a, C: 123}
  1146  
  1147  	// Because the Field A inside B is omitted  HasZero should return false
  1148  	// because it will stop iterating deeper andnot going to lookup for D
  1149  	ok := g.HasZero(b)
  1150  	if ok {
  1151  		t.Error("HasZero should return false because A and C are initialized")
  1152  	}
  1153  }
  1154  
  1155  func TestHasZero_Nested(t *testing.T) {
  1156  	type A struct {
  1157  		Name string
  1158  		D    string
  1159  	}
  1160  	a := A{Name: "example"}
  1161  
  1162  	type B struct {
  1163  		A A
  1164  		C int
  1165  	}
  1166  	b := &B{A: a, C: 123}
  1167  
  1168  	ok := g.HasZero(b)
  1169  	if !ok {
  1170  		t.Error("HasZero should return true because D is not initialized")
  1171  	}
  1172  }
  1173  
  1174  func TestHasZero_Anonymous(t *testing.T) {
  1175  	type A struct {
  1176  		Name string
  1177  		D    string
  1178  	}
  1179  	a := A{Name: "example"}
  1180  
  1181  	type B struct {
  1182  		A
  1183  		C int
  1184  	}
  1185  	b := &B{C: 123}
  1186  	b.A = a
  1187  
  1188  	ok := g.HasZero(b)
  1189  	if !ok {
  1190  		t.Error("HasZero should return false because D is not initialized")
  1191  	}
  1192  }
  1193  
  1194  func TestName(t *testing.T) {
  1195  	type Foo struct {
  1196  		A string
  1197  		B bool
  1198  	}
  1199  	f := &Foo{}
  1200  
  1201  	n := g.Name(f)
  1202  	if n != "Foo" {
  1203  		t.Errorf("Name should return Foo, got: %s", n)
  1204  	}
  1205  
  1206  	unnamed := struct{ Name string }{Name: "Cihangir"}
  1207  	m := g.Name(unnamed)
  1208  	if m != "" {
  1209  		t.Errorf("Name should return empty string for unnamed struct, got: %s", n)
  1210  	}
  1211  
  1212  	defer func() {
  1213  		err := recover()
  1214  		if err == nil {
  1215  			t.Error("Name should panic if a non struct is passed")
  1216  		}
  1217  	}()
  1218  
  1219  	g.Name([]string{})
  1220  }
  1221  
  1222  func TestNestedNilPointer(t *testing.T) {
  1223  	type Collar struct {
  1224  		Engraving string
  1225  	}
  1226  
  1227  	type Dog struct {
  1228  		Name   string
  1229  		Collar *Collar
  1230  	}
  1231  
  1232  	type Person struct {
  1233  		Name string
  1234  		Dog  *Dog
  1235  	}
  1236  
  1237  	person := &Person{
  1238  		Name: "John",
  1239  	}
  1240  
  1241  	personWithDog := &Person{
  1242  		Name: "Ron",
  1243  		Dog: &Dog{
  1244  			Name: "Rover",
  1245  		},
  1246  	}
  1247  
  1248  	personWithDogWithCollar := &Person{
  1249  		Name: "Kon",
  1250  		Dog: &Dog{
  1251  			Name: "Ruffles",
  1252  			Collar: &Collar{
  1253  				Engraving: "If lost, call Kon",
  1254  			},
  1255  		},
  1256  	}
  1257  
  1258  	defer func() {
  1259  		err := recover()
  1260  		if err != nil {
  1261  			fmt.Printf("err %+v\n", err)
  1262  			t.Error("Internal nil pointer should not panic")
  1263  		}
  1264  	}()
  1265  
  1266  	_ = g.Maps(person)                  // Panics
  1267  	_ = g.Maps(personWithDog)           // Panics
  1268  	_ = g.Maps(personWithDogWithCollar) // Doesn't panic
  1269  }
  1270  
  1271  func TestSetValueOnNestedField(t *testing.T) {
  1272  	type Base struct {
  1273  		ID int
  1274  	}
  1275  
  1276  	type User struct {
  1277  		Base
  1278  		Name string
  1279  	}
  1280  
  1281  	u := User{}
  1282  	s := g.NewStruct(&u)
  1283  	f := s.Field("Base").Field("ID")
  1284  	err := f.Set(10)
  1285  	if err != nil {
  1286  		t.Errorf("Error %v", err)
  1287  	}
  1288  	if f.Value().(int) != 10 {
  1289  		t.Errorf("Value should be equal to 10, got %v", f.Value())
  1290  	}
  1291  }
  1292  
  1293  type Person struct {
  1294  	Name string
  1295  	Age  int
  1296  }
  1297  
  1298  func (p *Person) String() string {
  1299  	return fmt.Sprintf("%s(%d)", p.Name, p.Age)
  1300  }
  1301  
  1302  func TestTagWithStringOption(t *testing.T) {
  1303  
  1304  	type Address struct {
  1305  		Country string  `json:"country"`
  1306  		Person  *Person `json:"person,string"`
  1307  	}
  1308  
  1309  	person := &Person{
  1310  		Name: "John",
  1311  		Age:  23,
  1312  	}
  1313  
  1314  	address := &Address{
  1315  		Country: "EU",
  1316  		Person:  person,
  1317  	}
  1318  
  1319  	defer func() {
  1320  		err := recover()
  1321  		if err != nil {
  1322  			fmt.Printf("err %+v\n", err)
  1323  			t.Error("Internal nil pointer should not panic")
  1324  		}
  1325  	}()
  1326  
  1327  	s := g.NewStruct(address)
  1328  
  1329  	s.TagName = "json"
  1330  	m := s.Maps()
  1331  
  1332  	if m["person"] != person.String() {
  1333  		t.Errorf("Value for field person should be %s, got: %s", person.String(), m["person"])
  1334  	}
  1335  
  1336  	vs := s.Values()
  1337  	if vs[1] != person.String() {
  1338  		t.Errorf("Value for 2nd field (person) should be %T, got: %T", person.String(), vs[1])
  1339  	}
  1340  }
  1341  
  1342  type Animal struct {
  1343  	Name string
  1344  	Age  int
  1345  }
  1346  
  1347  type Dog struct {
  1348  	Animal *Animal `json:"animal,string"`
  1349  }
  1350  
  1351  func TestNonStringerTagWithStringOption(t *testing.T) {
  1352  	a := &Animal{
  1353  		Name: "Fluff",
  1354  		Age:  4,
  1355  	}
  1356  
  1357  	d := &Dog{
  1358  		Animal: a,
  1359  	}
  1360  
  1361  	defer func() {
  1362  		err := recover()
  1363  		if err != nil {
  1364  			fmt.Printf("err %+v\n", err)
  1365  			t.Error("Internal nil pointer should not panic")
  1366  		}
  1367  	}()
  1368  
  1369  	s := g.NewStruct(d)
  1370  
  1371  	s.TagName = "json"
  1372  	m := s.Maps()
  1373  
  1374  	if _, exists := m["animal"]; exists {
  1375  		t.Errorf("Value for field Animal should not exist")
  1376  	}
  1377  }
  1378  
  1379  func TestMap_InterfaceValue(t *testing.T) {
  1380  	type TestStruct struct {
  1381  		A interface{}
  1382  	}
  1383  
  1384  	expected := []byte("test value")
  1385  
  1386  	a := TestStruct{A: expected}
  1387  	s := g.Maps(a)
  1388  	if !reflect.DeepEqual(s["A"], expected) {
  1389  		t.Errorf("Value does not match expected: %q != %q", s["A"], expected)
  1390  	}
  1391  }
  1392  
  1393  func TestPointer2Pointer(t *testing.T) {
  1394  	defer func() {
  1395  		err := recover()
  1396  		if err != nil {
  1397  			fmt.Printf("err %+v\n", err)
  1398  			t.Error("Internal nil pointer should not panic")
  1399  		}
  1400  	}()
  1401  	a := &Animal{
  1402  		Name: "Fluff",
  1403  		Age:  4,
  1404  	}
  1405  	_ = g.Maps(&a)
  1406  
  1407  	b := &a
  1408  	_ = g.Maps(&b)
  1409  
  1410  	c := &b
  1411  	_ = g.Maps(&c)
  1412  }
  1413  
  1414  func TestMap_InterfaceTypeWithMapValue(t *testing.T) {
  1415  	type A struct {
  1416  		Name    string      `struct:"name"`
  1417  		IP      string      `struct:"ip"`
  1418  		Query   string      `struct:"query"`
  1419  		Payload interface{} `struct:"payload"`
  1420  	}
  1421  
  1422  	a := A{
  1423  		Name:    "test",
  1424  		IP:      "127.0.0.1",
  1425  		Query:   "",
  1426  		Payload: map[string]string{"test_param": "test_param"},
  1427  	}
  1428  
  1429  	defer func() {
  1430  		err := recover()
  1431  		if err != nil {
  1432  			t.Error("Converting Map with an interface{} type with map value should not panic")
  1433  		}
  1434  	}()
  1435  
  1436  	_ = g.Maps(a)
  1437  }