github.com/gogf/gf/v2@v2.7.4/util/gconv/gconv_z_unit_scan_test.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gconv_test
     8  
     9  import (
    10  	"fmt"
    11  	"testing"
    12  
    13  	"github.com/gogf/gf/v2/container/gvar"
    14  	"github.com/gogf/gf/v2/errors/gerror"
    15  	"github.com/gogf/gf/v2/frame/g"
    16  	"github.com/gogf/gf/v2/os/gtime"
    17  	"github.com/gogf/gf/v2/test/gtest"
    18  	"github.com/gogf/gf/v2/util/gconv"
    19  )
    20  
    21  type scanStructTest struct {
    22  	Name  string
    23  	Place string
    24  }
    25  
    26  type scanExpectTest struct {
    27  	mapStrStr map[string]string
    28  	mapStrAny map[string]interface{}
    29  	mapAnyAny map[interface{}]interface{}
    30  
    31  	structSub    scanStructTest
    32  	structSubPtr *scanStructTest
    33  }
    34  
    35  var scanValueMapsTest = []map[string]interface{}{
    36  	{"Name": false, "Place": true},
    37  	{"Name": int(0), "Place": int(1)},
    38  	{"Name": int8(0), "Place": int8(1)},
    39  	{"Name": int16(0), "Place": int16(1)},
    40  	{"Name": int32(0), "Place": int32(1)},
    41  	{"Name": int64(0), "Place": int64(1)},
    42  	{"Name": uint(0), "Place": uint(1)},
    43  	{"Name": uint8(0), "Place": uint8(1)},
    44  	{"Name": uint16(0), "Place": uint16(1)},
    45  	{"Name": uint32(0), "Place": uint32(1)},
    46  	{"Name": uint64(0), "Place": uint64(1)},
    47  	{"Name": float32(0), "Place": float32(1)},
    48  	{"Name": float64(0), "Place": float64(1)},
    49  	{"Name": "Mercury", "Place": "卡罗利斯盆地"},
    50  	{"Name": []byte("Saturn"), "Place": []byte("土星环")},
    51  	{"Name": complex64(0), "Place": complex64(1 + 2i)},
    52  	{"Name": complex128(0), "Place": complex128(1 + 2i)},
    53  	{"Name": interface{}(0), "Place": interface{}("1")},
    54  	{"Name": gvar.New("Jupiter"), "Place": gvar.New("大红斑")},
    55  	{"Name": gtime.New("2024-01-01 01:01:01"), "Place": gtime.New("2021-01-01 01:01:01")},
    56  	{"Name": map[string]string{"Name": "Sun"}, "Place": map[string]string{"Place": "太阳黑子"}},
    57  	{"Name": []string{"Earth", "Moon"}, "Place": []string{"好望角", "万户环形山"}},
    58  }
    59  
    60  var scanValueStructsTest = []scanStructTest{
    61  	{"Venus", "阿佛洛狄特高原"},
    62  }
    63  
    64  var scanValueJsonTest = []string{
    65  	`{"Name": "Mars", "Place": "奥林帕斯山"}`,
    66  }
    67  
    68  var scanExpects = scanExpectTest{
    69  	mapStrStr: make(map[string]string),
    70  	mapStrAny: make(map[string]interface{}),
    71  	mapAnyAny: make(map[interface{}]interface{}),
    72  
    73  	structSub:    scanStructTest{},
    74  	structSubPtr: &scanStructTest{},
    75  }
    76  
    77  func TestScan(t *testing.T) {
    78  	// Test for map converting.
    79  	gtest.C(t, func(t *gtest.T) {
    80  		scanValuesTest := scanValueMapsTest
    81  		for _, test := range scanValuesTest {
    82  			var (
    83  				err         error
    84  				scanExpects = scanExpects
    85  			)
    86  
    87  			err = gconv.Scan(test, &scanExpects.mapStrStr)
    88  			t.AssertNil(err)
    89  			t.Assert(test["Name"], scanExpects.mapStrStr["Name"])
    90  			t.Assert(test["Place"], scanExpects.mapStrStr["Place"])
    91  
    92  			err = gconv.Scan(test, &scanExpects.mapStrAny)
    93  			t.AssertNil(err)
    94  			t.Assert(test["Name"], scanExpects.mapStrAny["Name"])
    95  			t.Assert(test["Place"], scanExpects.mapStrAny["Place"])
    96  
    97  			err = gconv.Scan(test, &scanExpects.mapAnyAny)
    98  			t.AssertNil(err)
    99  			t.Assert(test["Name"], scanExpects.mapAnyAny["Name"])
   100  			t.Assert(test["Place"], scanExpects.mapAnyAny["Place"])
   101  
   102  			err = gconv.Scan(test, &scanExpects.structSub)
   103  			t.AssertNil(err)
   104  			t.Assert(test["Name"], scanExpects.structSub.Name)
   105  			t.Assert(test["Place"], scanExpects.structSub.Place)
   106  
   107  			err = gconv.Scan(test, &scanExpects.structSubPtr)
   108  			t.AssertNil(err)
   109  			t.Assert(test["Name"], scanExpects.structSubPtr.Name)
   110  			t.Assert(test["Place"], scanExpects.structSubPtr.Place)
   111  
   112  		}
   113  	})
   114  
   115  	// Test for slice map converting.
   116  	gtest.C(t, func(t *gtest.T) {
   117  		scanValuesTest := scanValueMapsTest
   118  		for _, test := range scanValuesTest {
   119  			var (
   120  				err         error
   121  				scanExpects = scanExpects
   122  				maps        = []map[string]interface{}{test, test}
   123  			)
   124  
   125  			var mss = []map[string]string{scanExpects.mapStrStr, scanExpects.mapStrStr}
   126  			err = gconv.Scan(maps, &mss)
   127  			t.AssertNil(err)
   128  			t.Assert(len(mss), len(maps))
   129  			for k, _ := range maps {
   130  				t.Assert(maps[k]["Name"], mss[k]["Name"])
   131  				t.Assert(maps[k]["Place"], mss[k]["Place"])
   132  			}
   133  
   134  			var msa = []map[string]interface{}{scanExpects.mapStrAny, scanExpects.mapStrAny}
   135  			err = gconv.Scan(maps, &msa)
   136  			t.AssertNil(err)
   137  			t.Assert(len(msa), len(maps))
   138  			for k, _ := range maps {
   139  				t.Assert(maps[k]["Name"], msa[k]["Name"])
   140  				t.Assert(maps[k]["Place"], msa[k]["Place"])
   141  			}
   142  
   143  			var maa = []map[interface{}]interface{}{scanExpects.mapAnyAny, scanExpects.mapAnyAny}
   144  			err = gconv.Scan(maps, &maa)
   145  			t.AssertNil(err)
   146  			t.Assert(len(maa), len(maps))
   147  			for k, _ := range maps {
   148  				t.Assert(maps[k]["Name"], maa[k]["Name"])
   149  				t.Assert(maps[k]["Place"], maa[k]["Place"])
   150  			}
   151  
   152  			var ss = []scanStructTest{scanExpects.structSub, scanExpects.structSub}
   153  			err = gconv.Scan(maps, &ss)
   154  			t.AssertNil(err)
   155  			t.Assert(len(ss), len(maps))
   156  			for k, _ := range maps {
   157  				t.Assert(maps[k]["Name"], ss[k].Name)
   158  				t.Assert(maps[k]["Place"], ss[k].Place)
   159  			}
   160  
   161  			var ssp = []*scanStructTest{scanExpects.structSubPtr, scanExpects.structSubPtr}
   162  			err = gconv.Scan(maps, &ssp)
   163  			t.AssertNil(err)
   164  			t.Assert(len(ssp), len(maps))
   165  			for k, _ := range maps {
   166  				t.Assert(maps[k]["Name"], ssp[k].Name)
   167  				t.Assert(maps[k]["Place"], ssp[k].Place)
   168  			}
   169  		}
   170  	})
   171  
   172  	// Test for struct converting.
   173  	gtest.C(t, func(t *gtest.T) {
   174  		scanValuesTest := scanValueStructsTest
   175  		for _, test := range scanValuesTest {
   176  			var (
   177  				err         error
   178  				scanExpects = scanExpects
   179  			)
   180  
   181  			err = gconv.Scan(test, &scanExpects.mapStrStr)
   182  			t.AssertNil(err)
   183  			t.Assert(test.Name, scanExpects.mapStrStr["Name"])
   184  			t.Assert(test.Place, scanExpects.mapStrStr["Place"])
   185  
   186  			err = gconv.Scan(test, &scanExpects.mapStrAny)
   187  			t.AssertNil(err)
   188  			t.Assert(test.Name, scanExpects.mapStrAny["Name"])
   189  			t.Assert(test.Place, scanExpects.mapStrAny["Place"])
   190  
   191  			err = gconv.Scan(test, &scanExpects.mapAnyAny)
   192  			t.AssertNil(err)
   193  			t.Assert(test.Name, scanExpects.mapAnyAny["Name"])
   194  			t.Assert(test.Place, scanExpects.mapAnyAny["Place"])
   195  
   196  			err = gconv.Scan(test, &scanExpects.structSub)
   197  			t.AssertNil(err)
   198  			t.Assert(test.Name, scanExpects.structSub.Name)
   199  			t.Assert(test.Place, scanExpects.structSub.Place)
   200  
   201  			err = gconv.Scan(test, &scanExpects.structSubPtr)
   202  			t.AssertNil(err)
   203  			t.Assert(test.Name, scanExpects.structSubPtr.Name)
   204  			t.Assert(test.Place, scanExpects.structSubPtr.Place)
   205  		}
   206  	})
   207  
   208  	// Test for slice struct converting.
   209  	gtest.C(t, func(t *gtest.T) {
   210  		scanValuesTest := scanValueStructsTest
   211  		for _, test := range scanValuesTest {
   212  			var (
   213  				err         error
   214  				scanExpects = scanExpects
   215  				structs     = []scanStructTest{test, test}
   216  			)
   217  
   218  			var mss = []map[string]string{scanExpects.mapStrStr, scanExpects.mapStrStr}
   219  			err = gconv.Scan(structs, &mss)
   220  			t.AssertNil(err)
   221  			t.Assert(len(mss), len(structs))
   222  			for k, _ := range structs {
   223  				t.Assert(structs[k].Name, mss[k]["Name"])
   224  				t.Assert(structs[k].Place, mss[k]["Place"])
   225  			}
   226  
   227  			var msa = []map[string]interface{}{scanExpects.mapStrAny, scanExpects.mapStrAny}
   228  			err = gconv.Scan(structs, &msa)
   229  			t.AssertNil(err)
   230  			t.Assert(len(msa), len(structs))
   231  			for k, _ := range structs {
   232  				t.Assert(structs[k].Name, msa[k]["Name"])
   233  				t.Assert(structs[k].Place, msa[k]["Place"])
   234  			}
   235  
   236  			var maa = []map[interface{}]interface{}{scanExpects.mapAnyAny, scanExpects.mapAnyAny}
   237  			err = gconv.Scan(structs, &maa)
   238  			t.AssertNil(err)
   239  			t.Assert(len(maa), len(structs))
   240  			for k, _ := range structs {
   241  				t.Assert(structs[k].Name, maa[k]["Name"])
   242  				t.Assert(structs[k].Place, maa[k]["Place"])
   243  			}
   244  
   245  			var ss = []scanStructTest{scanExpects.structSub, scanExpects.structSub}
   246  			err = gconv.Scan(structs, &ss)
   247  			t.AssertNil(err)
   248  			t.Assert(len(ss), len(structs))
   249  			for k, _ := range structs {
   250  				t.Assert(structs[k].Name, ss[k].Name)
   251  				t.Assert(structs[k].Place, ss[k].Place)
   252  			}
   253  
   254  			var ssp = []*scanStructTest{scanExpects.structSubPtr, scanExpects.structSubPtr}
   255  			err = gconv.Scan(structs, &ssp)
   256  			t.AssertNil(err)
   257  			t.Assert(len(ssp), len(structs))
   258  			for k, _ := range structs {
   259  				t.Assert(structs[k].Name, ssp[k].Name)
   260  				t.Assert(structs[k].Place, ssp[k].Place)
   261  			}
   262  		}
   263  	})
   264  
   265  	// Test for json converting.
   266  	gtest.C(t, func(t *gtest.T) {
   267  		scanValuesTest := scanValueJsonTest
   268  		for _, test := range scanValuesTest {
   269  			var (
   270  				err         error
   271  				scanExpects = scanExpects
   272  			)
   273  
   274  			err = gconv.Scan(test, &scanExpects.mapStrStr)
   275  			t.AssertNil(err)
   276  			t.Assert("Mars", scanExpects.mapStrStr["Name"])
   277  			t.Assert("奥林帕斯山", scanExpects.mapStrStr["Place"])
   278  
   279  			err = gconv.Scan(test, &scanExpects.mapStrAny)
   280  			t.AssertNil(err)
   281  			t.Assert("Mars", scanExpects.mapStrAny["Name"])
   282  			t.Assert("奥林帕斯山", scanExpects.mapStrAny["Place"])
   283  
   284  			err = gconv.Scan(test, &scanExpects.mapAnyAny)
   285  			t.Assert(err, gerror.New(
   286  				"json.UnmarshalUseNumber failed: json: cannot unmarshal object into Go value of type map[interface {}]interface {}",
   287  			))
   288  
   289  			err = gconv.Scan(test, &scanExpects.structSub)
   290  			t.AssertNil(err)
   291  			t.Assert("Mars", scanExpects.structSub.Name)
   292  			t.Assert("奥林帕斯山", scanExpects.structSub.Place)
   293  
   294  			err = gconv.Scan(test, &scanExpects.structSubPtr)
   295  			t.AssertNil(err)
   296  			t.Assert("Mars", scanExpects.structSubPtr.Name)
   297  			t.Assert("奥林帕斯山", scanExpects.structSubPtr.Place)
   298  		}
   299  	})
   300  
   301  	// Test for slice json converting.
   302  	gtest.C(t, func(t *gtest.T) {
   303  		scanValuesTest := scanValueJsonTest
   304  		for _, test := range scanValuesTest {
   305  			var (
   306  				err         error
   307  				scanExpects = scanExpects
   308  				jsons       = fmt.Sprintf("[%s, %s]", test, test)
   309  			)
   310  
   311  			var mss = []map[string]string{scanExpects.mapStrStr, scanExpects.mapStrStr}
   312  			err = gconv.Scan(jsons, &mss)
   313  			t.AssertNil(err)
   314  			t.Assert(len(mss), 2)
   315  			for k, _ := range mss {
   316  				t.Assert("Mars", mss[k]["Name"])
   317  				t.Assert("奥林帕斯山", mss[k]["Place"])
   318  			}
   319  
   320  			var msa = []map[string]interface{}{scanExpects.mapStrAny, scanExpects.mapStrAny}
   321  			err = gconv.Scan(jsons, &msa)
   322  			t.AssertNil(err)
   323  			t.Assert(len(msa), 2)
   324  			for k, _ := range msa {
   325  				t.Assert("Mars", msa[k]["Name"])
   326  				t.Assert("奥林帕斯山", msa[k]["Place"])
   327  			}
   328  
   329  			var maa = []map[interface{}]interface{}{scanExpects.mapAnyAny, scanExpects.mapAnyAny}
   330  			err = gconv.Scan(jsons, &maa)
   331  			t.Assert(err, gerror.New(
   332  				"json.UnmarshalUseNumber failed: json: cannot unmarshal object into Go value of type map[interface {}]interface {}",
   333  			))
   334  
   335  			var ss = []scanStructTest{scanExpects.structSub, scanExpects.structSub}
   336  			err = gconv.Scan(jsons, &ss)
   337  			t.AssertNil(err)
   338  			t.Assert(len(ss), 2)
   339  			for k, _ := range ss {
   340  				t.Assert("Mars", ss[k].Name)
   341  				t.Assert("奥林帕斯山", ss[k].Place)
   342  			}
   343  
   344  			var ssp = []*scanStructTest{scanExpects.structSubPtr, scanExpects.structSubPtr}
   345  			err = gconv.Scan(jsons, &ssp)
   346  			t.AssertNil(err)
   347  			t.Assert(len(ssp), 2)
   348  			for k, _ := range ssp {
   349  				t.Assert("Mars", ssp[k].Name)
   350  				t.Assert("奥林帕斯山", ssp[k].Place)
   351  			}
   352  		}
   353  	})
   354  
   355  	// Test for paramKeyToAttrMap
   356  	gtest.C(t, func(t *gtest.T) {
   357  		scanValuesTest := scanValueMapsTest
   358  		for _, test := range scanValuesTest {
   359  			var (
   360  				err          error
   361  				scanExpects  = scanExpects
   362  				mapParameter = map[string]string{"Name": "Place", "Place": "Name"}
   363  			)
   364  
   365  			// TODO: The following test cases should be working, but they are not.
   366  			//err = gconv.Scan(test, &scanExpects.mapStrStr, mapParameter)
   367  			//t.AssertNil(err)
   368  			//t.Assert(test["Name"], scanExpects.mapStrStr["Place"])
   369  			//t.Assert(test["Place"], scanExpects.mapStrStr["Name"])
   370  			//
   371  			//err = gconv.Scan(test, &scanExpects.mapStrAny, mapParameter)
   372  			//t.AssertNil(err)
   373  			//t.Assert(test["Name"], scanExpects.mapStrAny["Place"])
   374  			//t.Assert(test["Place"], scanExpects.mapStrAny["Name"])
   375  			//
   376  			//err = gconv.Scan(test, &scanExpects.mapAnyAny, mapParameter)
   377  			//t.AssertNil(err)
   378  			//t.Assert(test["Name"], scanExpects.mapAnyAny["Place"])
   379  			//t.Assert(test["Place"], scanExpects.mapAnyAny["Name"])
   380  
   381  			err = gconv.Scan(test, &scanExpects.structSub, mapParameter)
   382  			t.AssertNil(err)
   383  			t.Assert(test["Name"], scanExpects.structSub.Place)
   384  			t.Assert(test["Place"], scanExpects.structSub.Name)
   385  
   386  			err = gconv.Scan(test, &scanExpects.structSubPtr, mapParameter)
   387  			t.AssertNil(err)
   388  			t.Assert(test["Name"], scanExpects.structSubPtr.Place)
   389  			t.Assert(test["Place"], scanExpects.structSubPtr.Name)
   390  		}
   391  	})
   392  
   393  	// Test for special types.
   394  	gtest.C(t, func(t *gtest.T) {
   395  		var (
   396  			err error
   397  			src = "Sun"
   398  			dst = "日冕"
   399  		)
   400  
   401  		err = gconv.Scan(nil, &dst)
   402  		t.AssertNil(err)
   403  		t.Assert(dst, "日冕")
   404  
   405  		err = gconv.Scan(src, nil)
   406  		t.Assert(err, gerror.New("destination pointer should not be nil"))
   407  
   408  		// Test for non-pointer.
   409  		err = gconv.Scan(src, dst)
   410  		t.Assert(err, gerror.New(
   411  			"destination pointer should be type of pointer, but got type: string",
   412  		))
   413  	})
   414  }
   415  
   416  func TestScanEmptyStringToCustomType(t *testing.T) {
   417  	gtest.C(t, func(t *gtest.T) {
   418  		type Status string
   419  		type Req struct {
   420  			Name     string
   421  			Statuses []Status
   422  			Types    []string
   423  		}
   424  		var (
   425  			req  *Req
   426  			data = g.Map{
   427  				"Name":     "john",
   428  				"Statuses": "",
   429  				"Types":    "",
   430  			}
   431  		)
   432  		err := gconv.Scan(data, &req)
   433  		t.AssertNil(err)
   434  		t.Assert(len(req.Statuses), 0)
   435  		t.Assert(len(req.Types), 0)
   436  	})
   437  }