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 }