mirror of
https://github.com/gogf/gf.git
synced 2025-04-05 03:05:05 +08:00
424 lines
12 KiB
Go
424 lines
12 KiB
Go
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package gconv_test
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/gogf/gf/v2/container/gvar"
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
"github.com/gogf/gf/v2/os/gtime"
|
|
"github.com/gogf/gf/v2/test/gtest"
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
)
|
|
|
|
type scanStructTest struct {
|
|
Name string
|
|
Place string
|
|
}
|
|
|
|
type scanExpectTest struct {
|
|
mapStrStr map[string]string
|
|
mapStrAny map[string]interface{}
|
|
mapAnyAny map[interface{}]interface{}
|
|
|
|
structSub scanStructTest
|
|
structSubPtr *scanStructTest
|
|
}
|
|
|
|
var scanValueMapsTest = []map[string]interface{}{
|
|
{"Name": false, "Place": true},
|
|
{"Name": int(0), "Place": int(1)},
|
|
{"Name": int8(0), "Place": int8(1)},
|
|
{"Name": int16(0), "Place": int16(1)},
|
|
{"Name": int32(0), "Place": int32(1)},
|
|
{"Name": int64(0), "Place": int64(1)},
|
|
{"Name": uint(0), "Place": uint(1)},
|
|
{"Name": uint8(0), "Place": uint8(1)},
|
|
{"Name": uint16(0), "Place": uint16(1)},
|
|
{"Name": uint32(0), "Place": uint32(1)},
|
|
{"Name": uint64(0), "Place": uint64(1)},
|
|
{"Name": float32(0), "Place": float32(1)},
|
|
{"Name": float64(0), "Place": float64(1)},
|
|
{"Name": "Mercury", "Place": "卡罗利斯盆地"},
|
|
{"Name": []byte("Saturn"), "Place": []byte("土星环")},
|
|
{"Name": complex64(0), "Place": complex64(1 + 2i)},
|
|
{"Name": complex128(0), "Place": complex128(1 + 2i)},
|
|
{"Name": interface{}(0), "Place": interface{}("1")},
|
|
{"Name": gvar.New("Jupiter"), "Place": gvar.New("大红斑")},
|
|
{"Name": gtime.New("2024-01-01 01:01:01"), "Place": gtime.New("2021-01-01 01:01:01")},
|
|
{"Name": map[string]string{"Name": "Sun"}, "Place": map[string]string{"Place": "太阳黑子"}},
|
|
{"Name": []string{"Earth", "Moon"}, "Place": []string{"好望角", "万户环形山"}},
|
|
}
|
|
|
|
var scanValueStructsTest = []scanStructTest{
|
|
{"Venus", "阿佛洛狄特高原"},
|
|
}
|
|
|
|
var scanValueJsonTest = []string{
|
|
`{"Name": "Mars", "Place": "奥林帕斯山"}`,
|
|
}
|
|
|
|
var scanExpects = scanExpectTest{
|
|
mapStrStr: make(map[string]string),
|
|
mapStrAny: make(map[string]interface{}),
|
|
mapAnyAny: make(map[interface{}]interface{}),
|
|
|
|
structSub: scanStructTest{},
|
|
structSubPtr: &scanStructTest{},
|
|
}
|
|
|
|
func TestScan(t *testing.T) {
|
|
// Test for map converting.
|
|
gtest.C(t, func(t *gtest.T) {
|
|
scanValuesTest := scanValueMapsTest
|
|
for _, test := range scanValuesTest {
|
|
var (
|
|
err error
|
|
scanExpects = scanExpects
|
|
)
|
|
|
|
err = gconv.Scan(test, &scanExpects.mapStrStr)
|
|
t.AssertNil(err)
|
|
t.Assert(test["Name"], scanExpects.mapStrStr["Name"])
|
|
t.Assert(test["Place"], scanExpects.mapStrStr["Place"])
|
|
|
|
err = gconv.Scan(test, &scanExpects.mapStrAny)
|
|
t.AssertNil(err)
|
|
t.Assert(test["Name"], scanExpects.mapStrAny["Name"])
|
|
t.Assert(test["Place"], scanExpects.mapStrAny["Place"])
|
|
|
|
err = gconv.Scan(test, &scanExpects.mapAnyAny)
|
|
t.AssertNil(err)
|
|
t.Assert(test["Name"], scanExpects.mapAnyAny["Name"])
|
|
t.Assert(test["Place"], scanExpects.mapAnyAny["Place"])
|
|
|
|
err = gconv.Scan(test, &scanExpects.structSub)
|
|
t.AssertNil(err)
|
|
t.Assert(test["Name"], scanExpects.structSub.Name)
|
|
t.Assert(test["Place"], scanExpects.structSub.Place)
|
|
|
|
err = gconv.Scan(test, &scanExpects.structSubPtr)
|
|
t.AssertNil(err)
|
|
t.Assert(test["Name"], scanExpects.structSubPtr.Name)
|
|
t.Assert(test["Place"], scanExpects.structSubPtr.Place)
|
|
|
|
}
|
|
})
|
|
|
|
// Test for slice map converting.
|
|
gtest.C(t, func(t *gtest.T) {
|
|
scanValuesTest := scanValueMapsTest
|
|
for _, test := range scanValuesTest {
|
|
var (
|
|
err error
|
|
scanExpects = scanExpects
|
|
maps = []map[string]interface{}{test, test}
|
|
)
|
|
|
|
var mss = []map[string]string{scanExpects.mapStrStr, scanExpects.mapStrStr}
|
|
err = gconv.Scan(maps, &mss)
|
|
t.AssertNil(err)
|
|
t.Assert(len(mss), len(maps))
|
|
for k := range maps {
|
|
t.Assert(maps[k]["Name"], mss[k]["Name"])
|
|
t.Assert(maps[k]["Place"], mss[k]["Place"])
|
|
}
|
|
|
|
var msa = []map[string]interface{}{scanExpects.mapStrAny, scanExpects.mapStrAny}
|
|
err = gconv.Scan(maps, &msa)
|
|
t.AssertNil(err)
|
|
t.Assert(len(msa), len(maps))
|
|
for k := range maps {
|
|
t.Assert(maps[k]["Name"], msa[k]["Name"])
|
|
t.Assert(maps[k]["Place"], msa[k]["Place"])
|
|
}
|
|
|
|
var maa = []map[interface{}]interface{}{scanExpects.mapAnyAny, scanExpects.mapAnyAny}
|
|
err = gconv.Scan(maps, &maa)
|
|
t.AssertNil(err)
|
|
t.Assert(len(maa), len(maps))
|
|
for k := range maps {
|
|
t.Assert(maps[k]["Name"], maa[k]["Name"])
|
|
t.Assert(maps[k]["Place"], maa[k]["Place"])
|
|
}
|
|
|
|
var ss = []scanStructTest{scanExpects.structSub, scanExpects.structSub}
|
|
err = gconv.Scan(maps, &ss)
|
|
t.AssertNil(err)
|
|
t.Assert(len(ss), len(maps))
|
|
for k := range maps {
|
|
t.Assert(maps[k]["Name"], ss[k].Name)
|
|
t.Assert(maps[k]["Place"], ss[k].Place)
|
|
}
|
|
|
|
var ssp = []*scanStructTest{scanExpects.structSubPtr, scanExpects.structSubPtr}
|
|
err = gconv.Scan(maps, &ssp)
|
|
t.AssertNil(err)
|
|
t.Assert(len(ssp), len(maps))
|
|
for k := range maps {
|
|
t.Assert(maps[k]["Name"], ssp[k].Name)
|
|
t.Assert(maps[k]["Place"], ssp[k].Place)
|
|
}
|
|
}
|
|
})
|
|
|
|
// Test for struct converting.
|
|
gtest.C(t, func(t *gtest.T) {
|
|
scanValuesTest := scanValueStructsTest
|
|
for _, test := range scanValuesTest {
|
|
var (
|
|
err error
|
|
scanExpects = scanExpects
|
|
)
|
|
|
|
err = gconv.Scan(test, &scanExpects.mapStrStr)
|
|
t.AssertNil(err)
|
|
t.Assert(test.Name, scanExpects.mapStrStr["Name"])
|
|
t.Assert(test.Place, scanExpects.mapStrStr["Place"])
|
|
|
|
err = gconv.Scan(test, &scanExpects.mapStrAny)
|
|
t.AssertNil(err)
|
|
t.Assert(test.Name, scanExpects.mapStrAny["Name"])
|
|
t.Assert(test.Place, scanExpects.mapStrAny["Place"])
|
|
|
|
err = gconv.Scan(test, &scanExpects.mapAnyAny)
|
|
t.AssertNil(err)
|
|
t.Assert(test.Name, scanExpects.mapAnyAny["Name"])
|
|
t.Assert(test.Place, scanExpects.mapAnyAny["Place"])
|
|
|
|
err = gconv.Scan(test, &scanExpects.structSub)
|
|
t.AssertNil(err)
|
|
t.Assert(test.Name, scanExpects.structSub.Name)
|
|
t.Assert(test.Place, scanExpects.structSub.Place)
|
|
|
|
err = gconv.Scan(test, &scanExpects.structSubPtr)
|
|
t.AssertNil(err)
|
|
t.Assert(test.Name, scanExpects.structSubPtr.Name)
|
|
t.Assert(test.Place, scanExpects.structSubPtr.Place)
|
|
}
|
|
})
|
|
|
|
// Test for slice struct converting.
|
|
gtest.C(t, func(t *gtest.T) {
|
|
scanValuesTest := scanValueStructsTest
|
|
for _, test := range scanValuesTest {
|
|
var (
|
|
err error
|
|
scanExpects = scanExpects
|
|
structs = []scanStructTest{test, test}
|
|
)
|
|
|
|
var mss = []map[string]string{scanExpects.mapStrStr, scanExpects.mapStrStr}
|
|
err = gconv.Scan(structs, &mss)
|
|
t.AssertNil(err)
|
|
t.Assert(len(mss), len(structs))
|
|
for k := range structs {
|
|
t.Assert(structs[k].Name, mss[k]["Name"])
|
|
t.Assert(structs[k].Place, mss[k]["Place"])
|
|
}
|
|
|
|
var msa = []map[string]interface{}{scanExpects.mapStrAny, scanExpects.mapStrAny}
|
|
err = gconv.Scan(structs, &msa)
|
|
t.AssertNil(err)
|
|
t.Assert(len(msa), len(structs))
|
|
for k := range structs {
|
|
t.Assert(structs[k].Name, msa[k]["Name"])
|
|
t.Assert(structs[k].Place, msa[k]["Place"])
|
|
}
|
|
|
|
var maa = []map[interface{}]interface{}{scanExpects.mapAnyAny, scanExpects.mapAnyAny}
|
|
err = gconv.Scan(structs, &maa)
|
|
t.AssertNil(err)
|
|
t.Assert(len(maa), len(structs))
|
|
for k := range structs {
|
|
t.Assert(structs[k].Name, maa[k]["Name"])
|
|
t.Assert(structs[k].Place, maa[k]["Place"])
|
|
}
|
|
|
|
var ss = []scanStructTest{scanExpects.structSub, scanExpects.structSub}
|
|
err = gconv.Scan(structs, &ss)
|
|
t.AssertNil(err)
|
|
t.Assert(len(ss), len(structs))
|
|
for k := range structs {
|
|
t.Assert(structs[k].Name, ss[k].Name)
|
|
t.Assert(structs[k].Place, ss[k].Place)
|
|
}
|
|
|
|
var ssp = []*scanStructTest{scanExpects.structSubPtr, scanExpects.structSubPtr}
|
|
err = gconv.Scan(structs, &ssp)
|
|
t.AssertNil(err)
|
|
t.Assert(len(ssp), len(structs))
|
|
for k := range structs {
|
|
t.Assert(structs[k].Name, ssp[k].Name)
|
|
t.Assert(structs[k].Place, ssp[k].Place)
|
|
}
|
|
}
|
|
})
|
|
|
|
// Test for json converting.
|
|
gtest.C(t, func(t *gtest.T) {
|
|
scanValuesTest := scanValueJsonTest
|
|
for _, test := range scanValuesTest {
|
|
var (
|
|
err error
|
|
scanExpects = scanExpects
|
|
)
|
|
|
|
err = gconv.Scan(test, &scanExpects.mapStrStr)
|
|
t.AssertNil(err)
|
|
t.Assert("Mars", scanExpects.mapStrStr["Name"])
|
|
t.Assert("奥林帕斯山", scanExpects.mapStrStr["Place"])
|
|
|
|
err = gconv.Scan(test, &scanExpects.mapStrAny)
|
|
t.AssertNil(err)
|
|
t.Assert("Mars", scanExpects.mapStrAny["Name"])
|
|
t.Assert("奥林帕斯山", scanExpects.mapStrAny["Place"])
|
|
|
|
err = gconv.Scan(test, &scanExpects.mapAnyAny)
|
|
t.Assert(err, gerror.New(
|
|
"json.UnmarshalUseNumber failed: json: cannot unmarshal object into Go value of type map[interface {}]interface {}",
|
|
))
|
|
|
|
err = gconv.Scan(test, &scanExpects.structSub)
|
|
t.AssertNil(err)
|
|
t.Assert("Mars", scanExpects.structSub.Name)
|
|
t.Assert("奥林帕斯山", scanExpects.structSub.Place)
|
|
|
|
err = gconv.Scan(test, &scanExpects.structSubPtr)
|
|
t.AssertNil(err)
|
|
t.Assert("Mars", scanExpects.structSubPtr.Name)
|
|
t.Assert("奥林帕斯山", scanExpects.structSubPtr.Place)
|
|
}
|
|
})
|
|
|
|
// Test for slice json converting.
|
|
gtest.C(t, func(t *gtest.T) {
|
|
scanValuesTest := scanValueJsonTest
|
|
for _, test := range scanValuesTest {
|
|
var (
|
|
err error
|
|
scanExpects = scanExpects
|
|
jsons = fmt.Sprintf("[%s, %s]", test, test)
|
|
)
|
|
|
|
var mss = []map[string]string{scanExpects.mapStrStr, scanExpects.mapStrStr}
|
|
err = gconv.Scan(jsons, &mss)
|
|
t.AssertNil(err)
|
|
t.Assert(len(mss), 2)
|
|
for k := range mss {
|
|
t.Assert("Mars", mss[k]["Name"])
|
|
t.Assert("奥林帕斯山", mss[k]["Place"])
|
|
}
|
|
|
|
var msa = []map[string]interface{}{scanExpects.mapStrAny, scanExpects.mapStrAny}
|
|
err = gconv.Scan(jsons, &msa)
|
|
t.AssertNil(err)
|
|
t.Assert(len(msa), 2)
|
|
for k := range msa {
|
|
t.Assert("Mars", msa[k]["Name"])
|
|
t.Assert("奥林帕斯山", msa[k]["Place"])
|
|
}
|
|
|
|
var maa = []map[interface{}]interface{}{scanExpects.mapAnyAny, scanExpects.mapAnyAny}
|
|
err = gconv.Scan(jsons, &maa)
|
|
t.Assert(err, gerror.New(
|
|
"json.UnmarshalUseNumber failed: json: cannot unmarshal object into Go value of type map[interface {}]interface {}",
|
|
))
|
|
|
|
var ss = []scanStructTest{scanExpects.structSub, scanExpects.structSub}
|
|
err = gconv.Scan(jsons, &ss)
|
|
t.AssertNil(err)
|
|
t.Assert(len(ss), 2)
|
|
for k := range ss {
|
|
t.Assert("Mars", ss[k].Name)
|
|
t.Assert("奥林帕斯山", ss[k].Place)
|
|
}
|
|
|
|
var ssp = []*scanStructTest{scanExpects.structSubPtr, scanExpects.structSubPtr}
|
|
err = gconv.Scan(jsons, &ssp)
|
|
t.AssertNil(err)
|
|
t.Assert(len(ssp), 2)
|
|
for k := range ssp {
|
|
t.Assert("Mars", ssp[k].Name)
|
|
t.Assert("奥林帕斯山", ssp[k].Place)
|
|
}
|
|
}
|
|
})
|
|
|
|
// Test for paramKeyToAttrMap
|
|
gtest.C(t, func(t *gtest.T) {
|
|
scanValuesTest := scanValueMapsTest
|
|
for _, test := range scanValuesTest {
|
|
var (
|
|
err error
|
|
scanExpects = scanExpects
|
|
mapParameter = map[string]string{"Name": "Place", "Place": "Name"}
|
|
)
|
|
|
|
err = gconv.Scan(test, &scanExpects.structSub, mapParameter)
|
|
t.AssertNil(err)
|
|
t.Assert(test["Name"], scanExpects.structSub.Place)
|
|
t.Assert(test["Place"], scanExpects.structSub.Name)
|
|
|
|
//t.Logf("%#v", test)
|
|
err = gconv.Scan(test, &scanExpects.structSubPtr, mapParameter)
|
|
t.AssertNil(err)
|
|
//t.Logf("%#v", scanExpects.structSubPtr)
|
|
t.Assert(test["Name"], scanExpects.structSubPtr.Place)
|
|
t.Assert(test["Place"], scanExpects.structSubPtr.Name)
|
|
}
|
|
})
|
|
|
|
// Test for special types.
|
|
gtest.C(t, func(t *gtest.T) {
|
|
var (
|
|
err error
|
|
src = "Sun"
|
|
dst = "日冕"
|
|
)
|
|
|
|
err = gconv.Scan(nil, &dst)
|
|
t.AssertNil(err)
|
|
t.Assert(dst, "日冕")
|
|
|
|
err = gconv.Scan(src, nil)
|
|
t.Assert(err, gerror.New("destination pointer should not be nil"))
|
|
|
|
// Test for non-pointer.
|
|
err = gconv.Scan(src, dst)
|
|
t.Assert(err, gerror.New(
|
|
"destination pointer should be type of pointer, but got type: string",
|
|
))
|
|
})
|
|
}
|
|
|
|
func TestScanEmptyStringToCustomType(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Status string
|
|
type Req struct {
|
|
Name string
|
|
Statuses []Status
|
|
Types []string
|
|
}
|
|
var (
|
|
req *Req
|
|
data = g.Map{
|
|
"Name": "john",
|
|
"Statuses": "",
|
|
"Types": "",
|
|
}
|
|
)
|
|
err := gconv.Scan(data, &req)
|
|
t.AssertNil(err)
|
|
t.Assert(len(req.Statuses), 0)
|
|
t.Assert(len(req.Types), 0)
|
|
})
|
|
}
|