...

Source file src/github.com/doug-martin/goqu/v9/internal/util/reflect_test.go

Documentation: github.com/doug-martin/goqu/v9/internal/util

     1  package util_test
     2  
     3  import (
     4  	"database/sql"
     5  	"reflect"
     6  	"strings"
     7  	"sync"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/doug-martin/goqu/v9/internal/util"
    12  	"github.com/stretchr/testify/suite"
    13  )
    14  
    15  var (
    16  	uints = []interface{}{
    17  		uint(10),
    18  		uint8(10),
    19  		uint16(10),
    20  		uint32(10),
    21  		uint64(10),
    22  	}
    23  	ints = []interface{}{
    24  		int(10),
    25  		int8(10),
    26  		int16(10),
    27  		int32(10),
    28  		int64(10),
    29  	}
    30  	floats = []interface{}{
    31  		float32(3.14),
    32  		float64(3.14),
    33  	}
    34  	strs = []interface{}{
    35  		"abc",
    36  		"",
    37  	}
    38  	bools = []interface{}{
    39  		true,
    40  		false,
    41  	}
    42  	structs = []interface{}{
    43  		sql.NullString{},
    44  	}
    45  	invalids = []interface{}{
    46  		nil,
    47  	}
    48  	pointers = []interface{}{
    49  		&sql.NullString{},
    50  	}
    51  )
    52  
    53  type (
    54  	TestInterface interface {
    55  		A() string
    56  	}
    57  	TestInterfaceImpl struct {
    58  		str string
    59  	}
    60  	TestStruct struct {
    61  		arr  [0]string
    62  		slc  []string
    63  		mp   map[string]interface{}
    64  		str  string
    65  		bl   bool
    66  		i    int
    67  		i8   int8
    68  		i16  int16
    69  		i32  int32
    70  		i64  int64
    71  		ui   uint
    72  		ui8  uint8
    73  		ui16 uint16
    74  		ui32 uint32
    75  		ui64 uint64
    76  		f32  float32
    77  		f64  float64
    78  		intr TestInterface
    79  		ptr  *sql.NullString
    80  	}
    81  )
    82  
    83  func (t TestInterfaceImpl) A() string {
    84  	return t.str
    85  }
    86  
    87  type reflectTest struct {
    88  	suite.Suite
    89  }
    90  
    91  func (rt *reflectTest) TestIsUint() {
    92  	for _, v := range uints {
    93  		rt.True(util.IsUint(reflect.ValueOf(v).Kind()))
    94  	}
    95  
    96  	for _, v := range ints {
    97  		rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
    98  	}
    99  	for _, v := range floats {
   100  		rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
   101  	}
   102  	for _, v := range strs {
   103  		rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
   104  	}
   105  	for _, v := range bools {
   106  		rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
   107  	}
   108  	for _, v := range structs {
   109  		rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
   110  	}
   111  	for _, v := range invalids {
   112  		rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
   113  	}
   114  	for _, v := range pointers {
   115  		rt.False(util.IsUint(reflect.ValueOf(v).Kind()))
   116  	}
   117  }
   118  
   119  func (rt *reflectTest) TestIsInt() {
   120  	for _, v := range ints {
   121  		rt.True(util.IsInt(reflect.ValueOf(v).Kind()))
   122  	}
   123  
   124  	for _, v := range uints {
   125  		rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
   126  	}
   127  	for _, v := range floats {
   128  		rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
   129  	}
   130  	for _, v := range strs {
   131  		rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
   132  	}
   133  	for _, v := range bools {
   134  		rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
   135  	}
   136  	for _, v := range structs {
   137  		rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
   138  	}
   139  	for _, v := range invalids {
   140  		rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
   141  	}
   142  	for _, v := range pointers {
   143  		rt.False(util.IsInt(reflect.ValueOf(v).Kind()))
   144  	}
   145  }
   146  
   147  func (rt *reflectTest) TestIsFloat() {
   148  	for _, v := range floats {
   149  		rt.True(util.IsFloat(reflect.ValueOf(v).Kind()))
   150  	}
   151  
   152  	for _, v := range uints {
   153  		rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
   154  	}
   155  	for _, v := range ints {
   156  		rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
   157  	}
   158  	for _, v := range strs {
   159  		rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
   160  	}
   161  	for _, v := range bools {
   162  		rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
   163  	}
   164  	for _, v := range structs {
   165  		rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
   166  	}
   167  	for _, v := range invalids {
   168  		rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
   169  	}
   170  	for _, v := range pointers {
   171  		rt.False(util.IsFloat(reflect.ValueOf(v).Kind()))
   172  	}
   173  }
   174  
   175  func (rt *reflectTest) TestIsString() {
   176  	for _, v := range strs {
   177  		rt.True(util.IsString(reflect.ValueOf(v).Kind()))
   178  	}
   179  
   180  	for _, v := range uints {
   181  		rt.False(util.IsString(reflect.ValueOf(v).Kind()))
   182  	}
   183  	for _, v := range ints {
   184  		rt.False(util.IsString(reflect.ValueOf(v).Kind()))
   185  	}
   186  	for _, v := range floats {
   187  		rt.False(util.IsString(reflect.ValueOf(v).Kind()))
   188  	}
   189  	for _, v := range bools {
   190  		rt.False(util.IsString(reflect.ValueOf(v).Kind()))
   191  	}
   192  	for _, v := range structs {
   193  		rt.False(util.IsString(reflect.ValueOf(v).Kind()))
   194  	}
   195  	for _, v := range invalids {
   196  		rt.False(util.IsString(reflect.ValueOf(v).Kind()))
   197  	}
   198  	for _, v := range pointers {
   199  		rt.False(util.IsString(reflect.ValueOf(v).Kind()))
   200  	}
   201  }
   202  
   203  func (rt *reflectTest) TestIsBool() {
   204  	for _, v := range bools {
   205  		rt.True(util.IsBool(reflect.ValueOf(v).Kind()))
   206  	}
   207  
   208  	for _, v := range uints {
   209  		rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
   210  	}
   211  	for _, v := range ints {
   212  		rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
   213  	}
   214  	for _, v := range floats {
   215  		rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
   216  	}
   217  	for _, v := range strs {
   218  		rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
   219  	}
   220  	for _, v := range structs {
   221  		rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
   222  	}
   223  	for _, v := range invalids {
   224  		rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
   225  	}
   226  	for _, v := range pointers {
   227  		rt.False(util.IsBool(reflect.ValueOf(v).Kind()))
   228  	}
   229  }
   230  
   231  func (rt *reflectTest) TestIsStruct() {
   232  	for _, v := range structs {
   233  		rt.True(util.IsStruct(reflect.ValueOf(v).Kind()))
   234  	}
   235  
   236  	for _, v := range uints {
   237  		rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
   238  	}
   239  	for _, v := range ints {
   240  		rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
   241  	}
   242  	for _, v := range floats {
   243  		rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
   244  	}
   245  	for _, v := range bools {
   246  		rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
   247  	}
   248  	for _, v := range strs {
   249  		rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
   250  	}
   251  	for _, v := range invalids {
   252  		rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
   253  	}
   254  	for _, v := range pointers {
   255  		rt.False(util.IsStruct(reflect.ValueOf(v).Kind()))
   256  	}
   257  }
   258  
   259  func (rt *reflectTest) TestIsSlice() {
   260  	rt.True(util.IsSlice(reflect.ValueOf(uints).Kind()))
   261  	rt.True(util.IsSlice(reflect.ValueOf(ints).Kind()))
   262  	rt.True(util.IsSlice(reflect.ValueOf(floats).Kind()))
   263  	rt.True(util.IsSlice(reflect.ValueOf(structs).Kind()))
   264  
   265  	rt.False(util.IsSlice(reflect.ValueOf(structs[0]).Kind()))
   266  }
   267  
   268  func (rt *reflectTest) TestIsInvalid() {
   269  	for _, v := range invalids {
   270  		rt.True(util.IsInvalid(reflect.ValueOf(v).Kind()))
   271  	}
   272  
   273  	for _, v := range uints {
   274  		rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
   275  	}
   276  	for _, v := range ints {
   277  		rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
   278  	}
   279  	for _, v := range floats {
   280  		rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
   281  	}
   282  	for _, v := range bools {
   283  		rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
   284  	}
   285  	for _, v := range strs {
   286  		rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
   287  	}
   288  	for _, v := range structs {
   289  		rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
   290  	}
   291  	for _, v := range pointers {
   292  		rt.False(util.IsInvalid(reflect.ValueOf(v).Kind()))
   293  	}
   294  }
   295  
   296  func (rt *reflectTest) TestIsPointer() {
   297  	for _, v := range pointers {
   298  		rt.True(util.IsPointer(reflect.ValueOf(v).Kind()))
   299  	}
   300  
   301  	for _, v := range uints {
   302  		rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
   303  	}
   304  	for _, v := range ints {
   305  		rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
   306  	}
   307  	for _, v := range floats {
   308  		rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
   309  	}
   310  	for _, v := range bools {
   311  		rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
   312  	}
   313  	for _, v := range strs {
   314  		rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
   315  	}
   316  	for _, v := range structs {
   317  		rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
   318  	}
   319  	for _, v := range invalids {
   320  		rt.False(util.IsPointer(reflect.ValueOf(v).Kind()))
   321  	}
   322  }
   323  
   324  func (rt *reflectTest) TestIsEmptyValue_emptyValues() {
   325  	ts := TestStruct{}
   326  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.arr)))
   327  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.slc)))
   328  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.mp)))
   329  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.str)))
   330  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.bl)))
   331  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.i)))
   332  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.i8)))
   333  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.i16)))
   334  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.i32)))
   335  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.i64)))
   336  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ui)))
   337  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ui8)))
   338  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ui16)))
   339  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ui32)))
   340  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ui64)))
   341  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.f32)))
   342  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.f64)))
   343  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.intr)))
   344  	rt.True(util.IsEmptyValue(reflect.ValueOf(ts.ptr)))
   345  }
   346  
   347  func (rt *reflectTest) TestIsEmptyValue_validValues() {
   348  	ts := TestStruct{intr: TestInterfaceImpl{"hello"}}
   349  	rt.False(util.IsEmptyValue(reflect.ValueOf([1]string{"a"})))
   350  	rt.False(util.IsEmptyValue(reflect.ValueOf([]string{"a"})))
   351  	rt.False(util.IsEmptyValue(reflect.ValueOf(map[string]interface{}{"a": true})))
   352  	rt.False(util.IsEmptyValue(reflect.ValueOf("str")))
   353  	rt.False(util.IsEmptyValue(reflect.ValueOf(true)))
   354  	rt.False(util.IsEmptyValue(reflect.ValueOf(int(1))))
   355  	rt.False(util.IsEmptyValue(reflect.ValueOf(int8(1))))
   356  	rt.False(util.IsEmptyValue(reflect.ValueOf(int16(1))))
   357  	rt.False(util.IsEmptyValue(reflect.ValueOf(int32(1))))
   358  	rt.False(util.IsEmptyValue(reflect.ValueOf(int64(1))))
   359  	rt.False(util.IsEmptyValue(reflect.ValueOf(uint(1))))
   360  	rt.False(util.IsEmptyValue(reflect.ValueOf(uint8(1))))
   361  	rt.False(util.IsEmptyValue(reflect.ValueOf(uint16(1))))
   362  	rt.False(util.IsEmptyValue(reflect.ValueOf(uint32(1))))
   363  	rt.False(util.IsEmptyValue(reflect.ValueOf(uint64(1))))
   364  	rt.False(util.IsEmptyValue(reflect.ValueOf(float32(0.1))))
   365  	rt.False(util.IsEmptyValue(reflect.ValueOf(float64(0.2))))
   366  	rt.False(util.IsEmptyValue(reflect.ValueOf(ts.intr)))
   367  	rt.False(util.IsEmptyValue(reflect.ValueOf(&TestStruct{str: "a"})))
   368  }
   369  
   370  func (rt *reflectTest) TestColumnRename() {
   371  	// different key names are used each time to circumvent the caching that happens
   372  	// it seems like a solid assumption that when people use this feature,
   373  	// they would simply set a renaming function once at startup,
   374  	// and not change between requests like this
   375  	lowerAnon := struct {
   376  		FirstLower string
   377  		LastLower  string
   378  	}{}
   379  	lowerColumnMap, lowerErr := util.GetColumnMap(&lowerAnon)
   380  	rt.NoError(lowerErr)
   381  
   382  	lowerKeys := make([]string, 0, len(lowerColumnMap))
   383  	for key := range lowerColumnMap {
   384  		lowerKeys = append(lowerKeys, key)
   385  	}
   386  	rt.Contains(lowerKeys, "firstlower")
   387  	rt.Contains(lowerKeys, "lastlower")
   388  
   389  	// changing rename function
   390  	util.SetColumnRenameFunction(strings.ToUpper)
   391  
   392  	upperAnon := struct {
   393  		FirstUpper string
   394  		LastUpper  string
   395  	}{}
   396  	upperColumnMap, upperErr := util.GetColumnMap(&upperAnon)
   397  	rt.NoError(upperErr)
   398  
   399  	upperKeys := make([]string, 0, len(upperColumnMap))
   400  	for key := range upperColumnMap {
   401  		upperKeys = append(upperKeys, key)
   402  	}
   403  	rt.Contains(upperKeys, "FIRSTUPPER")
   404  	rt.Contains(upperKeys, "LASTUPPER")
   405  
   406  	util.SetColumnRenameFunction(util.DefaultColumnRenameFunction)
   407  }
   408  
   409  func (rt *reflectTest) TestParallelGetColumnMap() {
   410  	type item struct {
   411  		id   uint
   412  		name string
   413  	}
   414  
   415  	wg := sync.WaitGroup{}
   416  
   417  	wg.Add(1)
   418  	go func() {
   419  		i := item{id: 1, name: "bob"}
   420  		m, err := util.GetColumnMap(i)
   421  		rt.NoError(err)
   422  		rt.NotNil(m)
   423  		wg.Done()
   424  	}()
   425  
   426  	wg.Add(1)
   427  	go func() {
   428  		i := item{id: 2, name: "sally"}
   429  		m, err := util.GetColumnMap(i)
   430  		rt.NoError(err)
   431  		rt.NotNil(m)
   432  		wg.Done()
   433  	}()
   434  
   435  	wg.Wait()
   436  }
   437  
   438  func (rt *reflectTest) TestAssignStructVals_withStruct() {
   439  	type TestStruct struct {
   440  		Str    string
   441  		Int    int64
   442  		Bool   bool
   443  		Valuer sql.NullString
   444  	}
   445  	var ts TestStruct
   446  	cm, err := util.GetColumnMap(&ts)
   447  	rt.NoError(err)
   448  	data := map[string]interface{}{
   449  		"str":    "string",
   450  		"int":    int64(10),
   451  		"bool":   true,
   452  		"valuer": sql.NullString{String: "null_str", Valid: true},
   453  	}
   454  
   455  	util.AssignStructVals(&ts, data, cm)
   456  	rt.Equal(ts, TestStruct{
   457  		Str:    "string",
   458  		Int:    10,
   459  		Bool:   true,
   460  		Valuer: sql.NullString{String: "null_str", Valid: true},
   461  	})
   462  }
   463  
   464  func (rt *reflectTest) TestAssignStructVals_withStructWithPointerVals() {
   465  	type TestStruct struct {
   466  		Str    string
   467  		Int    int64
   468  		Bool   bool
   469  		Valuer *sql.NullString
   470  	}
   471  	var ts TestStruct
   472  	cm, err := util.GetColumnMap(&ts)
   473  	rt.NoError(err)
   474  	ns := &sql.NullString{String: "null_str1", Valid: true}
   475  	data := map[string]interface{}{
   476  		"str":    "string",
   477  		"int":    int64(10),
   478  		"bool":   true,
   479  		"valuer": &ns,
   480  	}
   481  	util.AssignStructVals(&ts, data, cm)
   482  	rt.Equal(ts, TestStruct{
   483  		Str:    "string",
   484  		Int:    10,
   485  		Bool:   true,
   486  		Valuer: ns,
   487  	})
   488  }
   489  
   490  func (rt *reflectTest) TestAssignStructVals_withStructWithEmbeddedStruct() {
   491  	type EmbeddedStruct struct {
   492  		Str string
   493  	}
   494  	type TestStruct struct {
   495  		EmbeddedStruct
   496  		Int    int64
   497  		Bool   bool
   498  		Valuer *sql.NullString
   499  	}
   500  	var ts TestStruct
   501  	cm, err := util.GetColumnMap(&ts)
   502  	rt.NoError(err)
   503  	ns := &sql.NullString{String: "null_str1", Valid: true}
   504  	data := map[string]interface{}{
   505  		"str":    "string",
   506  		"int":    int64(10),
   507  		"bool":   true,
   508  		"valuer": &ns,
   509  	}
   510  	util.AssignStructVals(&ts, data, cm)
   511  	rt.Equal(ts, TestStruct{
   512  		EmbeddedStruct: EmbeddedStruct{Str: "string"},
   513  		Int:            10,
   514  		Bool:           true,
   515  		Valuer:         ns,
   516  	})
   517  }
   518  
   519  func (rt *reflectTest) TestAssignStructVals_withStructWithEmbeddedStructPointer() {
   520  	type EmbeddedStruct struct {
   521  		Str string
   522  	}
   523  	type TestStruct struct {
   524  		*EmbeddedStruct
   525  		Int    int64
   526  		Bool   bool
   527  		Valuer *sql.NullString
   528  	}
   529  	var ts TestStruct
   530  	cm, err := util.GetColumnMap(&ts)
   531  	rt.NoError(err)
   532  	ns := &sql.NullString{String: "null_str1", Valid: true}
   533  	data := map[string]interface{}{
   534  		"str":    "string",
   535  		"int":    int64(10),
   536  		"bool":   true,
   537  		"valuer": &ns,
   538  	}
   539  	util.AssignStructVals(&ts, data, cm)
   540  	rt.Equal(ts, TestStruct{
   541  		EmbeddedStruct: &EmbeddedStruct{Str: "string"},
   542  		Int:            10,
   543  		Bool:           true,
   544  		Valuer:         ns,
   545  	})
   546  }
   547  
   548  func (rt *reflectTest) TestAssignStructVals_withStructWithTaggedEmbeddedStruct() {
   549  	type EmbeddedStruct struct {
   550  		Str string
   551  	}
   552  	type TestStruct struct {
   553  		EmbeddedStruct `db:"embedded"`
   554  		Int            int64
   555  		Bool           bool
   556  		Valuer         *sql.NullString
   557  	}
   558  	var ts TestStruct
   559  	cm, err := util.GetColumnMap(&ts)
   560  	rt.NoError(err)
   561  	ns := &sql.NullString{String: "null_str1", Valid: true}
   562  	data := map[string]interface{}{
   563  		"embedded.str": "string",
   564  		"int":          int64(10),
   565  		"bool":         true,
   566  		"valuer":       &ns,
   567  	}
   568  	util.AssignStructVals(&ts, data, cm)
   569  	rt.Equal(ts, TestStruct{
   570  		EmbeddedStruct: EmbeddedStruct{Str: "string"},
   571  		Int:            10,
   572  		Bool:           true,
   573  		Valuer:         ns,
   574  	})
   575  }
   576  
   577  func (rt *reflectTest) TestAssignStructVals_withStructWithTaggedEmbeddedPointer() {
   578  	type EmbeddedStruct struct {
   579  		Str string
   580  	}
   581  	type TestStruct struct {
   582  		*EmbeddedStruct `db:"embedded"`
   583  		Int             int64
   584  		Bool            bool
   585  		Valuer          *sql.NullString
   586  	}
   587  	var ts TestStruct
   588  	cm, err := util.GetColumnMap(&ts)
   589  	rt.NoError(err)
   590  	ns := &sql.NullString{String: "null_str1", Valid: true}
   591  	data := map[string]interface{}{
   592  		"embedded.str": "string",
   593  		"int":          int64(10),
   594  		"bool":         true,
   595  		"valuer":       &ns,
   596  	}
   597  	util.AssignStructVals(&ts, data, cm)
   598  	rt.Equal(ts, TestStruct{
   599  		EmbeddedStruct: &EmbeddedStruct{Str: "string"},
   600  		Int:            10,
   601  		Bool:           true,
   602  		Valuer:         ns,
   603  	})
   604  }
   605  
   606  func (rt *reflectTest) TestAssignStructVals_withStructWithTaggedStructField() {
   607  	type EmbeddedStruct struct {
   608  		Str string
   609  	}
   610  	type TestStruct struct {
   611  		Embedded EmbeddedStruct `db:"embedded"`
   612  		Int      int64
   613  		Bool     bool
   614  		Valuer   *sql.NullString
   615  	}
   616  	var ts TestStruct
   617  	cm, err := util.GetColumnMap(&ts)
   618  	rt.NoError(err)
   619  	ns := &sql.NullString{String: "null_str1", Valid: true}
   620  	data := map[string]interface{}{
   621  		"embedded.str": "string",
   622  		"int":          int64(10),
   623  		"bool":         true,
   624  		"valuer":       &ns,
   625  	}
   626  	util.AssignStructVals(&ts, data, cm)
   627  	rt.Equal(ts, TestStruct{
   628  		Embedded: EmbeddedStruct{Str: "string"},
   629  		Int:      10,
   630  		Bool:     true,
   631  		Valuer:   ns,
   632  	})
   633  }
   634  
   635  func (rt *reflectTest) TestAssignStructVals_withStructWithTaggedPointerField() {
   636  	type EmbeddedStruct struct {
   637  		Str string
   638  	}
   639  	type TestStruct struct {
   640  		Embedded *EmbeddedStruct `db:"embedded"`
   641  		Int      int64
   642  		Bool     bool
   643  		Valuer   *sql.NullString
   644  	}
   645  	var ts TestStruct
   646  	cm, err := util.GetColumnMap(&ts)
   647  	rt.NoError(err)
   648  	ns := &sql.NullString{String: "null_str1", Valid: true}
   649  	data := map[string]interface{}{
   650  		"embedded.str": "string",
   651  		"int":          int64(10),
   652  		"bool":         true,
   653  		"valuer":       &ns,
   654  	}
   655  	util.AssignStructVals(&ts, data, cm)
   656  	rt.Equal(ts, TestStruct{
   657  		Embedded: &EmbeddedStruct{Str: "string"},
   658  		Int:      10,
   659  		Bool:     true,
   660  		Valuer:   ns,
   661  	})
   662  }
   663  
   664  func (rt *reflectTest) TestGetColumnMap_withStruct() {
   665  	type TestStruct struct {
   666  		Str    string
   667  		Int    int64
   668  		Bool   bool
   669  		Valuer *sql.NullString
   670  	}
   671  	var ts TestStruct
   672  	cm, err := util.GetColumnMap(&ts)
   673  	rt.NoError(err)
   674  	rt.Equal(util.ColumnMap{
   675  		"str":    {ColumnName: "str", FieldIndex: []int{0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
   676  		"int":    {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   677  		"bool":   {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
   678  		"valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
   679  	}, cm)
   680  }
   681  
   682  func (rt *reflectTest) TestGetColumnMap_withStructGoquTags() {
   683  	type TestStruct struct {
   684  		Str    string `goqu:"skipinsert,skipupdate"`
   685  		Int    int64  `goqu:"skipinsert"`
   686  		Bool   bool   `goqu:"skipupdate"`
   687  		Empty  bool   `goqu:"defaultifempty"`
   688  		Valuer *sql.NullString
   689  	}
   690  	var ts TestStruct
   691  	cm, err := util.GetColumnMap(&ts)
   692  	rt.NoError(err)
   693  	rt.Equal(util.ColumnMap{
   694  		"str":  {ColumnName: "str", FieldIndex: []int{0}, ShouldInsert: false, ShouldUpdate: false, GoType: reflect.TypeOf("")},
   695  		"int":  {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: false, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   696  		"bool": {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: false, GoType: reflect.TypeOf(true)},
   697  		"empty": {
   698  			ColumnName:     "empty",
   699  			FieldIndex:     []int{3},
   700  			ShouldInsert:   true,
   701  			ShouldUpdate:   true,
   702  			DefaultIfEmpty: true,
   703  			GoType:         reflect.TypeOf(true),
   704  		},
   705  		"valuer": {ColumnName: "valuer", FieldIndex: []int{4}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
   706  	}, cm)
   707  }
   708  
   709  func (rt *reflectTest) TestGetColumnMap_withStructWithIgnoreUntagged() {
   710  	defer util.SetIgnoreUntaggedFields(false)
   711  	util.SetIgnoreUntaggedFields(true)
   712  
   713  	type EmbeddedStruct struct {
   714  		Float float64 `db:"f"`
   715  		Rune  rune    // Ignored
   716  	}
   717  
   718  	type TestStruct struct {
   719  		EmbeddedStruct
   720  		Str  string `db:"s"`
   721  		Int  int64  `db:"i"`
   722  		Bool bool   // Ignored
   723  	}
   724  	var ts TestStruct
   725  	cm, err := util.GetColumnMap(&ts)
   726  	rt.NoError(err)
   727  	rt.Equal(util.ColumnMap{
   728  		"f": {ColumnName: "f", FieldIndex: []int{0, 0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(float64(1))},
   729  		"s": {ColumnName: "s", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
   730  		"i": {ColumnName: "i", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   731  	}, cm)
   732  }
   733  
   734  func (rt *reflectTest) TestGetColumnMap_withStructWithTag() {
   735  	type TestStruct struct {
   736  		Str     string          `db:"s"`
   737  		Int     int64           `db:"i"`
   738  		Bool    bool            `db:"b"`
   739  		Valuer  *sql.NullString `db:"v"`
   740  		Ignored string          `db:"-"`
   741  	}
   742  	var ts TestStruct
   743  	cm, err := util.GetColumnMap(&ts)
   744  	rt.NoError(err)
   745  	rt.Equal(util.ColumnMap{
   746  		"s": {ColumnName: "s", FieldIndex: []int{0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
   747  		"i": {ColumnName: "i", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   748  		"b": {ColumnName: "b", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
   749  		"v": {ColumnName: "v", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
   750  	}, cm)
   751  }
   752  
   753  func (rt *reflectTest) TestGetColumnMap_withStructWithTagAndGoquTag() {
   754  	type TestStruct struct {
   755  		Str    string          `db:"s" goqu:"skipinsert,skipupdate"`
   756  		Int    int64           `db:"i" goqu:"skipinsert"`
   757  		Bool   bool            `db:"b" goqu:"skipupdate"`
   758  		Valuer *sql.NullString `db:"v"`
   759  	}
   760  	var ts TestStruct
   761  	cm, err := util.GetColumnMap(&ts)
   762  	rt.NoError(err)
   763  	rt.Equal(util.ColumnMap{
   764  		"s": {ColumnName: "s", FieldIndex: []int{0}, ShouldInsert: false, ShouldUpdate: false, GoType: reflect.TypeOf("")},
   765  		"i": {ColumnName: "i", FieldIndex: []int{1}, ShouldInsert: false, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   766  		"b": {ColumnName: "b", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: false, GoType: reflect.TypeOf(true)},
   767  		"v": {ColumnName: "v", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
   768  	}, cm)
   769  }
   770  
   771  func (rt *reflectTest) TestGetColumnMap_withStructWithTransientFields() {
   772  	type TestStruct struct {
   773  		Str    string
   774  		Int    int64
   775  		Bool   bool
   776  		Valuer *sql.NullString `db:"-"`
   777  	}
   778  	var ts TestStruct
   779  	cm, err := util.GetColumnMap(&ts)
   780  	rt.NoError(err)
   781  	rt.Equal(util.ColumnMap{
   782  		"str":  {ColumnName: "str", FieldIndex: []int{0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
   783  		"int":  {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   784  		"bool": {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
   785  	}, cm)
   786  }
   787  
   788  func (rt *reflectTest) TestGetColumnMap_withSliceOfStructs() {
   789  	type TestStruct struct {
   790  		Str    string
   791  		Int    int64
   792  		Bool   bool
   793  		Valuer *sql.NullString
   794  	}
   795  	var ts []TestStruct
   796  	cm, err := util.GetColumnMap(&ts)
   797  	rt.NoError(err)
   798  	rt.Equal(util.ColumnMap{
   799  		"str":    {ColumnName: "str", FieldIndex: []int{0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
   800  		"int":    {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   801  		"bool":   {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
   802  		"valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
   803  	}, cm)
   804  }
   805  
   806  func (rt *reflectTest) TestGetColumnMap_withNonStruct() {
   807  	var v int64
   808  	_, err := util.GetColumnMap(&v)
   809  	rt.EqualError(err, "goqu: cannot scan into this type: int64")
   810  }
   811  
   812  func (rt *reflectTest) TestGetColumnMap_withStructWithEmbeddedStruct() {
   813  	type EmbeddedStruct struct {
   814  		Str string
   815  	}
   816  	type TestStruct struct {
   817  		EmbeddedStruct
   818  		Int    int64
   819  		Bool   bool
   820  		Valuer *sql.NullString
   821  	}
   822  	var ts TestStruct
   823  	cm, err := util.GetColumnMap(&ts)
   824  	rt.NoError(err)
   825  	rt.Equal(util.ColumnMap{
   826  		"str":    {ColumnName: "str", FieldIndex: []int{0, 0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
   827  		"int":    {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   828  		"bool":   {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
   829  		"valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
   830  	}, cm)
   831  }
   832  
   833  func (rt *reflectTest) TestGetColumnMap_withStructWithEmbeddedStructPointer() {
   834  	type EmbeddedStruct struct {
   835  		Str string
   836  	}
   837  	type TestStruct struct {
   838  		*EmbeddedStruct
   839  		Int    int64
   840  		Bool   bool
   841  		Valuer *sql.NullString
   842  	}
   843  	var ts TestStruct
   844  	cm, err := util.GetColumnMap(&ts)
   845  	rt.NoError(err)
   846  	rt.Equal(util.ColumnMap{
   847  		"str":    {ColumnName: "str", FieldIndex: []int{0, 0}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf("")},
   848  		"int":    {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   849  		"bool":   {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
   850  		"valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
   851  	}, cm)
   852  }
   853  
   854  func (rt *reflectTest) TestGetColumnMap_withIgnoredEmbeddedStruct() {
   855  	type EmbeddedStruct struct {
   856  		Str string
   857  	}
   858  	type TestStruct struct {
   859  		EmbeddedStruct `db:"-"`
   860  		Int            int64
   861  		Bool           bool
   862  		Valuer         *sql.NullString
   863  	}
   864  	var ts TestStruct
   865  	cm, err := util.GetColumnMap(&ts)
   866  	rt.NoError(err)
   867  	rt.Equal(util.ColumnMap{
   868  		"int":    {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   869  		"bool":   {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
   870  		"valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
   871  	}, cm)
   872  }
   873  
   874  func (rt *reflectTest) TestGetColumnMap_withIgnoredEmbeddedPointerStruct() {
   875  	type EmbeddedStruct struct {
   876  		Str string
   877  	}
   878  	type TestStruct struct {
   879  		*EmbeddedStruct `db:"-"`
   880  		Int             int64
   881  		Bool            bool
   882  		Valuer          *sql.NullString
   883  	}
   884  	var ts TestStruct
   885  	cm, err := util.GetColumnMap(&ts)
   886  	rt.NoError(err)
   887  	rt.Equal(util.ColumnMap{
   888  		"int":    {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   889  		"bool":   {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
   890  		"valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
   891  	}, cm)
   892  }
   893  
   894  func (rt *reflectTest) TestGetColumnMap_withPrivateFields() {
   895  	type TestStruct struct {
   896  		str    string // nolint:structcheck,unused // not used directly but needed for test
   897  		Int    int64
   898  		Bool   bool
   899  		Valuer *sql.NullString
   900  	}
   901  	var ts TestStruct
   902  	cm, err := util.GetColumnMap(&ts)
   903  	rt.NoError(err)
   904  	rt.Equal(util.ColumnMap{
   905  		"int":    {ColumnName: "int", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   906  		"bool":   {ColumnName: "bool", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
   907  		"valuer": {ColumnName: "valuer", FieldIndex: []int{3}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
   908  	}, cm)
   909  }
   910  
   911  func (rt *reflectTest) TestGetColumnMap_withPrivateEmbeddedFields() {
   912  	type TestEmbedded struct {
   913  		str string // nolint:structcheck,unused // not used directly but need for test
   914  		Int int64
   915  	}
   916  
   917  	type TestStruct struct {
   918  		TestEmbedded
   919  		Bool   bool
   920  		Valuer *sql.NullString
   921  	}
   922  	var ts TestStruct
   923  	cm, err := util.GetColumnMap(&ts)
   924  	rt.NoError(err)
   925  	rt.Equal(util.ColumnMap{
   926  		"int":    {ColumnName: "int", FieldIndex: []int{0, 1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(int64(1))},
   927  		"bool":   {ColumnName: "bool", FieldIndex: []int{1}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(true)},
   928  		"valuer": {ColumnName: "valuer", FieldIndex: []int{2}, ShouldInsert: true, ShouldUpdate: true, GoType: reflect.TypeOf(&sql.NullString{})},
   929  	}, cm)
   930  }
   931  
   932  func (rt *reflectTest) TestGetColumnMap_withEmbeddedTaggedStruct() {
   933  	type TestEmbedded struct {
   934  		Bool   bool
   935  		Valuer *sql.NullString
   936  	}
   937  
   938  	type TestStruct struct {
   939  		TestEmbedded `db:"test_embedded"`
   940  		Bool         bool
   941  		Valuer       *sql.NullString
   942  	}
   943  	var ts TestStruct
   944  	cm, err := util.GetColumnMap(&ts)
   945  	rt.NoError(err)
   946  	rt.Equal(util.ColumnMap{
   947  		"test_embedded.bool": {
   948  			ColumnName:   "test_embedded.bool",
   949  			FieldIndex:   []int{0, 0},
   950  			ShouldInsert: true,
   951  			ShouldUpdate: true,
   952  			GoType:       reflect.TypeOf(true),
   953  		},
   954  		"test_embedded.valuer": {
   955  			ColumnName:   "test_embedded.valuer",
   956  			FieldIndex:   []int{0, 1},
   957  			ShouldInsert: true,
   958  			ShouldUpdate: true,
   959  			GoType:       reflect.TypeOf(&sql.NullString{}),
   960  		},
   961  		"bool": {
   962  			ColumnName:   "bool",
   963  			FieldIndex:   []int{1},
   964  			ShouldInsert: true,
   965  			ShouldUpdate: true,
   966  			GoType:       reflect.TypeOf(true),
   967  		},
   968  		"valuer": {
   969  			ColumnName:   "valuer",
   970  			FieldIndex:   []int{2},
   971  			ShouldInsert: true,
   972  			ShouldUpdate: true,
   973  			GoType:       reflect.TypeOf(&sql.NullString{}),
   974  		},
   975  	}, cm)
   976  }
   977  
   978  func (rt *reflectTest) TestGetColumnMap_withEmbeddedTaggedStructPointer() {
   979  	type TestEmbedded struct {
   980  		Bool   bool
   981  		Valuer *sql.NullString
   982  	}
   983  
   984  	type TestStruct struct {
   985  		*TestEmbedded `db:"test_embedded"`
   986  		Bool          bool
   987  		Valuer        *sql.NullString
   988  	}
   989  	var ts TestStruct
   990  	cm, err := util.GetColumnMap(&ts)
   991  	rt.NoError(err)
   992  	rt.Equal(util.ColumnMap{
   993  		"test_embedded.bool": {
   994  			ColumnName:   "test_embedded.bool",
   995  			FieldIndex:   []int{0, 0},
   996  			ShouldInsert: true,
   997  			ShouldUpdate: true,
   998  			GoType:       reflect.TypeOf(true),
   999  		},
  1000  		"test_embedded.valuer": {
  1001  			ColumnName:   "test_embedded.valuer",
  1002  			FieldIndex:   []int{0, 1},
  1003  			ShouldInsert: true, ShouldUpdate: true,
  1004  			GoType: reflect.TypeOf(&sql.NullString{}),
  1005  		},
  1006  		"bool": {
  1007  			ColumnName:   "bool",
  1008  			FieldIndex:   []int{1},
  1009  			ShouldInsert: true,
  1010  			ShouldUpdate: true,
  1011  			GoType:       reflect.TypeOf(true),
  1012  		},
  1013  		"valuer": {
  1014  			ColumnName:   "valuer",
  1015  			FieldIndex:   []int{2},
  1016  			ShouldInsert: true,
  1017  			ShouldUpdate: true,
  1018  			GoType:       reflect.TypeOf(&sql.NullString{}),
  1019  		},
  1020  	}, cm)
  1021  }
  1022  
  1023  func (rt *reflectTest) TestGetColumnMap_withTaggedStructField() {
  1024  	type TestEmbedded struct {
  1025  		Bool   bool
  1026  		Valuer *sql.NullString
  1027  	}
  1028  
  1029  	type TestStruct struct {
  1030  		Embedded TestEmbedded `db:"test_embedded"`
  1031  		Bool     bool
  1032  		Valuer   *sql.NullString
  1033  	}
  1034  	var ts TestStruct
  1035  	cm, err := util.GetColumnMap(&ts)
  1036  	rt.NoError(err)
  1037  	rt.Equal(util.ColumnMap{
  1038  		"test_embedded.bool": {
  1039  			ColumnName:   "test_embedded.bool",
  1040  			FieldIndex:   []int{0, 0},
  1041  			ShouldInsert: true,
  1042  			ShouldUpdate: true,
  1043  			GoType:       reflect.TypeOf(true),
  1044  		},
  1045  		"test_embedded.valuer": {
  1046  			ColumnName:   "test_embedded.valuer",
  1047  			FieldIndex:   []int{0, 1},
  1048  			ShouldInsert: true,
  1049  			ShouldUpdate: true,
  1050  			GoType:       reflect.TypeOf(&sql.NullString{}),
  1051  		},
  1052  		"bool": {
  1053  			ColumnName:   "bool",
  1054  			FieldIndex:   []int{1},
  1055  			ShouldInsert: true,
  1056  			ShouldUpdate: true,
  1057  			GoType:       reflect.TypeOf(true),
  1058  		},
  1059  		"valuer": {
  1060  			ColumnName:   "valuer",
  1061  			FieldIndex:   []int{2},
  1062  			ShouldInsert: true,
  1063  			ShouldUpdate: true,
  1064  			GoType:       reflect.TypeOf(&sql.NullString{}),
  1065  		},
  1066  	}, cm)
  1067  }
  1068  
  1069  func (rt *reflectTest) TestGetColumnMap_withTaggedStructPointerField() {
  1070  	type TestEmbedded struct {
  1071  		Bool   bool
  1072  		Valuer *sql.NullString
  1073  	}
  1074  
  1075  	type TestStruct struct {
  1076  		Embedded *TestEmbedded `db:"test_embedded"`
  1077  		Bool     bool
  1078  		Valuer   *sql.NullString
  1079  	}
  1080  	var ts TestStruct
  1081  	cm, err := util.GetColumnMap(&ts)
  1082  	rt.NoError(err)
  1083  	rt.Equal(util.ColumnMap{
  1084  		"test_embedded.bool": {
  1085  			ColumnName:   "test_embedded.bool",
  1086  			FieldIndex:   []int{0, 0},
  1087  			ShouldInsert: true,
  1088  			ShouldUpdate: true,
  1089  			GoType:       reflect.TypeOf(true),
  1090  		},
  1091  		"test_embedded.valuer": {
  1092  			ColumnName:   "test_embedded.valuer",
  1093  			FieldIndex:   []int{0, 1},
  1094  			ShouldInsert: true,
  1095  			ShouldUpdate: true,
  1096  			GoType:       reflect.TypeOf(&sql.NullString{}),
  1097  		},
  1098  		"bool": {
  1099  			ColumnName:   "bool",
  1100  			FieldIndex:   []int{1},
  1101  			ShouldInsert: true,
  1102  			ShouldUpdate: true,
  1103  			GoType:       reflect.TypeOf(true),
  1104  		},
  1105  		"valuer": {
  1106  			ColumnName:   "valuer",
  1107  			FieldIndex:   []int{2},
  1108  			ShouldInsert: true,
  1109  			ShouldUpdate: true,
  1110  			GoType:       reflect.TypeOf(&sql.NullString{}),
  1111  		},
  1112  	}, cm)
  1113  }
  1114  
  1115  func (rt *reflectTest) TestGetTypeInfo() {
  1116  	var a int64
  1117  	var b []int64
  1118  	var c []*time.Time
  1119  
  1120  	t, k := util.GetTypeInfo(&a, reflect.ValueOf(a))
  1121  	rt.Equal(reflect.TypeOf(a), t)
  1122  	rt.Equal(reflect.Int64, k)
  1123  
  1124  	t, k = util.GetTypeInfo(&b, reflect.ValueOf(a))
  1125  	rt.Equal(reflect.TypeOf(a), t)
  1126  	rt.Equal(reflect.Int64, k)
  1127  
  1128  	t, k = util.GetTypeInfo(c, reflect.ValueOf(c))
  1129  	rt.Equal(reflect.TypeOf(time.Time{}), t)
  1130  	rt.Equal(reflect.Struct, k)
  1131  }
  1132  
  1133  func (rt *reflectTest) TestSafeGetFieldByIndex() {
  1134  	type TestEmbedded struct {
  1135  		FieldA int
  1136  	}
  1137  	type TestEmbeddedPointerStruct struct {
  1138  		*TestEmbedded
  1139  		FieldB string
  1140  	}
  1141  	type TestEmbeddedStruct struct {
  1142  		TestEmbedded
  1143  		FieldB string
  1144  	}
  1145  	v := reflect.ValueOf(TestEmbeddedPointerStruct{})
  1146  	f, isAvailable := util.SafeGetFieldByIndex(v, []int{0, 0})
  1147  	rt.False(isAvailable)
  1148  	rt.False(f.IsValid())
  1149  	f, isAvailable = util.SafeGetFieldByIndex(v, []int{1})
  1150  	rt.True(isAvailable)
  1151  	rt.True(f.IsValid())
  1152  	rt.Equal(reflect.String, f.Type().Kind())
  1153  	f, isAvailable = util.SafeGetFieldByIndex(v, []int{})
  1154  	rt.True(isAvailable)
  1155  	rt.Equal(v, f)
  1156  
  1157  	v = reflect.ValueOf(TestEmbeddedPointerStruct{TestEmbedded: &TestEmbedded{}})
  1158  	f, isAvailable = util.SafeGetFieldByIndex(v, []int{0, 0})
  1159  	rt.True(isAvailable)
  1160  	rt.True(f.IsValid())
  1161  	rt.Equal(reflect.Int, f.Type().Kind())
  1162  	f, isAvailable = util.SafeGetFieldByIndex(v, []int{1})
  1163  	rt.True(isAvailable)
  1164  	rt.True(f.IsValid())
  1165  	rt.Equal(reflect.String, f.Type().Kind())
  1166  	f, isAvailable = util.SafeGetFieldByIndex(v, []int{})
  1167  	rt.True(isAvailable)
  1168  	rt.Equal(v, f)
  1169  
  1170  	v = reflect.ValueOf(TestEmbeddedStruct{})
  1171  	f, isAvailable = util.SafeGetFieldByIndex(v, []int{0, 0})
  1172  	rt.True(isAvailable)
  1173  	rt.True(f.IsValid())
  1174  	rt.Equal(reflect.Int, f.Type().Kind())
  1175  	f, isAvailable = util.SafeGetFieldByIndex(v, []int{1})
  1176  	rt.True(isAvailable)
  1177  	rt.True(f.IsValid())
  1178  	rt.Equal(reflect.String, f.Type().Kind())
  1179  	f, isAvailable = util.SafeGetFieldByIndex(v, []int{})
  1180  	rt.True(isAvailable)
  1181  	rt.Equal(v, f)
  1182  
  1183  	v = reflect.ValueOf(TestEmbeddedStruct{TestEmbedded: TestEmbedded{}})
  1184  	f, isAvailable = util.SafeGetFieldByIndex(v, []int{0, 0})
  1185  	rt.True(isAvailable)
  1186  	rt.True(f.IsValid())
  1187  	f, isAvailable = util.SafeGetFieldByIndex(v, []int{1})
  1188  	rt.True(isAvailable)
  1189  	rt.True(f.IsValid())
  1190  	rt.Equal(reflect.String, f.Type().Kind())
  1191  	f, isAvailable = util.SafeGetFieldByIndex(v, []int{})
  1192  	rt.True(isAvailable)
  1193  	rt.Equal(v, f)
  1194  }
  1195  
  1196  func (rt *reflectTest) TestSafeSetFieldByIndex() {
  1197  	type TestEmbedded struct {
  1198  		FieldA int
  1199  	}
  1200  	type TestEmbeddedPointerStruct struct {
  1201  		*TestEmbedded
  1202  		FieldB string
  1203  	}
  1204  	type TestEmbeddedStruct struct {
  1205  		TestEmbedded
  1206  		FieldB string
  1207  	}
  1208  	var teps TestEmbeddedPointerStruct
  1209  	v := reflect.ValueOf(&teps)
  1210  	f := util.SafeSetFieldByIndex(v, []int{}, nil)
  1211  	rt.Equal(TestEmbeddedPointerStruct{}, f.Interface())
  1212  
  1213  	f = util.SafeSetFieldByIndex(v, []int{0, 0}, 1)
  1214  	rt.Equal(TestEmbeddedPointerStruct{
  1215  		TestEmbedded: &TestEmbedded{FieldA: 1},
  1216  	}, f.Interface())
  1217  
  1218  	f = util.SafeSetFieldByIndex(v, []int{1}, "hello")
  1219  	rt.Equal(TestEmbeddedPointerStruct{
  1220  		TestEmbedded: &TestEmbedded{FieldA: 1},
  1221  		FieldB:       "hello",
  1222  	}, f.Interface())
  1223  	rt.Equal(TestEmbeddedPointerStruct{
  1224  		TestEmbedded: &TestEmbedded{FieldA: 1},
  1225  		FieldB:       "hello",
  1226  	}, teps)
  1227  
  1228  	var tes TestEmbeddedStruct
  1229  	v = reflect.ValueOf(&tes)
  1230  	f = util.SafeSetFieldByIndex(v, []int{}, nil)
  1231  	rt.Equal(TestEmbeddedStruct{}, f.Interface())
  1232  
  1233  	f = util.SafeSetFieldByIndex(v, []int{0, 0}, 1)
  1234  	rt.Equal(TestEmbeddedStruct{
  1235  		TestEmbedded: TestEmbedded{FieldA: 1},
  1236  	}, f.Interface())
  1237  
  1238  	f = util.SafeSetFieldByIndex(v, []int{1}, "hello")
  1239  	rt.Equal(TestEmbeddedStruct{
  1240  		TestEmbedded: TestEmbedded{FieldA: 1},
  1241  		FieldB:       "hello",
  1242  	}, f.Interface())
  1243  	rt.Equal(TestEmbeddedStruct{
  1244  		TestEmbedded: TestEmbedded{FieldA: 1},
  1245  		FieldB:       "hello",
  1246  	}, tes)
  1247  }
  1248  
  1249  func (rt *reflectTest) TestGetSliceElementType() {
  1250  	type MyStruct struct{}
  1251  
  1252  	tests := []struct {
  1253  		slice interface{}
  1254  		want  reflect.Type
  1255  	}{
  1256  		{
  1257  			slice: []int{},
  1258  			want:  reflect.TypeOf(1),
  1259  		},
  1260  		{
  1261  			slice: []*int{},
  1262  			want:  reflect.TypeOf(1),
  1263  		},
  1264  		{
  1265  			slice: []MyStruct{},
  1266  			want:  reflect.TypeOf(MyStruct{}),
  1267  		},
  1268  		{
  1269  			slice: []*MyStruct{},
  1270  			want:  reflect.TypeOf(MyStruct{}),
  1271  		},
  1272  	}
  1273  
  1274  	for _, tt := range tests {
  1275  		sliceVal := reflect.ValueOf(tt.slice)
  1276  		elementType := util.GetSliceElementType(sliceVal)
  1277  
  1278  		rt.Equal(tt.want, elementType)
  1279  	}
  1280  }
  1281  
  1282  func (rt *reflectTest) TestAppendSliceElement() {
  1283  	type MyStruct struct{}
  1284  
  1285  	sliceVal := reflect.Indirect(reflect.ValueOf(&[]MyStruct{}))
  1286  	util.AppendSliceElement(sliceVal, reflect.ValueOf(&MyStruct{}))
  1287  
  1288  	rt.Equal([]MyStruct{{}}, sliceVal.Interface())
  1289  
  1290  	sliceVal = reflect.Indirect(reflect.ValueOf(&[]*MyStruct{}))
  1291  	util.AppendSliceElement(sliceVal, reflect.ValueOf(&MyStruct{}))
  1292  
  1293  	rt.Equal([]*MyStruct{{}}, sliceVal.Interface())
  1294  }
  1295  
  1296  func TestReflectSuite(t *testing.T) {
  1297  	suite.Run(t, new(reflectTest))
  1298  }
  1299  

View as plain text