mirror of
https://github.com/gogf/gf.git
synced 2025-04-05 11:18:50 +08:00
447 lines
11 KiB
Go
Executable File
447 lines
11 KiB
Go
Executable File
// 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 gvalid_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
"github.com/gogf/gf/v2/test/gtest"
|
|
)
|
|
|
|
func Test_CheckStruct_Recursive_Struct(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Pass struct {
|
|
Pass1 string `v:"required|same:Pass2"`
|
|
Pass2 string `v:"required|same:Pass1"`
|
|
}
|
|
type User struct {
|
|
Id int
|
|
Name string `v:"required"`
|
|
Pass Pass
|
|
}
|
|
user := &User{
|
|
Name: "",
|
|
Pass: Pass{
|
|
Pass1: "1",
|
|
Pass2: "2",
|
|
},
|
|
}
|
|
err := g.Validator().Data(user).Run(ctx)
|
|
t.AssertNE(err, nil)
|
|
t.Assert(err.Maps()["Name"], g.Map{"required": "The Name field is required"})
|
|
t.Assert(err.Maps()["Pass1"], g.Map{"same": "The Pass1 value `1` must be the same as field Pass2 value `2`"})
|
|
t.Assert(err.Maps()["Pass2"], g.Map{"same": "The Pass2 value `2` must be the same as field Pass1 value `1`"})
|
|
})
|
|
}
|
|
|
|
func Test_CheckStruct_Recursive_Struct_WithData(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Pass struct {
|
|
Pass1 string `v:"required|same:Pass2"`
|
|
Pass2 string `v:"required|same:Pass1"`
|
|
}
|
|
type User struct {
|
|
Id int
|
|
Name string `v:"required"`
|
|
Pass Pass
|
|
}
|
|
user := &User{}
|
|
data := g.Map{
|
|
"Name": "john",
|
|
"Pass": g.Map{
|
|
"Pass1": 100,
|
|
"Pass2": 200,
|
|
},
|
|
}
|
|
err := g.Validator().Data(user).Assoc(data).Run(ctx)
|
|
t.AssertNE(err, nil)
|
|
t.Assert(err.Maps()["Name"], nil)
|
|
t.Assert(err.Maps()["Pass1"], g.Map{"same": "The Pass1 value `100` must be the same as field Pass2 value `200`"})
|
|
t.Assert(err.Maps()["Pass2"], g.Map{"same": "The Pass2 value `200` must be the same as field Pass1 value `100`"})
|
|
})
|
|
}
|
|
|
|
func Test_CheckStruct_Recursive_SliceStruct(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Pass struct {
|
|
Pass1 string `v:"required|same:Pass2"`
|
|
Pass2 string `v:"required|same:Pass1"`
|
|
}
|
|
type User struct {
|
|
Id int
|
|
Name string `v:"required"`
|
|
Passes []Pass
|
|
}
|
|
user := &User{
|
|
Name: "",
|
|
Passes: []Pass{
|
|
{
|
|
Pass1: "1",
|
|
Pass2: "2",
|
|
},
|
|
{
|
|
Pass1: "3",
|
|
Pass2: "4",
|
|
},
|
|
},
|
|
}
|
|
err := g.Validator().Data(user).Run(ctx)
|
|
g.Dump(err.Items())
|
|
t.AssertNE(err, nil)
|
|
t.Assert(err.Maps()["Name"], g.Map{"required": "The Name field is required"})
|
|
t.Assert(err.Maps()["Pass1"], g.Map{"same": "The Pass1 value `3` must be the same as field Pass2 value `4`"})
|
|
t.Assert(err.Maps()["Pass2"], g.Map{"same": "The Pass2 value `4` must be the same as field Pass1 value `3`"})
|
|
})
|
|
}
|
|
|
|
func Test_CheckStruct_Recursive_SliceStruct_Bail(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Pass struct {
|
|
Pass1 string `v:"required|same:Pass2"`
|
|
Pass2 string `v:"required|same:Pass1"`
|
|
}
|
|
type User struct {
|
|
Id int
|
|
Name string `v:"required"`
|
|
Passes []Pass
|
|
}
|
|
user := &User{
|
|
Name: "",
|
|
Passes: []Pass{
|
|
{
|
|
Pass1: "1",
|
|
Pass2: "2",
|
|
},
|
|
{
|
|
Pass1: "3",
|
|
Pass2: "4",
|
|
},
|
|
},
|
|
}
|
|
err := g.Validator().Bail().Data(user).Run(ctx)
|
|
g.Dump(err.Items())
|
|
t.AssertNE(err, nil)
|
|
t.Assert(err.Maps()["Name"], nil)
|
|
t.Assert(err.Maps()["Pass1"], g.Map{"same": "The Pass1 value `1` must be the same as field Pass2 value `2`"})
|
|
t.Assert(err.Maps()["Pass2"], nil)
|
|
})
|
|
}
|
|
|
|
func Test_CheckStruct_Recursive_SliceStruct_Required(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Pass struct {
|
|
Pass1 string `v:"required|same:Pass2"`
|
|
Pass2 string `v:"required|same:Pass1"`
|
|
}
|
|
type User struct {
|
|
Id int
|
|
Name string `v:"required"`
|
|
Passes []Pass
|
|
}
|
|
user := &User{}
|
|
err := g.Validator().Data(user).Run(ctx)
|
|
g.Dump(err.Items())
|
|
t.AssertNE(err, nil)
|
|
t.Assert(err.Maps()["Name"], g.Map{"required": "The Name field is required"})
|
|
t.Assert(err.Maps()["Pass1"], nil)
|
|
t.Assert(err.Maps()["Pass2"], nil)
|
|
})
|
|
}
|
|
|
|
func Test_CheckStruct_Recursive_MapStruct(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Pass struct {
|
|
Pass1 string `v:"required|same:Pass2"`
|
|
Pass2 string `v:"required|same:Pass1"`
|
|
}
|
|
type User struct {
|
|
Id int
|
|
Name string `v:"required"`
|
|
Passes map[string]Pass
|
|
}
|
|
user := &User{
|
|
Name: "",
|
|
Passes: map[string]Pass{
|
|
"test1": {
|
|
Pass1: "1",
|
|
Pass2: "2",
|
|
},
|
|
"test2": {
|
|
Pass1: "3",
|
|
Pass2: "4",
|
|
},
|
|
},
|
|
}
|
|
err := g.Validator().Data(user).Run(ctx)
|
|
g.Dump(err.Items())
|
|
t.AssertNE(err, nil)
|
|
t.Assert(err.Maps()["Name"], g.Map{"required": "The Name field is required"})
|
|
t.AssertNE(err.Maps()["Pass1"], nil)
|
|
t.AssertNE(err.Maps()["Pass2"], nil)
|
|
})
|
|
}
|
|
|
|
func Test_CheckMap_Recursive_SliceStruct(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Pass struct {
|
|
Pass1 string `v:"required|same:Pass2"`
|
|
Pass2 string `v:"required|same:Pass1"`
|
|
}
|
|
user := g.Map{
|
|
"Name": "",
|
|
"Pass": []Pass{
|
|
{
|
|
Pass1: "1",
|
|
Pass2: "2",
|
|
},
|
|
{
|
|
Pass1: "3",
|
|
Pass2: "4",
|
|
},
|
|
},
|
|
}
|
|
err := g.Validator().Data(user).Run(ctx)
|
|
g.Dump(err.Items())
|
|
t.AssertNE(err, nil)
|
|
t.Assert(err.Maps()["Name"], nil)
|
|
t.Assert(err.Maps()["Pass1"], g.Map{"same": "The Pass1 value `3` must be the same as field Pass2 value `4`"})
|
|
t.Assert(err.Maps()["Pass2"], g.Map{"same": "The Pass2 value `4` must be the same as field Pass1 value `3`"})
|
|
})
|
|
}
|
|
|
|
func Test_CheckStruct_Recursively_SliceAttribute(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Student struct {
|
|
Name string `v:"required#Student Name is required"`
|
|
Age int `v:"required"`
|
|
}
|
|
type Teacher struct {
|
|
Name string `v:"required#Teacher Name is required"`
|
|
Students []Student `v:"required"`
|
|
}
|
|
var (
|
|
teacher = Teacher{}
|
|
data = g.Map{
|
|
"name": "john",
|
|
"students": `[]`,
|
|
}
|
|
)
|
|
err := g.Validator().Assoc(data).Data(teacher).Run(ctx)
|
|
t.Assert(err, `The Students field is required`)
|
|
})
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Student struct {
|
|
Name string `v:"required#Student Name is required"`
|
|
Age int `v:"required"`
|
|
}
|
|
type Teacher struct {
|
|
Name string `v:"required#Teacher Name is required"`
|
|
Students []Student
|
|
}
|
|
var (
|
|
teacher = Teacher{}
|
|
data = g.Map{
|
|
"name": "john",
|
|
}
|
|
)
|
|
err := g.Validator().Assoc(data).Data(teacher).Run(ctx)
|
|
t.Assert(err, ``)
|
|
})
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Student struct {
|
|
Name string `v:"required#Student Name is required"`
|
|
Age int `v:"required"`
|
|
}
|
|
type Teacher struct {
|
|
Name string `v:"required#Teacher Name is required"`
|
|
Students []Student `v:"required"`
|
|
}
|
|
var (
|
|
teacher = Teacher{}
|
|
data = g.Map{
|
|
"name": "john",
|
|
"students": `[{"age":2}, {"name":"jack", "age":4}]`,
|
|
}
|
|
)
|
|
err := g.Validator().Assoc(data).Data(teacher).Run(ctx)
|
|
t.Assert(err, `Student Name is required`)
|
|
})
|
|
|
|
// https://github.com/gogf/gf/issues/1864
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Student struct {
|
|
Name string `v:"required"`
|
|
Age int
|
|
}
|
|
type Teacher struct {
|
|
Name string
|
|
Students []*Student
|
|
}
|
|
var (
|
|
teacher = Teacher{}
|
|
data = g.Map{
|
|
"name": "john",
|
|
"students": `[{"age":2},{"name":"jack", "age":4}]`,
|
|
}
|
|
)
|
|
err := g.Validator().Assoc(data).Data(teacher).Run(ctx)
|
|
t.Assert(err, `The Name field is required`)
|
|
})
|
|
}
|
|
|
|
func Test_CheckStruct_Recursively_SliceAttribute_WithTypeAlias(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type ParamsItemBase struct {
|
|
Component string `v:"required" dc:"组件名称"`
|
|
Params string `v:"required" dc:"配置参数(一般是JSON)"`
|
|
Version uint64 `v:"required" dc:"参数版本"`
|
|
}
|
|
type ParamsItem = ParamsItemBase
|
|
type ParamsModifyReq struct {
|
|
Revision uint64 `v:"required"`
|
|
BizParams []ParamsItem `v:"required"`
|
|
}
|
|
var (
|
|
req = ParamsModifyReq{}
|
|
data = g.Map{
|
|
"Revision": "1",
|
|
"BizParams": `[{}]`,
|
|
}
|
|
)
|
|
err := g.Validator().Assoc(data).Data(req).Run(ctx)
|
|
t.Assert(err, `The Component field is required; The Params field is required; The Version field is required`)
|
|
})
|
|
}
|
|
|
|
func Test_CheckStruct_Recursively_MapAttribute(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Student struct {
|
|
Name string `v:"required#Student Name is required"`
|
|
Age int `v:"required"`
|
|
}
|
|
type Teacher struct {
|
|
Name string `v:"required#Teacher Name is required"`
|
|
Students map[string]Student `v:"required"`
|
|
}
|
|
var (
|
|
teacher = Teacher{}
|
|
data = g.Map{
|
|
"name": "john",
|
|
"students": `{"john":{"age":18}}`,
|
|
}
|
|
)
|
|
err := g.Validator().Assoc(data).Data(teacher).Run(ctx)
|
|
t.Assert(err, `Student Name is required`)
|
|
})
|
|
}
|
|
|
|
// https://github.com/gogf/gf/issues/1983
|
|
func Test_Issue1983(t *testing.T) {
|
|
// Error as the attribute Student in Teacher is an initialized struct, which has default value.
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Student struct {
|
|
Name string `v:"required"`
|
|
Age int
|
|
}
|
|
type Teacher struct {
|
|
Students Student
|
|
}
|
|
var (
|
|
teacher = Teacher{}
|
|
data = g.Map{
|
|
"students": nil,
|
|
}
|
|
)
|
|
err := g.Validator().Assoc(data).Data(teacher).Run(ctx)
|
|
t.Assert(err, `The Name field is required`)
|
|
})
|
|
// The same as upper, it is not affected by association values.
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Student struct {
|
|
Name string `v:"required"`
|
|
Age int
|
|
}
|
|
type Teacher struct {
|
|
Students Student
|
|
}
|
|
var (
|
|
teacher = Teacher{}
|
|
data = g.Map{
|
|
"name": "john",
|
|
"students": nil,
|
|
}
|
|
)
|
|
err := g.Validator().Assoc(data).Data(teacher).Run(ctx)
|
|
t.Assert(err, `The Name field is required`)
|
|
})
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Student struct {
|
|
Name string `v:"required"`
|
|
Age int
|
|
}
|
|
type Teacher struct {
|
|
Students *Student
|
|
}
|
|
var (
|
|
teacher = Teacher{}
|
|
data = g.Map{
|
|
"students": nil,
|
|
}
|
|
)
|
|
err := g.Validator().Assoc(data).Data(teacher).Run(ctx)
|
|
t.AssertNil(err)
|
|
})
|
|
}
|
|
|
|
// https://github.com/gogf/gf/issues/1921
|
|
func Test_Issue1921(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type SearchOption struct {
|
|
Size int `v:"max:100"`
|
|
}
|
|
type SearchReq struct {
|
|
Option *SearchOption `json:"option,omitempty"`
|
|
}
|
|
|
|
var (
|
|
req = SearchReq{
|
|
Option: &SearchOption{
|
|
Size: 10000,
|
|
},
|
|
}
|
|
)
|
|
err := g.Validator().Data(req).Run(ctx)
|
|
t.Assert(err, "The Size value `10000` must be equal or lesser than 100")
|
|
})
|
|
}
|
|
|
|
// https://github.com/gogf/gf/issues/2011
|
|
func Test_Issue2011(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
type Student struct {
|
|
Name string `v:"required|min-length:6"`
|
|
Age int
|
|
}
|
|
type Teacher struct {
|
|
Student *Student
|
|
}
|
|
var (
|
|
teacher = Teacher{}
|
|
data = g.Map{
|
|
"student": g.Map{
|
|
"name": "john",
|
|
},
|
|
}
|
|
)
|
|
err := g.Validator().Assoc(data).Data(teacher).Run(ctx)
|
|
t.Assert(err, "The Name value `john` length must be equal or greater than 6")
|
|
})
|
|
}
|