gf/internal/structs/structs_z_unit_test.go

386 lines
9.5 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 structs_test
import (
"testing"
"github.com/gogf/gf/v2/internal/structs"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/test/gtest"
)
func Test_Basic(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Name string `params:"name"`
Pass string `my-tag1:"pass1" my-tag2:"pass2" params:"pass"`
}
var user User
m, _ := structs.TagMapName(user, []string{"params"})
t.Assert(m, g.Map{"name": "Name", "pass": "Pass"})
m, _ = structs.TagMapName(&user, []string{"params"})
t.Assert(m, g.Map{"name": "Name", "pass": "Pass"})
m, _ = structs.TagMapName(&user, []string{"params", "my-tag1"})
t.Assert(m, g.Map{"name": "Name", "pass": "Pass"})
m, _ = structs.TagMapName(&user, []string{"my-tag1", "params"})
t.Assert(m, g.Map{"name": "Name", "pass1": "Pass"})
m, _ = structs.TagMapName(&user, []string{"my-tag2", "params"})
t.Assert(m, g.Map{"name": "Name", "pass2": "Pass"})
})
gtest.C(t, func(t *gtest.T) {
type Base struct {
Pass1 string `params:"password1"`
Pass2 string `params:"password2"`
}
type UserWithBase struct {
Id int
Name string
Base `params:"base"`
}
user := new(UserWithBase)
m, _ := structs.TagMapName(user, []string{"params"})
t.Assert(m, g.Map{
"base": "Base",
"password1": "Pass1",
"password2": "Pass2",
})
})
gtest.C(t, func(t *gtest.T) {
type Base struct {
Pass1 string `params:"password1"`
Pass2 string `params:"password2"`
}
type UserWithEmbeddedAttribute struct {
Id int
Name string
Base
}
type UserWithoutEmbeddedAttribute struct {
Id int
Name string
Pass Base
}
user1 := new(UserWithEmbeddedAttribute)
user2 := new(UserWithoutEmbeddedAttribute)
m, _ := structs.TagMapName(user1, []string{"params"})
t.Assert(m, g.Map{"password1": "Pass1", "password2": "Pass2"})
m, _ = structs.TagMapName(user2, []string{"params"})
t.Assert(m, g.Map{})
})
}
func Test_StructOfNilPointer(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Name string `params:"name"`
Pass string `my-tag1:"pass1" my-tag2:"pass2" params:"pass"`
}
var user *User
m, _ := structs.TagMapName(user, []string{"params"})
t.Assert(m, g.Map{"name": "Name", "pass": "Pass"})
m, _ = structs.TagMapName(&user, []string{"params"})
t.Assert(m, g.Map{"name": "Name", "pass": "Pass"})
m, _ = structs.TagMapName(&user, []string{"params", "my-tag1"})
t.Assert(m, g.Map{"name": "Name", "pass": "Pass"})
m, _ = structs.TagMapName(&user, []string{"my-tag1", "params"})
t.Assert(m, g.Map{"name": "Name", "pass1": "Pass"})
m, _ = structs.TagMapName(&user, []string{"my-tag2", "params"})
t.Assert(m, g.Map{"name": "Name", "pass2": "Pass"})
})
}
func Test_Fields(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Name string `params:"name"`
Pass string `my-tag1:"pass1" my-tag2:"pass2" params:"pass"`
}
var user *User
fields, _ := structs.Fields(structs.FieldsInput{
Pointer: user,
RecursiveOption: 0,
})
t.Assert(len(fields), 3)
t.Assert(fields[0].Name(), "Id")
t.Assert(fields[1].Name(), "Name")
t.Assert(fields[1].Tag("params"), "name")
t.Assert(fields[2].Name(), "Pass")
t.Assert(fields[2].Tag("my-tag1"), "pass1")
t.Assert(fields[2].Tag("my-tag2"), "pass2")
t.Assert(fields[2].Tag("params"), "pass")
})
}
func Test_Fields_WithEmbedded1(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type B struct {
Name string
Age int
}
type A struct {
Site string
B // Should be put here to validate its index.
Score int64
}
r, err := structs.Fields(structs.FieldsInput{
Pointer: new(A),
RecursiveOption: structs.RecursiveOptionEmbeddedNoTag,
})
t.AssertNil(err)
t.Assert(len(r), 4)
t.Assert(r[0].Name(), `Site`)
t.Assert(r[1].Name(), `Name`)
t.Assert(r[2].Name(), `Age`)
t.Assert(r[3].Name(), `Score`)
})
}
func Test_Fields_WithEmbedded2(t *testing.T) {
type MetaNode struct {
Id uint `orm:"id,primary" description:""`
Capacity string `orm:"capacity" description:"Capacity string"`
Allocatable string `orm:"allocatable" description:"Allocatable string"`
Status string `orm:"status" description:"Status string"`
}
type MetaNodeZone struct {
Nodes uint
Clusters uint
Disk uint
Cpu uint
Memory uint
Zone string
}
type MetaNodeItem struct {
MetaNode
Capacity []MetaNodeZone `dc:"Capacity []MetaNodeZone"`
Allocatable []MetaNodeZone `dc:"Allocatable []MetaNodeZone"`
}
gtest.C(t, func(t *gtest.T) {
r, err := structs.Fields(structs.FieldsInput{
Pointer: new(MetaNodeItem),
RecursiveOption: structs.RecursiveOptionEmbeddedNoTag,
})
t.AssertNil(err)
t.Assert(len(r), 4)
t.Assert(r[0].Name(), `Id`)
t.Assert(r[1].Name(), `Capacity`)
t.Assert(r[1].TagStr(), `dc:"Capacity []MetaNodeZone"`)
t.Assert(r[2].Name(), `Allocatable`)
t.Assert(r[2].TagStr(), `dc:"Allocatable []MetaNodeZone"`)
t.Assert(r[3].Name(), `Status`)
})
}
// Filter repeated fields when there is embedded struct.
func Test_Fields_WithEmbedded_Filter(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type B struct {
Name string
Age int
}
type A struct {
Name string
Site string
Age string
B // Should be put here to validate its index.
Score int64
}
r, err := structs.Fields(structs.FieldsInput{
Pointer: new(A),
RecursiveOption: structs.RecursiveOptionEmbeddedNoTag,
})
t.AssertNil(err)
t.Assert(len(r), 4)
t.Assert(r[0].Name(), `Name`)
t.Assert(r[1].Name(), `Site`)
t.Assert(r[2].Name(), `Age`)
t.Assert(r[3].Name(), `Score`)
})
}
func Test_FieldMap(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Name string `params:"name"`
Pass string `my-tag1:"pass1" my-tag2:"pass2" params:"pass"`
}
var user *User
m, _ := structs.FieldMap(structs.FieldMapInput{
Pointer: user,
PriorityTagArray: []string{"params"},
RecursiveOption: structs.RecursiveOptionEmbedded,
})
t.Assert(len(m), 3)
_, ok := m["Id"]
t.Assert(ok, true)
_, ok = m["Name"]
t.Assert(ok, false)
_, ok = m["name"]
t.Assert(ok, true)
_, ok = m["Pass"]
t.Assert(ok, false)
_, ok = m["pass"]
t.Assert(ok, true)
})
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Name string `params:"name"`
Pass string `my-tag1:"pass1" my-tag2:"pass2" params:"pass"`
}
var user *User
m, _ := structs.FieldMap(structs.FieldMapInput{
Pointer: user,
PriorityTagArray: nil,
RecursiveOption: structs.RecursiveOptionEmbedded,
})
t.Assert(len(m), 3)
_, ok := m["Id"]
t.Assert(ok, true)
_, ok = m["Name"]
t.Assert(ok, true)
_, ok = m["name"]
t.Assert(ok, false)
_, ok = m["Pass"]
t.Assert(ok, true)
_, ok = m["pass"]
t.Assert(ok, false)
})
}
func Test_StructType(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type B struct {
Name string
}
type A struct {
B
}
r, err := structs.StructType(new(A))
t.AssertNil(err)
t.Assert(r.Signature(), `github.com/gogf/gf/v2/internal/structs_test/structs_test.A`)
})
gtest.C(t, func(t *gtest.T) {
type B struct {
Name string
}
type A struct {
B
}
r, err := structs.StructType(new(A).B)
t.AssertNil(err)
t.Assert(r.Signature(), `github.com/gogf/gf/v2/internal/structs_test/structs_test.B`)
})
gtest.C(t, func(t *gtest.T) {
type B struct {
Name string
}
type A struct {
*B
}
r, err := structs.StructType(new(A).B)
t.AssertNil(err)
t.Assert(r.String(), `structs_test.B`)
})
// Error.
gtest.C(t, func(t *gtest.T) {
type B struct {
Name string
}
type A struct {
*B
Id int
}
_, err := structs.StructType(new(A).Id)
t.AssertNE(err, nil)
})
}
func Test_StructTypeBySlice(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type B struct {
Name string
}
type A struct {
Array []*B
}
r, err := structs.StructType(new(A).Array)
t.AssertNil(err)
t.Assert(r.Signature(), `github.com/gogf/gf/v2/internal/structs_test/structs_test.B`)
})
gtest.C(t, func(t *gtest.T) {
type B struct {
Name string
}
type A struct {
Array []B
}
r, err := structs.StructType(new(A).Array)
t.AssertNil(err)
t.Assert(r.Signature(), `github.com/gogf/gf/v2/internal/structs_test/structs_test.B`)
})
gtest.C(t, func(t *gtest.T) {
type B struct {
Name string
}
type A struct {
Array *[]B
}
r, err := structs.StructType(new(A).Array)
t.AssertNil(err)
t.Assert(r.Signature(), `github.com/gogf/gf/v2/internal/structs_test/structs_test.B`)
})
}
func TestType_FieldKeys(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type B struct {
Id int
Name string
}
type A struct {
Array []*B
}
r, err := structs.StructType(new(A).Array)
t.AssertNil(err)
t.Assert(r.FieldKeys(), g.Slice{"Id", "Name"})
})
}
func TestType_TagMap(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type A struct {
Id int `d:"123" description:"I love gf"`
Name string `v:"required" description:"应用Id"`
}
r, err := structs.Fields(structs.FieldsInput{
Pointer: new(A),
RecursiveOption: 0,
})
t.AssertNil(err)
t.Assert(len(r), 2)
t.Assert(r[0].TagMap()["d"], `123`)
t.Assert(r[0].TagMap()["description"], `I love gf`)
t.Assert(r[1].TagMap()["v"], `required`)
t.Assert(r[1].TagMap()["description"], `应用Id`)
})
}