github.com/gogf/gf@v1.16.9/util/gvalid/gvalid_z_unit_checkstruct_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 gvalid_test
     8  
     9  import (
    10  	"context"
    11  	"github.com/gogf/gf/container/gvar"
    12  	"github.com/gogf/gf/os/gtime"
    13  	"testing"
    14  
    15  	"github.com/gogf/gf/frame/g"
    16  
    17  	"github.com/gogf/gf/test/gtest"
    18  	"github.com/gogf/gf/util/gvalid"
    19  )
    20  
    21  func Test_CheckStruct(t *testing.T) {
    22  	gtest.C(t, func(t *gtest.T) {
    23  		type Object struct {
    24  			Name string
    25  			Age  int
    26  		}
    27  		rules := []string{
    28  			"@required|length:6,16",
    29  			"@between:18,30",
    30  		}
    31  		msgs := map[string]interface{}{
    32  			"Name": map[string]string{
    33  				"required": "名称不能为空",
    34  				"length":   "名称长度为:min到:max个字符",
    35  			},
    36  			"Age": "年龄为18到30周岁",
    37  		}
    38  		obj := &Object{"john", 16}
    39  		err := gvalid.CheckStruct(context.TODO(), obj, rules, msgs)
    40  		t.Assert(err, nil)
    41  	})
    42  
    43  	gtest.C(t, func(t *gtest.T) {
    44  		type Object struct {
    45  			Name string
    46  			Age  int
    47  		}
    48  		rules := []string{
    49  			"Name@required|length:6,16#名称不能为空",
    50  			"Age@between:18,30",
    51  		}
    52  		msgs := map[string]interface{}{
    53  			"Name": map[string]string{
    54  				"required": "名称不能为空",
    55  				"length":   "名称长度为:min到:max个字符",
    56  			},
    57  			"Age": "年龄为18到30周岁",
    58  		}
    59  		obj := &Object{"john", 16}
    60  		err := gvalid.CheckStruct(context.TODO(), obj, rules, msgs)
    61  		t.AssertNE(err, nil)
    62  		t.Assert(len(err.Maps()), 2)
    63  		t.Assert(err.Maps()["Name"]["required"], "")
    64  		t.Assert(err.Maps()["Name"]["length"], "名称长度为6到16个字符")
    65  		t.Assert(err.Maps()["Age"]["between"], "年龄为18到30周岁")
    66  	})
    67  
    68  	gtest.C(t, func(t *gtest.T) {
    69  		type Object struct {
    70  			Name string
    71  			Age  int
    72  		}
    73  		rules := []string{
    74  			"Name@required|length:6,16#名称不能为空|",
    75  			"Age@between:18,30",
    76  		}
    77  		msgs := map[string]interface{}{
    78  			"Name": map[string]string{
    79  				"required": "名称不能为空",
    80  				"length":   "名称长度为:min到:max个字符",
    81  			},
    82  			"Age": "年龄为18到30周岁",
    83  		}
    84  		obj := &Object{"john", 16}
    85  		err := gvalid.CheckStruct(context.TODO(), obj, rules, msgs)
    86  		t.AssertNE(err, nil)
    87  		t.Assert(len(err.Maps()), 2)
    88  		t.Assert(err.Maps()["Name"]["required"], "")
    89  		t.Assert(err.Maps()["Name"]["length"], "名称长度为6到16个字符")
    90  		t.Assert(err.Maps()["Age"]["between"], "年龄为18到30周岁")
    91  	})
    92  
    93  	gtest.C(t, func(t *gtest.T) {
    94  		type Object struct {
    95  			Name string
    96  			Age  int
    97  		}
    98  		rules := map[string]string{
    99  			"Name": "required|length:6,16",
   100  			"Age":  "between:18,30",
   101  		}
   102  		msgs := map[string]interface{}{
   103  			"Name": map[string]string{
   104  				"required": "名称不能为空",
   105  				"length":   "名称长度为:min到:max个字符",
   106  			},
   107  			"Age": "年龄为18到30周岁",
   108  		}
   109  		obj := &Object{"john", 16}
   110  		err := gvalid.CheckStruct(context.TODO(), obj, rules, msgs)
   111  		t.AssertNE(err, nil)
   112  		t.Assert(len(err.Maps()), 2)
   113  		t.Assert(err.Maps()["Name"]["required"], "")
   114  		t.Assert(err.Maps()["Name"]["length"], "名称长度为6到16个字符")
   115  		t.Assert(err.Maps()["Age"]["between"], "年龄为18到30周岁")
   116  	})
   117  
   118  	gtest.C(t, func(t *gtest.T) {
   119  		type LoginRequest struct {
   120  			Username string `json:"username" gvalid:"username@required#用户名不能为空"`
   121  			Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
   122  		}
   123  		var login LoginRequest
   124  		err := gvalid.CheckStruct(context.TODO(), login, nil)
   125  		t.AssertNE(err, nil)
   126  		t.Assert(len(err.Maps()), 2)
   127  		t.Assert(err.Maps()["username"]["required"], "用户名不能为空")
   128  		t.Assert(err.Maps()["password"]["required"], "登录密码不能为空")
   129  	})
   130  
   131  	gtest.C(t, func(t *gtest.T) {
   132  		type LoginRequest struct {
   133  			Username string `json:"username" gvalid:"@required#用户名不能为空"`
   134  			Password string `json:"password" gvalid:"@required#登录密码不能为空"`
   135  		}
   136  		var login LoginRequest
   137  		err := gvalid.CheckStruct(context.TODO(), login, nil)
   138  		t.Assert(err, nil)
   139  	})
   140  
   141  	gtest.C(t, func(t *gtest.T) {
   142  		type LoginRequest struct {
   143  			username string `json:"username" gvalid:"username@required#用户名不能为空"`
   144  			Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
   145  		}
   146  		var login LoginRequest
   147  		err := gvalid.CheckStruct(context.TODO(), login, nil)
   148  		t.AssertNE(err, nil)
   149  		t.Assert(err.Maps()["password"]["required"], "登录密码不能为空")
   150  	})
   151  
   152  	// gvalid tag
   153  	gtest.C(t, func(t *gtest.T) {
   154  		type User struct {
   155  			Id       int    `gvalid:"uid@required|min:10#|ID不能为空"`
   156  			Age      int    `gvalid:"age@required#年龄不能为空"`
   157  			Username string `json:"username" gvalid:"username@required#用户名不能为空"`
   158  			Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
   159  		}
   160  		user := &User{
   161  			Id:       1,
   162  			Username: "john",
   163  			Password: "123456",
   164  		}
   165  		err := gvalid.CheckStruct(context.TODO(), user, nil)
   166  		t.AssertNE(err, nil)
   167  		t.Assert(len(err.Maps()), 1)
   168  		t.Assert(err.Maps()["uid"]["min"], "ID不能为空")
   169  	})
   170  
   171  	gtest.C(t, func(t *gtest.T) {
   172  		type User struct {
   173  			Id       int    `gvalid:"uid@required|min:10#|ID不能为空"`
   174  			Age      int    `gvalid:"age@required#年龄不能为空"`
   175  			Username string `json:"username" gvalid:"username@required#用户名不能为空"`
   176  			Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
   177  		}
   178  		user := &User{
   179  			Id:       1,
   180  			Username: "john",
   181  			Password: "123456",
   182  		}
   183  
   184  		rules := []string{
   185  			"username@required#用户名不能为空",
   186  		}
   187  
   188  		err := gvalid.CheckStruct(context.TODO(), user, rules)
   189  		t.AssertNE(err, nil)
   190  		t.Assert(len(err.Maps()), 1)
   191  		t.Assert(err.Maps()["uid"]["min"], "ID不能为空")
   192  	})
   193  
   194  	gtest.C(t, func(t *gtest.T) {
   195  		type User struct {
   196  			Id       int    `gvalid:"uid@required|min:10#ID不能为空"`
   197  			Age      int    `gvalid:"age@required#年龄不能为空"`
   198  			Username string `json:"username" gvalid:"username@required#用户名不能为空"`
   199  			Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
   200  		}
   201  		user := &User{
   202  			Id:       1,
   203  			Username: "john",
   204  			Password: "123456",
   205  		}
   206  		err := gvalid.CheckStruct(context.TODO(), user, nil)
   207  		t.AssertNE(err, nil)
   208  		t.Assert(len(err.Maps()), 1)
   209  	})
   210  
   211  	// valid tag
   212  	gtest.C(t, func(t *gtest.T) {
   213  		type User struct {
   214  			Id       int    `valid:"uid@required|min:10#|ID不能为空"`
   215  			Age      int    `valid:"age@required#年龄不能为空"`
   216  			Username string `json:"username" gvalid:"username@required#用户名不能为空"`
   217  			Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
   218  		}
   219  		user := &User{
   220  			Id:       1,
   221  			Username: "john",
   222  			Password: "123456",
   223  		}
   224  		err := gvalid.CheckStruct(context.TODO(), user, nil)
   225  		t.AssertNE(err, nil)
   226  		t.Assert(len(err.Maps()), 1)
   227  		t.Assert(err.Maps()["uid"]["min"], "ID不能为空")
   228  	})
   229  }
   230  
   231  func Test_CheckStruct_EmbeddedObject_Attribute(t *testing.T) {
   232  	gtest.C(t, func(t *gtest.T) {
   233  		type Base struct {
   234  			Time *gtime.Time
   235  		}
   236  		type Object struct {
   237  			Base
   238  			Name string
   239  			Type int
   240  		}
   241  		rules := map[string]string{
   242  			"Name": "required",
   243  			"Type": "required",
   244  		}
   245  		ruleMsg := map[string]interface{}{
   246  			"Name": "名称必填",
   247  			"Type": "类型必填",
   248  		}
   249  		obj := &Object{}
   250  		obj.Type = 1
   251  		obj.Name = "john"
   252  		obj.Time = gtime.Now()
   253  		err := gvalid.CheckStruct(context.TODO(), obj, rules, ruleMsg)
   254  		t.Assert(err, nil)
   255  	})
   256  	gtest.C(t, func(t *gtest.T) {
   257  		type Base struct {
   258  			Name string
   259  			Type int
   260  		}
   261  		type Object struct {
   262  			Base Base
   263  			Name string
   264  			Type int
   265  		}
   266  		rules := map[string]string{
   267  			"Name": "required",
   268  			"Type": "required",
   269  		}
   270  		ruleMsg := map[string]interface{}{
   271  			"Name": "名称必填",
   272  			"Type": "类型必填",
   273  		}
   274  		obj := &Object{}
   275  		obj.Type = 1
   276  		obj.Name = "john"
   277  		err := gvalid.CheckStruct(context.TODO(), obj, rules, ruleMsg)
   278  		t.Assert(err, nil)
   279  	})
   280  }
   281  
   282  func Test_CheckStruct_With_EmbeddedObject(t *testing.T) {
   283  	gtest.C(t, func(t *gtest.T) {
   284  		type Pass struct {
   285  			Pass1 string `valid:"password1@required|same:password2#请输入您的密码|您两次输入的密码不一致"`
   286  			Pass2 string `valid:"password2@required|same:password1#请再次输入您的密码|您两次输入的密码不一致"`
   287  		}
   288  		type User struct {
   289  			Id   int
   290  			Name string `valid:"name@required#请输入您的姓名"`
   291  			Pass
   292  		}
   293  		user := &User{
   294  			Name: "",
   295  			Pass: Pass{
   296  				Pass1: "1",
   297  				Pass2: "2",
   298  			},
   299  		}
   300  		err := gvalid.CheckStruct(context.TODO(), user, nil)
   301  		t.AssertNE(err, nil)
   302  		t.Assert(err.Maps()["name"], g.Map{"required": "请输入您的姓名"})
   303  		t.Assert(err.Maps()["password1"], g.Map{"same": "您两次输入的密码不一致"})
   304  		t.Assert(err.Maps()["password2"], g.Map{"same": "您两次输入的密码不一致"})
   305  	})
   306  }
   307  
   308  func Test_CheckStruct_With_StructAttribute(t *testing.T) {
   309  	gtest.C(t, func(t *gtest.T) {
   310  		type Pass struct {
   311  			Pass1 string `valid:"password1@required|same:password2#请输入您的密码|您两次输入的密码不一致"`
   312  			Pass2 string `valid:"password2@required|same:password1#请再次输入您的密码|您两次输入的密码不一致"`
   313  		}
   314  		type User struct {
   315  			Pass
   316  			Id   int
   317  			Name string `valid:"name@required#请输入您的姓名"`
   318  		}
   319  		user := &User{
   320  			Name: "",
   321  			Pass: Pass{
   322  				Pass1: "1",
   323  				Pass2: "2",
   324  			},
   325  		}
   326  		err := gvalid.CheckStruct(context.TODO(), user, nil)
   327  		t.AssertNE(err, nil)
   328  		t.Assert(err.Maps()["name"], g.Map{"required": "请输入您的姓名"})
   329  		t.Assert(err.Maps()["password1"], g.Map{"same": "您两次输入的密码不一致"})
   330  		t.Assert(err.Maps()["password2"], g.Map{"same": "您两次输入的密码不一致"})
   331  	})
   332  }
   333  
   334  func Test_CheckStruct_Optional(t *testing.T) {
   335  	gtest.C(t, func(t *gtest.T) {
   336  		type Params struct {
   337  			Page      int    `v:"required|min:1         # page is required"`
   338  			Size      int    `v:"required|between:1,100 # size is required"`
   339  			ProjectId string `v:"between:1,10000        # project id must between :min, :max"`
   340  		}
   341  		obj := &Params{
   342  			Page: 1,
   343  			Size: 10,
   344  		}
   345  		err := gvalid.CheckStruct(context.TODO(), obj, nil)
   346  		t.Assert(err, nil)
   347  	})
   348  	gtest.C(t, func(t *gtest.T) {
   349  		type Params struct {
   350  			Page      int       `v:"required|min:1         # page is required"`
   351  			Size      int       `v:"required|between:1,100 # size is required"`
   352  			ProjectId *gvar.Var `v:"between:1,10000        # project id must between :min, :max"`
   353  		}
   354  		obj := &Params{
   355  			Page: 1,
   356  			Size: 10,
   357  		}
   358  		err := gvalid.CheckStruct(context.TODO(), obj, nil)
   359  		t.Assert(err, nil)
   360  	})
   361  	gtest.C(t, func(t *gtest.T) {
   362  		type Params struct {
   363  			Page      int `v:"required|min:1         # page is required"`
   364  			Size      int `v:"required|between:1,100 # size is required"`
   365  			ProjectId int `v:"between:1,10000        # project id must between :min, :max"`
   366  		}
   367  		obj := &Params{
   368  			Page: 1,
   369  			Size: 10,
   370  		}
   371  		err := gvalid.CheckStruct(context.TODO(), obj, nil)
   372  		t.Assert(err.String(), "project id must between 1, 10000")
   373  	})
   374  }
   375  
   376  func Test_CheckStruct_NoTag(t *testing.T) {
   377  	gtest.C(t, func(t *gtest.T) {
   378  		type Params struct {
   379  			Page      int
   380  			Size      int
   381  			ProjectId string
   382  		}
   383  		obj := &Params{
   384  			Page: 1,
   385  			Size: 10,
   386  		}
   387  		err := gvalid.CheckStruct(context.TODO(), obj, nil)
   388  		t.Assert(err, nil)
   389  	})
   390  }
   391  
   392  func Test_CheckStruct_InvalidRule(t *testing.T) {
   393  	gtest.C(t, func(t *gtest.T) {
   394  		type Params struct {
   395  			Name  string
   396  			Age   uint
   397  			Phone string `v:"mobile"`
   398  		}
   399  		obj := &Params{
   400  			Name:  "john",
   401  			Age:   18,
   402  			Phone: "123",
   403  		}
   404  		err := gvalid.CheckStruct(context.TODO(), obj, nil)
   405  		t.AssertNE(err, nil)
   406  	})
   407  }
   408  
   409  func TestValidator_CheckStructWithData(t *testing.T) {
   410  	gtest.C(t, func(t *gtest.T) {
   411  		type UserApiSearch struct {
   412  			Uid      int64  `v:"required"`
   413  			Nickname string `v:"required-with:uid"`
   414  		}
   415  		data := UserApiSearch{
   416  			Uid:      1,
   417  			Nickname: "john",
   418  		}
   419  		t.Assert(gvalid.CheckStructWithData(context.TODO(), data, g.Map{"uid": 1, "nickname": "john"}, nil), nil)
   420  	})
   421  	gtest.C(t, func(t *gtest.T) {
   422  		type UserApiSearch struct {
   423  			Uid      int64  `v:"required"`
   424  			Nickname string `v:"required-with:uid"`
   425  		}
   426  		data := UserApiSearch{}
   427  		t.AssertNE(gvalid.CheckStructWithData(context.TODO(), data, g.Map{}, nil), nil)
   428  	})
   429  	gtest.C(t, func(t *gtest.T) {
   430  		type UserApiSearch struct {
   431  			Uid      int64  `json:"uid" v:"required"`
   432  			Nickname string `json:"nickname" v:"required-with:Uid"`
   433  		}
   434  		data := UserApiSearch{
   435  			Uid: 1,
   436  		}
   437  		t.AssertNE(gvalid.CheckStructWithData(context.TODO(), data, g.Map{}, nil), nil)
   438  	})
   439  
   440  	gtest.C(t, func(t *gtest.T) {
   441  		type UserApiSearch struct {
   442  			Uid       int64       `json:"uid"`
   443  			Nickname  string      `json:"nickname" v:"required-with:Uid"`
   444  			StartTime *gtime.Time `json:"start_time" v:"required-with:EndTime"`
   445  			EndTime   *gtime.Time `json:"end_time" v:"required-with:StartTime"`
   446  		}
   447  		data := UserApiSearch{
   448  			StartTime: nil,
   449  			EndTime:   nil,
   450  		}
   451  		t.Assert(gvalid.CheckStructWithData(context.TODO(), data, g.Map{}, nil), nil)
   452  	})
   453  	gtest.C(t, func(t *gtest.T) {
   454  		type UserApiSearch struct {
   455  			Uid       int64       `json:"uid"`
   456  			Nickname  string      `json:"nickname" v:"required-with:Uid"`
   457  			StartTime *gtime.Time `json:"start_time" v:"required-with:EndTime"`
   458  			EndTime   *gtime.Time `json:"end_time" v:"required-with:StartTime"`
   459  		}
   460  		data := UserApiSearch{
   461  			StartTime: gtime.Now(),
   462  			EndTime:   nil,
   463  		}
   464  		t.AssertNE(gvalid.CheckStructWithData(context.TODO(), data, g.Map{"start_time": gtime.Now()}, nil), nil)
   465  	})
   466  }