github.com/wangyougui/gf/v2@v2.6.5/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/wangyougui/gf.
     6  
     7  package gconv_test
     8  
     9  import (
    10  	"fmt"
    11  	"math/big"
    12  	"testing"
    13  
    14  	"github.com/wangyougui/gf/v2/container/gvar"
    15  	"github.com/wangyougui/gf/v2/frame/g"
    16  	"github.com/wangyougui/gf/v2/test/gtest"
    17  	"github.com/wangyougui/gf/v2/util/gconv"
    18  )
    19  
    20  func Test_Scan_WithMapParameter(t *testing.T) {
    21  	type User struct {
    22  		Uid  int
    23  		Name string
    24  	}
    25  	gtest.C(t, func(t *gtest.T) {
    26  		for i := 0; i < 100; i++ {
    27  			var (
    28  				user   = new(User)
    29  				params = g.Map{
    30  					"uid":    1,
    31  					"myname": "john",
    32  					"name":   "smith",
    33  				}
    34  			)
    35  			err := gconv.Scan(params, user, g.MapStrStr{
    36  				"myname": "Name",
    37  			})
    38  			t.AssertNil(err)
    39  			t.Assert(user, &User{
    40  				Uid:  1,
    41  				Name: "john",
    42  			})
    43  		}
    44  	})
    45  }
    46  
    47  func Test_Scan_StructStructs(t *testing.T) {
    48  	type User struct {
    49  		Uid   int
    50  		Name  string
    51  		Pass1 string `gconv:"password1"`
    52  		Pass2 string `gconv:"password2"`
    53  	}
    54  	gtest.C(t, func(t *gtest.T) {
    55  		var (
    56  			user   = new(User)
    57  			params = g.Map{
    58  				"uid":   1,
    59  				"name":  "john",
    60  				"PASS1": "123",
    61  				"PASS2": "456",
    62  			}
    63  		)
    64  		err := gconv.Scan(params, user)
    65  		t.AssertNil(err)
    66  		t.Assert(user, &User{
    67  			Uid:   1,
    68  			Name:  "john",
    69  			Pass1: "123",
    70  			Pass2: "456",
    71  		})
    72  	})
    73  	gtest.C(t, func(t *gtest.T) {
    74  		var (
    75  			users  []User
    76  			params = g.Slice{
    77  				g.Map{
    78  					"uid":   1,
    79  					"name":  "john1",
    80  					"PASS1": "111",
    81  					"PASS2": "222",
    82  				},
    83  				g.Map{
    84  					"uid":   2,
    85  					"name":  "john2",
    86  					"PASS1": "333",
    87  					"PASS2": "444",
    88  				},
    89  			}
    90  		)
    91  		err := gconv.Scan(params, &users)
    92  		t.AssertNil(err)
    93  		t.Assert(users, g.Slice{
    94  			&User{
    95  				Uid:   1,
    96  				Name:  "john1",
    97  				Pass1: "111",
    98  				Pass2: "222",
    99  			},
   100  			&User{
   101  				Uid:   2,
   102  				Name:  "john2",
   103  				Pass1: "333",
   104  				Pass2: "444",
   105  			},
   106  		})
   107  	})
   108  }
   109  
   110  func Test_Scan_StructStr(t *testing.T) {
   111  	type User struct {
   112  		Uid   int
   113  		Name  string
   114  		Pass1 string `gconv:"password1"`
   115  		Pass2 string `gconv:"password2"`
   116  	}
   117  	gtest.C(t, func(t *gtest.T) {
   118  		var (
   119  			user   = new(User)
   120  			params = `{"uid":1,"name":"john", "pass1":"123","pass2":"456"}`
   121  		)
   122  		err := gconv.Scan(params, user)
   123  		t.AssertNil(err)
   124  		t.Assert(user, &User{
   125  			Uid:   1,
   126  			Name:  "john",
   127  			Pass1: "123",
   128  			Pass2: "456",
   129  		})
   130  	})
   131  	gtest.C(t, func(t *gtest.T) {
   132  		var (
   133  			users  []User
   134  			params = `[
   135  {"uid":1,"name":"john1", "pass1":"111","pass2":"222"},
   136  {"uid":2,"name":"john2", "pass1":"333","pass2":"444"}
   137  ]`
   138  		)
   139  		err := gconv.Scan(params, &users)
   140  		t.AssertNil(err)
   141  		t.Assert(users, g.Slice{
   142  			&User{
   143  				Uid:   1,
   144  				Name:  "john1",
   145  				Pass1: "111",
   146  				Pass2: "222",
   147  			},
   148  			&User{
   149  				Uid:   2,
   150  				Name:  "john2",
   151  				Pass1: "333",
   152  				Pass2: "444",
   153  			},
   154  		})
   155  	})
   156  }
   157  
   158  func Test_Scan_Map(t *testing.T) {
   159  	gtest.C(t, func(t *gtest.T) {
   160  		var m map[string]string
   161  		data := g.Map{
   162  			"k1": "v1",
   163  			"k2": "v2",
   164  		}
   165  		err := gconv.Scan(data, &m)
   166  		t.AssertNil(err)
   167  		t.Assert(data, m)
   168  	})
   169  	gtest.C(t, func(t *gtest.T) {
   170  		var m map[int]int
   171  		data := g.Map{
   172  			"1": "11",
   173  			"2": "22",
   174  		}
   175  		err := gconv.Scan(data, &m)
   176  		t.AssertNil(err)
   177  		t.Assert(data, m)
   178  	})
   179  	// json string parameter.
   180  	gtest.C(t, func(t *gtest.T) {
   181  		var m map[string]string
   182  		data := `{"k1":"v1","k2":"v2"}`
   183  		err := gconv.Scan(data, &m)
   184  		t.AssertNil(err)
   185  		t.Assert(m, g.Map{
   186  			"k1": "v1",
   187  			"k2": "v2",
   188  		})
   189  	})
   190  }
   191  
   192  func Test_Scan_Maps(t *testing.T) {
   193  	gtest.C(t, func(t *gtest.T) {
   194  		var maps []map[string]string
   195  		data := g.Slice{
   196  			g.Map{
   197  				"k1": "v1",
   198  				"k2": "v2",
   199  			},
   200  			g.Map{
   201  				"k3": "v3",
   202  				"k4": "v4",
   203  			},
   204  		}
   205  		err := gconv.Scan(data, &maps)
   206  		t.AssertNil(err)
   207  		t.Assert(data, maps)
   208  	})
   209  	// json string parameter.
   210  	gtest.C(t, func(t *gtest.T) {
   211  		var maps []map[string]string
   212  		data := `[{"k1":"v1","k2":"v2"},{"k3":"v3","k4":"v4"}]`
   213  		err := gconv.Scan(data, &maps)
   214  		t.AssertNil(err)
   215  		t.Assert(maps, g.Slice{
   216  			g.Map{
   217  				"k1": "v1",
   218  				"k2": "v2",
   219  			},
   220  			g.Map{
   221  				"k3": "v3",
   222  				"k4": "v4",
   223  			},
   224  		})
   225  	})
   226  }
   227  
   228  func Test_Scan_JsonAttributes(t *testing.T) {
   229  	gtest.C(t, func(t *gtest.T) {
   230  		type Sku struct {
   231  			GiftId      int64  `json:"gift_id"`
   232  			Name        string `json:"name"`
   233  			ScorePrice  int    `json:"score_price"`
   234  			MarketPrice int    `json:"market_price"`
   235  			CostPrice   int    `json:"cost_price"`
   236  			Stock       int    `json:"stock"`
   237  		}
   238  		v := gvar.New(`
   239  [
   240  {"name": "red", "stock": 10, "gift_id": 1, "cost_price": 80, "score_price": 188, "market_price": 188}, 
   241  {"name": "blue", "stock": 100, "gift_id": 2, "cost_price": 81, "score_price": 200, "market_price": 288}
   242  ]`)
   243  		type Product struct {
   244  			Skus []Sku
   245  		}
   246  		var p *Product
   247  		err := gconv.Scan(g.Map{
   248  			"Skus": v,
   249  		}, &p)
   250  		t.AssertNil(err)
   251  		t.Assert(len(p.Skus), 2)
   252  
   253  		t.Assert(p.Skus[0].Name, "red")
   254  		t.Assert(p.Skus[0].Stock, 10)
   255  		t.Assert(p.Skus[0].GiftId, 1)
   256  		t.Assert(p.Skus[0].CostPrice, 80)
   257  		t.Assert(p.Skus[0].ScorePrice, 188)
   258  		t.Assert(p.Skus[0].MarketPrice, 188)
   259  
   260  		t.Assert(p.Skus[1].Name, "blue")
   261  		t.Assert(p.Skus[1].Stock, 100)
   262  		t.Assert(p.Skus[1].GiftId, 2)
   263  		t.Assert(p.Skus[1].CostPrice, 81)
   264  		t.Assert(p.Skus[1].ScorePrice, 200)
   265  		t.Assert(p.Skus[1].MarketPrice, 288)
   266  	})
   267  }
   268  
   269  func Test_Scan_JsonAttributes_StringArray(t *testing.T) {
   270  	gtest.C(t, func(t *gtest.T) {
   271  		type S struct {
   272  			Array []string
   273  		}
   274  		var s *S
   275  		err := gconv.Scan(g.Map{
   276  			"Array": `["a", "b"]`,
   277  		}, &s)
   278  		t.AssertNil(err)
   279  		t.Assert(len(s.Array), 2)
   280  		t.Assert(s.Array[0], "a")
   281  		t.Assert(s.Array[1], "b")
   282  	})
   283  
   284  	gtest.C(t, func(t *gtest.T) {
   285  		type S struct {
   286  			Array []string
   287  		}
   288  		var s *S
   289  		err := gconv.Scan(g.Map{
   290  			"Array": `[]`,
   291  		}, &s)
   292  		t.AssertNil(err)
   293  		t.Assert(len(s.Array), 0)
   294  	})
   295  
   296  	gtest.C(t, func(t *gtest.T) {
   297  		type S struct {
   298  			Array []int64
   299  		}
   300  		var s *S
   301  		err := gconv.Scan(g.Map{
   302  			"Array": `[]`,
   303  		}, &s)
   304  		t.AssertNil(err)
   305  		t.Assert(len(s.Array), 0)
   306  	})
   307  }
   308  
   309  func Test_Scan_SameType_Just_Assign(t *testing.T) {
   310  	// Struct.
   311  	gtest.C(t, func(t *gtest.T) {
   312  		type User struct {
   313  			Uid     int
   314  			Name    string
   315  			Pass1   string
   316  			Pass2   string
   317  			Pointer *int
   318  		}
   319  		var (
   320  			int1  = 1
   321  			int2  = 1
   322  			user1 = new(User)
   323  			user2 *User
   324  		)
   325  		user1.Pointer = &int1
   326  		err := gconv.Scan(user1, &user2)
   327  		t.AssertNil(err)
   328  		t.Assert(fmt.Sprintf(`%p`, user1), fmt.Sprintf(`%p`, user2))
   329  		t.Assert(*user1.Pointer, *user2.Pointer)
   330  		user1.Pointer = &int2
   331  		t.Assert(*user1.Pointer, *user2.Pointer)
   332  	})
   333  	// Map.
   334  	gtest.C(t, func(t *gtest.T) {
   335  		var (
   336  			int1 = 1
   337  			int2 = 1
   338  			m1   = map[string]*int{
   339  				"int": &int1,
   340  			}
   341  			m2 map[string]*int
   342  		)
   343  		err := gconv.Scan(m1, &m2)
   344  		t.AssertNil(err)
   345  		t.Assert(fmt.Sprintf(`%p`, m1), fmt.Sprintf(`%p`, m2))
   346  		t.Assert(*m1["int"], *m2["int"])
   347  		m1["int"] = &int2
   348  		t.Assert(*m1["int"], *m2["int"])
   349  	})
   350  }
   351  
   352  func Test_ScanList_Basic(t *testing.T) {
   353  	// Struct attribute.
   354  	gtest.C(t, func(t *gtest.T) {
   355  		type EntityUser struct {
   356  			Uid  int
   357  			Name string
   358  		}
   359  
   360  		type EntityUserDetail struct {
   361  			Uid     int
   362  			Address string
   363  		}
   364  
   365  		type EntityUserScores struct {
   366  			Id    int
   367  			Uid   int
   368  			Score int
   369  		}
   370  
   371  		type Entity struct {
   372  			User       EntityUser
   373  			UserDetail EntityUserDetail
   374  			UserScores []EntityUserScores
   375  		}
   376  
   377  		var (
   378  			err         error
   379  			entities    []Entity
   380  			entityUsers = []EntityUser{
   381  				{Uid: 1, Name: "name1"},
   382  				{Uid: 2, Name: "name2"},
   383  				{Uid: 3, Name: "name3"},
   384  			}
   385  			userDetails = []EntityUserDetail{
   386  				{Uid: 1, Address: "address1"},
   387  				{Uid: 2, Address: "address2"},
   388  			}
   389  			userScores = []EntityUserScores{
   390  				{Id: 10, Uid: 1, Score: 100},
   391  				{Id: 11, Uid: 1, Score: 60},
   392  				{Id: 20, Uid: 2, Score: 99},
   393  			}
   394  		)
   395  		err = gconv.ScanList(entityUsers, &entities, "User")
   396  		t.AssertNil(err)
   397  
   398  		err = gconv.ScanList(userDetails, &entities, "UserDetail", "User", "uid")
   399  		t.AssertNil(err)
   400  
   401  		err = gconv.ScanList(userScores, &entities, "UserScores", "User", "uid")
   402  		t.AssertNil(err)
   403  
   404  		t.Assert(len(entities), 3)
   405  		t.Assert(entities[0].User, entityUsers[0])
   406  		t.Assert(entities[1].User, entityUsers[1])
   407  		t.Assert(entities[2].User, entityUsers[2])
   408  
   409  		t.Assert(entities[0].UserDetail, userDetails[0])
   410  		t.Assert(entities[1].UserDetail, userDetails[1])
   411  		t.Assert(entities[2].UserDetail, EntityUserDetail{})
   412  
   413  		t.Assert(len(entities[0].UserScores), 2)
   414  		t.Assert(entities[0].UserScores[0], userScores[0])
   415  		t.Assert(entities[0].UserScores[1], userScores[1])
   416  
   417  		t.Assert(len(entities[1].UserScores), 1)
   418  		t.Assert(entities[1].UserScores[0], userScores[2])
   419  
   420  		t.Assert(len(entities[2].UserScores), 0)
   421  	})
   422  	// Pointer attribute.
   423  	gtest.C(t, func(t *gtest.T) {
   424  		type EntityUser struct {
   425  			Uid  int
   426  			Name string
   427  		}
   428  
   429  		type EntityUserDetail struct {
   430  			Uid     int
   431  			Address string
   432  		}
   433  
   434  		type EntityUserScores struct {
   435  			Id    int
   436  			Uid   int
   437  			Score int
   438  		}
   439  
   440  		type Entity struct {
   441  			User       *EntityUser
   442  			UserDetail *EntityUserDetail
   443  			UserScores []*EntityUserScores
   444  		}
   445  
   446  		var (
   447  			err         error
   448  			entities    []*Entity
   449  			entityUsers = []*EntityUser{
   450  				{Uid: 1, Name: "name1"},
   451  				{Uid: 2, Name: "name2"},
   452  				{Uid: 3, Name: "name3"},
   453  			}
   454  			userDetails = []*EntityUserDetail{
   455  				{Uid: 1, Address: "address1"},
   456  				{Uid: 2, Address: "address2"},
   457  			}
   458  			userScores = []*EntityUserScores{
   459  				{Id: 10, Uid: 1, Score: 100},
   460  				{Id: 11, Uid: 1, Score: 60},
   461  				{Id: 20, Uid: 2, Score: 99},
   462  			}
   463  		)
   464  		err = gconv.ScanList(entityUsers, &entities, "User")
   465  		t.AssertNil(err)
   466  
   467  		err = gconv.ScanList(userDetails, &entities, "UserDetail", "User", "uid")
   468  		t.AssertNil(err)
   469  
   470  		err = gconv.ScanList(userScores, &entities, "UserScores", "User", "uid")
   471  		t.AssertNil(err)
   472  
   473  		t.Assert(len(entities), 3)
   474  		t.Assert(entities[0].User, entityUsers[0])
   475  		t.Assert(entities[1].User, entityUsers[1])
   476  		t.Assert(entities[2].User, entityUsers[2])
   477  
   478  		t.Assert(entities[0].UserDetail, userDetails[0])
   479  		t.Assert(entities[1].UserDetail, userDetails[1])
   480  		t.Assert(entities[2].UserDetail, nil)
   481  
   482  		t.Assert(len(entities[0].UserScores), 2)
   483  		t.Assert(entities[0].UserScores[0], userScores[0])
   484  		t.Assert(entities[0].UserScores[1], userScores[1])
   485  
   486  		t.Assert(len(entities[1].UserScores), 1)
   487  		t.Assert(entities[1].UserScores[0], userScores[2])
   488  
   489  		t.Assert(len(entities[2].UserScores), 0)
   490  	})
   491  }
   492  
   493  func Test_ScanList_Embedded(t *testing.T) {
   494  	// Struct attribute.
   495  	gtest.C(t, func(t *gtest.T) {
   496  		type EntityUser struct {
   497  			Uid  int
   498  			Name string
   499  		}
   500  
   501  		type EntityUserDetail struct {
   502  			Uid     int
   503  			Address string
   504  		}
   505  
   506  		type EntityUserScores struct {
   507  			Id    int
   508  			Uid   int
   509  			Score int
   510  		}
   511  
   512  		type Entity struct {
   513  			EntityUser
   514  			UserDetail EntityUserDetail
   515  			UserScores []EntityUserScores
   516  		}
   517  
   518  		var (
   519  			err         error
   520  			entities    []Entity
   521  			entityUsers = []EntityUser{
   522  				{Uid: 1, Name: "name1"},
   523  				{Uid: 2, Name: "name2"},
   524  				{Uid: 3, Name: "name3"},
   525  			}
   526  			userDetails = []EntityUserDetail{
   527  				{Uid: 1, Address: "address1"},
   528  				{Uid: 2, Address: "address2"},
   529  			}
   530  			userScores = []EntityUserScores{
   531  				{Id: 10, Uid: 1, Score: 100},
   532  				{Id: 11, Uid: 1, Score: 60},
   533  				{Id: 20, Uid: 2, Score: 99},
   534  			}
   535  		)
   536  		err = gconv.Scan(entityUsers, &entities)
   537  		t.AssertNil(err)
   538  
   539  		err = gconv.ScanList(userDetails, &entities, "UserDetail", "uid")
   540  		t.AssertNil(err)
   541  
   542  		err = gconv.ScanList(userScores, &entities, "UserScores", "uid")
   543  		t.AssertNil(err)
   544  
   545  		t.Assert(len(entities), 3)
   546  		t.Assert(entities[0].EntityUser, entityUsers[0])
   547  		t.Assert(entities[1].EntityUser, entityUsers[1])
   548  		t.Assert(entities[2].EntityUser, entityUsers[2])
   549  
   550  		t.Assert(entities[0].UserDetail, userDetails[0])
   551  		t.Assert(entities[1].UserDetail, userDetails[1])
   552  		t.Assert(entities[2].UserDetail, EntityUserDetail{})
   553  
   554  		t.Assert(len(entities[0].UserScores), 2)
   555  		t.Assert(entities[0].UserScores[0], userScores[0])
   556  		t.Assert(entities[0].UserScores[1], userScores[1])
   557  
   558  		t.Assert(len(entities[1].UserScores), 1)
   559  		t.Assert(entities[1].UserScores[0], userScores[2])
   560  
   561  		t.Assert(len(entities[2].UserScores), 0)
   562  	})
   563  	// Pointer attribute.
   564  	gtest.C(t, func(t *gtest.T) {
   565  		type EntityUser struct {
   566  			Uid  int
   567  			Name string
   568  		}
   569  
   570  		type EntityUserDetail struct {
   571  			Uid     int
   572  			Address string
   573  		}
   574  
   575  		type EntityUserScores struct {
   576  			Id    int
   577  			Uid   int
   578  			Score int
   579  		}
   580  
   581  		type Entity struct {
   582  			*EntityUser
   583  			UserDetail *EntityUserDetail
   584  			UserScores []*EntityUserScores
   585  		}
   586  
   587  		var (
   588  			err         error
   589  			entities    []Entity
   590  			entityUsers = []EntityUser{
   591  				{Uid: 1, Name: "name1"},
   592  				{Uid: 2, Name: "name2"},
   593  				{Uid: 3, Name: "name3"},
   594  			}
   595  			userDetails = []EntityUserDetail{
   596  				{Uid: 1, Address: "address1"},
   597  				{Uid: 2, Address: "address2"},
   598  			}
   599  			userScores = []EntityUserScores{
   600  				{Id: 10, Uid: 1, Score: 100},
   601  				{Id: 11, Uid: 1, Score: 60},
   602  				{Id: 20, Uid: 2, Score: 99},
   603  			}
   604  		)
   605  		err = gconv.Scan(entityUsers, &entities)
   606  		t.AssertNil(err)
   607  
   608  		err = gconv.ScanList(userDetails, &entities, "UserDetail", "uid")
   609  		t.AssertNil(err)
   610  
   611  		err = gconv.ScanList(userScores, &entities, "UserScores", "uid")
   612  		t.AssertNil(err)
   613  
   614  		t.Assert(len(entities), 3)
   615  		t.Assert(entities[0].EntityUser, entityUsers[0])
   616  		t.Assert(entities[1].EntityUser, entityUsers[1])
   617  		t.Assert(entities[2].EntityUser, entityUsers[2])
   618  
   619  		t.Assert(entities[0].UserDetail, userDetails[0])
   620  		t.Assert(entities[1].UserDetail, userDetails[1])
   621  		t.Assert(entities[2].UserDetail, nil)
   622  
   623  		t.Assert(len(entities[0].UserScores), 2)
   624  		t.Assert(entities[0].UserScores[0], userScores[0])
   625  		t.Assert(entities[0].UserScores[1], userScores[1])
   626  
   627  		t.Assert(len(entities[1].UserScores), 1)
   628  		t.Assert(entities[1].UserScores[0], userScores[2])
   629  
   630  		t.Assert(len(entities[2].UserScores), 0)
   631  	})
   632  }
   633  
   634  type Float64 float64
   635  
   636  func (f *Float64) UnmarshalValue(value interface{}) error {
   637  	if v, ok := value.(*big.Rat); ok {
   638  		f64, _ := v.Float64()
   639  		*f = Float64(f64)
   640  	}
   641  	return nil
   642  }
   643  
   644  func Test_Scan_AutoCreatingPointerElem(t *testing.T) {
   645  	type A struct {
   646  		Name string
   647  	}
   648  	gtest.C(t, func(t *gtest.T) {
   649  		var dst A
   650  		var src = A{
   651  			Name: "john",
   652  		}
   653  		err := gconv.Scan(src, &dst)
   654  		t.AssertNil(err)
   655  		t.Assert(src, dst)
   656  	})
   657  	gtest.C(t, func(t *gtest.T) {
   658  		var dst = &A{
   659  			Name: "smith",
   660  		}
   661  		var src = A{
   662  			Name: "john",
   663  		}
   664  		err := gconv.Scan(src, &dst)
   665  		t.AssertNil(err)
   666  		t.Assert(src, dst)
   667  	})
   668  	gtest.C(t, func(t *gtest.T) {
   669  		var dst = A{
   670  			Name: "smith",
   671  		}
   672  		var src = &A{
   673  			Name: "john",
   674  		}
   675  		err := gconv.Scan(src, &dst)
   676  		t.AssertNil(err)
   677  		t.Assert(src, dst)
   678  	})
   679  	gtest.C(t, func(t *gtest.T) {
   680  		var dst *A
   681  		var src = &A{
   682  			Name: "john",
   683  		}
   684  		err := gconv.Scan(src, &dst)
   685  		t.AssertNil(err)
   686  		t.Assert(src, dst)
   687  
   688  		// Note that the dst points to src.
   689  		src.Name = "smith"
   690  		t.Assert(src, dst)
   691  	})
   692  }