OSDN Git Service

new repo
[bytom/vapor.git] / vendor / gopkg.in / go-playground / validator.v9 / validator_test.go
1 package validator
2
3 import (
4         "bytes"
5         "context"
6         "database/sql"
7         "database/sql/driver"
8         "encoding/json"
9         "fmt"
10         "reflect"
11         "strings"
12         "testing"
13         "time"
14
15         . "gopkg.in/go-playground/assert.v1"
16
17         "github.com/go-playground/locales/en"
18         "github.com/go-playground/locales/fr"
19         "github.com/go-playground/locales/nl"
20         ut "github.com/go-playground/universal-translator"
21 )
22
23 // NOTES:
24 // - Run "go test" to run tests
25 // - Run "gocov test | gocov report" to report on test converage by file
26 // - Run "gocov test | gocov annotate -" to report on all code and functions, those ,marked with "MISS" were never called
27 //
28 // or
29 //
30 // -- may be a good idea to change to output path to somewherelike /tmp
31 // go test -coverprofile cover.out && go tool cover -html=cover.out -o cover.html
32 //
33 //
34 // go test -cpuprofile cpu.out
35 // ./validator.test -test.bench=. -test.cpuprofile=cpu.prof
36 // go tool pprof validator.test cpu.prof
37 //
38 //
39 // go test -memprofile mem.out
40
41 type I interface {
42         Foo() string
43 }
44
45 type Impl struct {
46         F string `validate:"len=3"`
47 }
48
49 func (i *Impl) Foo() string {
50         return i.F
51 }
52
53 type SubTest struct {
54         Test string `validate:"required"`
55 }
56
57 type TestInterface struct {
58         Iface I
59 }
60
61 type TestString struct {
62         BlankTag  string `validate:""`
63         Required  string `validate:"required"`
64         Len       string `validate:"len=10"`
65         Min       string `validate:"min=1"`
66         Max       string `validate:"max=10"`
67         MinMax    string `validate:"min=1,max=10"`
68         Lt        string `validate:"lt=10"`
69         Lte       string `validate:"lte=10"`
70         Gt        string `validate:"gt=10"`
71         Gte       string `validate:"gte=10"`
72         OmitEmpty string `validate:"omitempty,min=1,max=10"`
73         Sub       *SubTest
74         SubIgnore *SubTest `validate:"-"`
75         Anonymous struct {
76                 A string `validate:"required"`
77         }
78         Iface I
79 }
80
81 type TestUint64 struct {
82         Required  uint64 `validate:"required"`
83         Len       uint64 `validate:"len=10"`
84         Min       uint64 `validate:"min=1"`
85         Max       uint64 `validate:"max=10"`
86         MinMax    uint64 `validate:"min=1,max=10"`
87         OmitEmpty uint64 `validate:"omitempty,min=1,max=10"`
88 }
89
90 type TestFloat64 struct {
91         Required  float64 `validate:"required"`
92         Len       float64 `validate:"len=10"`
93         Min       float64 `validate:"min=1"`
94         Max       float64 `validate:"max=10"`
95         MinMax    float64 `validate:"min=1,max=10"`
96         Lte       float64 `validate:"lte=10"`
97         OmitEmpty float64 `validate:"omitempty,min=1,max=10"`
98 }
99
100 type TestSlice struct {
101         Required  []int `validate:"required"`
102         Len       []int `validate:"len=10"`
103         Min       []int `validate:"min=1"`
104         Max       []int `validate:"max=10"`
105         MinMax    []int `validate:"min=1,max=10"`
106         OmitEmpty []int `validate:"omitempty,min=1,max=10"`
107 }
108
109 func AssertError(t *testing.T, err error, nsKey, structNsKey, field, structField, expectedTag string) {
110
111         errs := err.(ValidationErrors)
112
113         found := false
114         var fe FieldError
115
116         for i := 0; i < len(errs); i++ {
117                 if errs[i].Namespace() == nsKey && errs[i].StructNamespace() == structNsKey {
118                         found = true
119                         fe = errs[i]
120                         break
121                 }
122         }
123
124         EqualSkip(t, 2, found, true)
125         NotEqualSkip(t, 2, fe, nil)
126         EqualSkip(t, 2, fe.Field(), field)
127         EqualSkip(t, 2, fe.StructField(), structField)
128         EqualSkip(t, 2, fe.Tag(), expectedTag)
129 }
130
131 func getError(err error, nsKey, structNsKey string) FieldError {
132
133         errs := err.(ValidationErrors)
134
135         var fe FieldError
136
137         for i := 0; i < len(errs); i++ {
138                 if errs[i].Namespace() == nsKey && errs[i].StructNamespace() == structNsKey {
139                         fe = errs[i]
140                         break
141                 }
142         }
143
144         return fe
145 }
146
147 type valuer struct {
148         Name string
149 }
150
151 func (v valuer) Value() (driver.Value, error) {
152
153         if v.Name == "errorme" {
154                 panic("SQL Driver Valuer error: some kind of error")
155                 // return nil, errors.New("some kind of error")
156         }
157
158         if len(v.Name) == 0 {
159                 return nil, nil
160         }
161
162         return v.Name, nil
163 }
164
165 type MadeUpCustomType struct {
166         FirstName string
167         LastName  string
168 }
169
170 func ValidateCustomType(field reflect.Value) interface{} {
171
172         if cust, ok := field.Interface().(MadeUpCustomType); ok {
173
174                 if len(cust.FirstName) == 0 || len(cust.LastName) == 0 {
175                         return ""
176                 }
177
178                 return cust.FirstName + " " + cust.LastName
179         }
180
181         return ""
182 }
183
184 func OverrideIntTypeForSomeReason(field reflect.Value) interface{} {
185
186         if i, ok := field.Interface().(int); ok {
187                 if i == 1 {
188                         return "1"
189                 }
190
191                 if i == 2 {
192                         return "12"
193                 }
194         }
195
196         return ""
197 }
198
199 type CustomMadeUpStruct struct {
200         MadeUp        MadeUpCustomType `validate:"required"`
201         OverriddenInt int              `validate:"gt=1"`
202 }
203
204 func ValidateValuerType(field reflect.Value) interface{} {
205
206         if valuer, ok := field.Interface().(driver.Valuer); ok {
207
208                 val, err := valuer.Value()
209                 if err != nil {
210                         // handle the error how you want
211                         return nil
212                 }
213
214                 return val
215         }
216
217         return nil
218 }
219
220 type TestPartial struct {
221         NoTag     string
222         BlankTag  string     `validate:""`
223         Required  string     `validate:"required"`
224         SubSlice  []*SubTest `validate:"required,dive"`
225         Sub       *SubTest
226         SubIgnore *SubTest `validate:"-"`
227         Anonymous struct {
228                 A         string     `validate:"required"`
229                 ASubSlice []*SubTest `validate:"required,dive"`
230
231                 SubAnonStruct []struct {
232                         Test      string `validate:"required"`
233                         OtherTest string `validate:"required"`
234                 } `validate:"required,dive"`
235         }
236 }
237
238 type TestStruct struct {
239         String string `validate:"required" json:"StringVal"`
240 }
241
242 func StructValidationTestStructSuccess(sl StructLevel) {
243
244         st := sl.Current().Interface().(TestStruct)
245
246         if st.String != "good value" {
247                 sl.ReportError(st.String, "StringVal", "String", "badvalueteststruct", "good value")
248         }
249 }
250
251 func StructValidationTestStruct(sl StructLevel) {
252
253         st := sl.Current().Interface().(TestStruct)
254
255         if st.String != "bad value" {
256                 sl.ReportError(st.String, "StringVal", "String", "badvalueteststruct", "bad value")
257         }
258 }
259
260 func StructValidationNoTestStructCustomName(sl StructLevel) {
261
262         st := sl.Current().Interface().(TestStruct)
263
264         if st.String != "bad value" {
265                 sl.ReportError(st.String, "String", "", "badvalueteststruct", "bad value")
266         }
267 }
268
269 func StructValidationTestStructInvalid(sl StructLevel) {
270
271         st := sl.Current().Interface().(TestStruct)
272
273         if st.String != "bad value" {
274                 sl.ReportError(nil, "StringVal", "String", "badvalueteststruct", "bad value")
275         }
276 }
277
278 func StructValidationTestStructReturnValidationErrors(sl StructLevel) {
279
280         s := sl.Current().Interface().(TestStructReturnValidationErrors)
281
282         errs := sl.Validator().Struct(s.Inner1.Inner2)
283         if errs == nil {
284                 return
285         }
286
287         sl.ReportValidationErrors("Inner1.", "Inner1.", errs.(ValidationErrors))
288 }
289
290 func StructValidationTestStructReturnValidationErrors2(sl StructLevel) {
291
292         s := sl.Current().Interface().(TestStructReturnValidationErrors)
293
294         errs := sl.Validator().Struct(s.Inner1.Inner2)
295         if errs == nil {
296                 return
297         }
298
299         sl.ReportValidationErrors("Inner1JSON.", "Inner1.", errs.(ValidationErrors))
300 }
301
302 type TestStructReturnValidationErrorsInner2 struct {
303         String string `validate:"required" json:"JSONString"`
304 }
305
306 type TestStructReturnValidationErrorsInner1 struct {
307         Inner2 *TestStructReturnValidationErrorsInner2
308 }
309
310 type TestStructReturnValidationErrors struct {
311         Inner1 *TestStructReturnValidationErrorsInner1 `json:"Inner1JSON"`
312 }
313
314 type StructLevelInvalidErr struct {
315         Value string
316 }
317
318 func StructLevelInvalidError(sl StructLevel) {
319
320         top := sl.Top().Interface().(StructLevelInvalidErr)
321         s := sl.Current().Interface().(StructLevelInvalidErr)
322
323         if top.Value == s.Value {
324                 sl.ReportError(nil, "Value", "Value", "required", "")
325         }
326 }
327
328 func TestStructLevelInvalidError(t *testing.T) {
329
330         validate := New()
331         validate.RegisterStructValidation(StructLevelInvalidError, StructLevelInvalidErr{})
332
333         var test StructLevelInvalidErr
334
335         err := validate.Struct(test)
336         NotEqual(t, err, nil)
337
338         errs, ok := err.(ValidationErrors)
339         Equal(t, ok, true)
340
341         fe := errs[0]
342         Equal(t, fe.Field(), "Value")
343         Equal(t, fe.StructField(), "Value")
344         Equal(t, fe.Namespace(), "StructLevelInvalidErr.Value")
345         Equal(t, fe.StructNamespace(), "StructLevelInvalidErr.Value")
346         Equal(t, fe.Tag(), "required")
347         Equal(t, fe.ActualTag(), "required")
348         Equal(t, fe.Kind(), reflect.Invalid)
349         Equal(t, fe.Type(), reflect.TypeOf(nil))
350 }
351
352 func TestNameNamespace(t *testing.T) {
353
354         type Inner2Namespace struct {
355                 String []string `validate:"dive,required" json:"JSONString"`
356         }
357
358         type Inner1Namespace struct {
359                 Inner2 *Inner2Namespace `json:"Inner2JSON"`
360         }
361
362         type Namespace struct {
363                 Inner1 *Inner1Namespace `json:"Inner1JSON"`
364         }
365
366         validate := New()
367         validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
368                 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
369
370                 if name == "-" {
371                         return ""
372                 }
373
374                 return name
375         })
376
377         i2 := &Inner2Namespace{String: []string{"ok", "ok", "ok"}}
378         i1 := &Inner1Namespace{Inner2: i2}
379         ns := &Namespace{Inner1: i1}
380
381         errs := validate.Struct(ns)
382         Equal(t, errs, nil)
383
384         i2.String[1] = ""
385
386         errs = validate.Struct(ns)
387         NotEqual(t, errs, nil)
388
389         ve := errs.(ValidationErrors)
390         Equal(t, len(ve), 1)
391         AssertError(t, errs, "Namespace.Inner1JSON.Inner2JSON.JSONString[1]", "Namespace.Inner1.Inner2.String[1]", "JSONString[1]", "String[1]", "required")
392
393         fe := getError(ve, "Namespace.Inner1JSON.Inner2JSON.JSONString[1]", "Namespace.Inner1.Inner2.String[1]")
394         NotEqual(t, fe, nil)
395         Equal(t, fe.Field(), "JSONString[1]")
396         Equal(t, fe.StructField(), "String[1]")
397         Equal(t, fe.Namespace(), "Namespace.Inner1JSON.Inner2JSON.JSONString[1]")
398         Equal(t, fe.StructNamespace(), "Namespace.Inner1.Inner2.String[1]")
399 }
400
401 func TestAnonymous(t *testing.T) {
402
403         validate := New()
404         validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
405                 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
406
407                 if name == "-" {
408                         return ""
409                 }
410
411                 return name
412         })
413
414         type Test struct {
415                 Anonymous struct {
416                         A string `validate:"required" json:"EH"`
417                 }
418                 AnonymousB struct {
419                         B string `validate:"required" json:"BEE"`
420                 }
421                 anonymousC struct {
422                         c string `validate:"required"`
423                 }
424         }
425
426         tst := &Test{
427                 Anonymous: struct {
428                         A string `validate:"required" json:"EH"`
429                 }{
430                         A: "1",
431                 },
432                 AnonymousB: struct {
433                         B string `validate:"required" json:"BEE"`
434                 }{
435                         B: "",
436                 },
437                 anonymousC: struct {
438                         c string `validate:"required"`
439                 }{
440                         c: "",
441                 },
442         }
443
444         err := validate.Struct(tst)
445         NotEqual(t, err, nil)
446
447         errs := err.(ValidationErrors)
448
449         Equal(t, len(errs), 1)
450         AssertError(t, errs, "Test.AnonymousB.BEE", "Test.AnonymousB.B", "BEE", "B", "required")
451
452         fe := getError(errs, "Test.AnonymousB.BEE", "Test.AnonymousB.B")
453         NotEqual(t, fe, nil)
454         Equal(t, fe.Field(), "BEE")
455         Equal(t, fe.StructField(), "B")
456
457         s := struct {
458                 c string `validate:"required"`
459         }{
460                 c: "",
461         }
462
463         err = validate.Struct(s)
464         Equal(t, err, nil)
465 }
466
467 func TestAnonymousSameStructDifferentTags(t *testing.T) {
468
469         validate := New()
470         validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
471                 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
472
473                 if name == "-" {
474                         return ""
475                 }
476
477                 return name
478         })
479
480         type Test struct {
481                 A interface{}
482         }
483
484         tst := &Test{
485                 A: struct {
486                         A string `validate:"required"`
487                 }{
488                         A: "",
489                 },
490         }
491
492         err := validate.Struct(tst)
493         NotEqual(t, err, nil)
494
495         errs := err.(ValidationErrors)
496
497         Equal(t, len(errs), 1)
498         AssertError(t, errs, "Test.A.A", "Test.A.A", "A", "A", "required")
499
500         tst = &Test{
501                 A: struct {
502                         A string `validate:"omitempty,required"`
503                 }{
504                         A: "",
505                 },
506         }
507
508         err = validate.Struct(tst)
509         Equal(t, err, nil)
510 }
511
512 func TestStructLevelReturnValidationErrors(t *testing.T) {
513
514         validate := New()
515         validate.RegisterStructValidation(StructValidationTestStructReturnValidationErrors, TestStructReturnValidationErrors{})
516
517         inner2 := &TestStructReturnValidationErrorsInner2{
518                 String: "I'm HERE",
519         }
520
521         inner1 := &TestStructReturnValidationErrorsInner1{
522                 Inner2: inner2,
523         }
524
525         val := &TestStructReturnValidationErrors{
526                 Inner1: inner1,
527         }
528
529         errs := validate.Struct(val)
530         Equal(t, errs, nil)
531
532         inner2.String = ""
533
534         errs = validate.Struct(val)
535         NotEqual(t, errs, nil)
536         Equal(t, len(errs.(ValidationErrors)), 2)
537         AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.Inner2.String", "TestStructReturnValidationErrors.Inner1.Inner2.String", "String", "String", "required")
538         // this is an extra error reported from struct validation
539         AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "String", "String", "required")
540 }
541
542 func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) {
543
544         validate := New()
545         validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
546                 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
547
548                 if name == "-" {
549                         return ""
550                 }
551
552                 return name
553         })
554         validate.RegisterStructValidation(StructValidationTestStructReturnValidationErrors2, TestStructReturnValidationErrors{})
555
556         inner2 := &TestStructReturnValidationErrorsInner2{
557                 String: "I'm HERE",
558         }
559
560         inner1 := &TestStructReturnValidationErrorsInner1{
561                 Inner2: inner2,
562         }
563
564         val := &TestStructReturnValidationErrors{
565                 Inner1: inner1,
566         }
567
568         errs := validate.Struct(val)
569         Equal(t, errs, nil)
570
571         inner2.String = ""
572
573         errs = validate.Struct(val)
574         NotEqual(t, errs, nil)
575         Equal(t, len(errs.(ValidationErrors)), 2)
576         AssertError(t, errs, "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString", "TestStructReturnValidationErrors.Inner1.Inner2.String", "JSONString", "String", "required")
577         // this is an extra error reported from struct validation, it's a badly formatted one, but on purpose
578         AssertError(t, errs, "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "JSONString", "String", "required")
579
580         fe := getError(errs, "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString", "TestStructReturnValidationErrors.Inner1.Inner2.String")
581         NotEqual(t, fe, nil)
582
583         // check for proper JSON namespace
584         Equal(t, fe.Field(), "JSONString")
585         Equal(t, fe.StructField(), "String")
586         Equal(t, fe.Namespace(), "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString")
587         Equal(t, fe.StructNamespace(), "TestStructReturnValidationErrors.Inner1.Inner2.String")
588
589         fe = getError(errs, "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String")
590         NotEqual(t, fe, nil)
591
592         // check for proper JSON namespace
593         Equal(t, fe.Field(), "JSONString")
594         Equal(t, fe.StructField(), "String")
595         Equal(t, fe.Namespace(), "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString")
596         Equal(t, fe.StructNamespace(), "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String")
597 }
598
599 func TestStructLevelValidations(t *testing.T) {
600
601         v1 := New()
602         v1.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
603
604         tst := &TestStruct{
605                 String: "good value",
606         }
607
608         errs := v1.Struct(tst)
609         NotEqual(t, errs, nil)
610         AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct")
611
612         v2 := New()
613         v2.RegisterStructValidation(StructValidationNoTestStructCustomName, TestStruct{})
614
615         errs = v2.Struct(tst)
616         NotEqual(t, errs, nil)
617         AssertError(t, errs, "TestStruct.String", "TestStruct.String", "String", "String", "badvalueteststruct")
618
619         v3 := New()
620         v3.RegisterStructValidation(StructValidationTestStructInvalid, TestStruct{})
621
622         errs = v3.Struct(tst)
623         NotEqual(t, errs, nil)
624         AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct")
625
626         v4 := New()
627         v4.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{})
628
629         errs = v4.Struct(tst)
630         Equal(t, errs, nil)
631 }
632
633 func TestAliasTags(t *testing.T) {
634
635         validate := New()
636         validate.RegisterAlias("iscoloralias", "hexcolor|rgb|rgba|hsl|hsla")
637
638         s := "rgb(255,255,255)"
639         errs := validate.Var(s, "iscoloralias")
640         Equal(t, errs, nil)
641
642         s = ""
643         errs = validate.Var(s, "omitempty,iscoloralias")
644         Equal(t, errs, nil)
645
646         s = "rgb(255,255,0)"
647         errs = validate.Var(s, "iscoloralias,len=5")
648         NotEqual(t, errs, nil)
649         AssertError(t, errs, "", "", "", "", "len")
650
651         type Test struct {
652                 Color string `validate:"iscoloralias"`
653         }
654
655         tst := &Test{
656                 Color: "#000",
657         }
658
659         errs = validate.Struct(tst)
660         Equal(t, errs, nil)
661
662         tst.Color = "cfvre"
663         errs = validate.Struct(tst)
664         NotEqual(t, errs, nil)
665         AssertError(t, errs, "Test.Color", "Test.Color", "Color", "Color", "iscoloralias")
666
667         fe := getError(errs, "Test.Color", "Test.Color")
668         NotEqual(t, fe, nil)
669         Equal(t, fe.ActualTag(), "hexcolor|rgb|rgba|hsl|hsla")
670
671         validate.RegisterAlias("req", "required,dive,iscoloralias")
672         arr := []string{"val1", "#fff", "#000"}
673
674         errs = validate.Var(arr, "req")
675         NotEqual(t, errs, nil)
676         AssertError(t, errs, "[0]", "[0]", "[0]", "[0]", "iscoloralias")
677
678         PanicMatches(t, func() { validate.RegisterAlias("exists!", "gt=5,lt=10") }, "Alias 'exists!' either contains restricted characters or is the same as a restricted tag needed for normal operation")
679 }
680
681 func TestNilValidator(t *testing.T) {
682
683         type TestStruct struct {
684                 Test string `validate:"required"`
685         }
686
687         ts := TestStruct{}
688
689         var val *Validate
690
691         fn := func(fl FieldLevel) bool {
692
693                 return fl.Parent().String() == fl.Field().String()
694         }
695
696         PanicMatches(t, func() { val.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) }, "runtime error: invalid memory address or nil pointer dereference")
697         PanicMatches(t, func() { val.RegisterValidation("something", fn) }, "runtime error: invalid memory address or nil pointer dereference")
698         PanicMatches(t, func() { val.Var(ts.Test, "required") }, "runtime error: invalid memory address or nil pointer dereference")
699         PanicMatches(t, func() { val.VarWithValue("test", ts.Test, "required") }, "runtime error: invalid memory address or nil pointer dereference")
700         PanicMatches(t, func() { val.Struct(ts) }, "runtime error: invalid memory address or nil pointer dereference")
701         PanicMatches(t, func() { val.StructExcept(ts, "Test") }, "runtime error: invalid memory address or nil pointer dereference")
702         PanicMatches(t, func() { val.StructPartial(ts, "Test") }, "runtime error: invalid memory address or nil pointer dereference")
703 }
704
705 func TestStructPartial(t *testing.T) {
706
707         p1 := []string{
708                 "NoTag",
709                 "Required",
710         }
711
712         p2 := []string{
713                 "SubSlice[0].Test",
714                 "Sub",
715                 "SubIgnore",
716                 "Anonymous.A",
717         }
718
719         p3 := []string{
720                 "SubTest.Test",
721         }
722
723         p4 := []string{
724                 "A",
725         }
726
727         tPartial := &TestPartial{
728                 NoTag:    "NoTag",
729                 Required: "Required",
730
731                 SubSlice: []*SubTest{
732                         {
733
734                                 Test: "Required",
735                         },
736                         {
737
738                                 Test: "Required",
739                         },
740                 },
741
742                 Sub: &SubTest{
743                         Test: "1",
744                 },
745                 SubIgnore: &SubTest{
746                         Test: "",
747                 },
748                 Anonymous: struct {
749                         A             string     `validate:"required"`
750                         ASubSlice     []*SubTest `validate:"required,dive"`
751                         SubAnonStruct []struct {
752                                 Test      string `validate:"required"`
753                                 OtherTest string `validate:"required"`
754                         } `validate:"required,dive"`
755                 }{
756                         A: "1",
757                         ASubSlice: []*SubTest{
758                                 {
759                                         Test: "Required",
760                                 },
761                                 {
762                                         Test: "Required",
763                                 },
764                         },
765
766                         SubAnonStruct: []struct {
767                                 Test      string `validate:"required"`
768                                 OtherTest string `validate:"required"`
769                         }{
770                                 {"Required", "RequiredOther"},
771                                 {"Required", "RequiredOther"},
772                         },
773                 },
774         }
775
776         validate := New()
777
778         // the following should all return no errors as everything is valid in
779         // the default state
780         errs := validate.StructPartialCtx(context.Background(), tPartial, p1...)
781         Equal(t, errs, nil)
782
783         errs = validate.StructPartial(tPartial, p2...)
784         Equal(t, errs, nil)
785
786         // this isn't really a robust test, but is ment to illustrate the ANON CASE below
787         errs = validate.StructPartial(tPartial.SubSlice[0], p3...)
788         Equal(t, errs, nil)
789
790         errs = validate.StructExceptCtx(context.Background(), tPartial, p1...)
791         Equal(t, errs, nil)
792
793         errs = validate.StructExcept(tPartial, p2...)
794         Equal(t, errs, nil)
795
796         // mod tParial for required feild and re-test making sure invalid fields are NOT required:
797         tPartial.Required = ""
798
799         errs = validate.StructExcept(tPartial, p1...)
800         Equal(t, errs, nil)
801
802         errs = validate.StructPartial(tPartial, p2...)
803         Equal(t, errs, nil)
804
805         // inversion and retesting Partial to generate failures:
806         errs = validate.StructPartial(tPartial, p1...)
807         NotEqual(t, errs, nil)
808         AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required")
809
810         errs = validate.StructExcept(tPartial, p2...)
811         AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required")
812
813         // reset Required field, and set nested struct
814         tPartial.Required = "Required"
815         tPartial.Anonymous.A = ""
816
817         // will pass as unset feilds is not going to be tested
818         errs = validate.StructPartial(tPartial, p1...)
819         Equal(t, errs, nil)
820
821         errs = validate.StructExcept(tPartial, p2...)
822         Equal(t, errs, nil)
823
824         // ANON CASE the response here is strange, it clearly does what it is being told to
825         errs = validate.StructExcept(tPartial.Anonymous, p4...)
826         Equal(t, errs, nil)
827
828         // will fail as unset feild is tested
829         errs = validate.StructPartial(tPartial, p2...)
830         NotEqual(t, errs, nil)
831         AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required")
832
833         errs = validate.StructExcept(tPartial, p1...)
834         NotEqual(t, errs, nil)
835         AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required")
836
837         // reset nested struct and unset struct in slice
838         tPartial.Anonymous.A = "Required"
839         tPartial.SubSlice[0].Test = ""
840
841         // these will pass as unset item is NOT tested
842         errs = validate.StructPartial(tPartial, p1...)
843         Equal(t, errs, nil)
844
845         errs = validate.StructExcept(tPartial, p2...)
846         Equal(t, errs, nil)
847
848         // these will fail as unset item IS tested
849         errs = validate.StructExcept(tPartial, p1...)
850         AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
851         Equal(t, len(errs.(ValidationErrors)), 1)
852
853         errs = validate.StructPartial(tPartial, p2...)
854         NotEqual(t, errs, nil)
855         AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
856         Equal(t, len(errs.(ValidationErrors)), 1)
857
858         // Unset second slice member concurrently to test dive behavior:
859         tPartial.SubSlice[1].Test = ""
860
861         errs = validate.StructPartial(tPartial, p1...)
862         Equal(t, errs, nil)
863
864         // NOTE: When specifying nested items, it is still the users responsibility
865         // to specify the dive tag, the library does not override this.
866         errs = validate.StructExcept(tPartial, p2...)
867         NotEqual(t, errs, nil)
868         AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required")
869
870         errs = validate.StructExcept(tPartial, p1...)
871         Equal(t, len(errs.(ValidationErrors)), 2)
872         AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
873         AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required")
874
875         errs = validate.StructPartial(tPartial, p2...)
876         NotEqual(t, errs, nil)
877         Equal(t, len(errs.(ValidationErrors)), 1)
878         AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
879
880         // reset struct in slice, and unset struct in slice in unset posistion
881         tPartial.SubSlice[0].Test = "Required"
882
883         // these will pass as the unset item is NOT tested
884         errs = validate.StructPartial(tPartial, p1...)
885         Equal(t, errs, nil)
886
887         errs = validate.StructPartial(tPartial, p2...)
888         Equal(t, errs, nil)
889
890         // testing for missing item by exception, yes it dives and fails
891         errs = validate.StructExcept(tPartial, p1...)
892         NotEqual(t, errs, nil)
893         Equal(t, len(errs.(ValidationErrors)), 1)
894         AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required")
895
896         errs = validate.StructExcept(tPartial, p2...)
897         NotEqual(t, errs, nil)
898         AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required")
899
900         tPartial.SubSlice[1].Test = "Required"
901
902         tPartial.Anonymous.SubAnonStruct[0].Test = ""
903         // these will pass as the unset item is NOT tested
904         errs = validate.StructPartial(tPartial, p1...)
905         Equal(t, errs, nil)
906
907         errs = validate.StructPartial(tPartial, p2...)
908         Equal(t, errs, nil)
909
910         errs = validate.StructExcept(tPartial, p1...)
911         NotEqual(t, errs, nil)
912         AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "Test", "required")
913
914         errs = validate.StructExcept(tPartial, p2...)
915         NotEqual(t, errs, nil)
916         AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "Test", "required")
917
918 }
919
920 func TestCrossStructLteFieldValidation(t *testing.T) {
921
922         type Inner struct {
923                 CreatedAt *time.Time
924                 String    string
925                 Int       int
926                 Uint      uint
927                 Float     float64
928                 Array     []string
929         }
930
931         type Test struct {
932                 Inner     *Inner
933                 CreatedAt *time.Time `validate:"ltecsfield=Inner.CreatedAt"`
934                 String    string     `validate:"ltecsfield=Inner.String"`
935                 Int       int        `validate:"ltecsfield=Inner.Int"`
936                 Uint      uint       `validate:"ltecsfield=Inner.Uint"`
937                 Float     float64    `validate:"ltecsfield=Inner.Float"`
938                 Array     []string   `validate:"ltecsfield=Inner.Array"`
939         }
940
941         now := time.Now().UTC()
942         then := now.Add(time.Hour * 5)
943
944         inner := &Inner{
945                 CreatedAt: &then,
946                 String:    "abcd",
947                 Int:       13,
948                 Uint:      13,
949                 Float:     1.13,
950                 Array:     []string{"val1", "val2"},
951         }
952
953         test := &Test{
954                 Inner:     inner,
955                 CreatedAt: &now,
956                 String:    "abc",
957                 Int:       12,
958                 Uint:      12,
959                 Float:     1.12,
960                 Array:     []string{"val1"},
961         }
962
963         validate := New()
964         errs := validate.Struct(test)
965         Equal(t, errs, nil)
966
967         test.CreatedAt = &then
968         test.String = "abcd"
969         test.Int = 13
970         test.Uint = 13
971         test.Float = 1.13
972         test.Array = []string{"val1", "val2"}
973
974         errs = validate.Struct(test)
975         Equal(t, errs, nil)
976
977         after := now.Add(time.Hour * 10)
978
979         test.CreatedAt = &after
980         test.String = "abce"
981         test.Int = 14
982         test.Uint = 14
983         test.Float = 1.14
984         test.Array = []string{"val1", "val2", "val3"}
985
986         errs = validate.Struct(test)
987         NotEqual(t, errs, nil)
988         AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltecsfield")
989         AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltecsfield")
990         AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltecsfield")
991         AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltecsfield")
992         AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltecsfield")
993         AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltecsfield")
994
995         errs = validate.VarWithValueCtx(context.Background(), 1, "", "ltecsfield")
996         NotEqual(t, errs, nil)
997         AssertError(t, errs, "", "", "", "", "ltecsfield")
998
999         // this test is for the WARNING about unforseen validation issues.
1000         errs = validate.VarWithValue(test, now, "ltecsfield")
1001         NotEqual(t, errs, nil)
1002         Equal(t, len(errs.(ValidationErrors)), 6)
1003         AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltecsfield")
1004         AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltecsfield")
1005         AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltecsfield")
1006         AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltecsfield")
1007         AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltecsfield")
1008         AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltecsfield")
1009
1010         type Other struct {
1011                 Value string
1012         }
1013
1014         type Test2 struct {
1015                 Value Other
1016                 Time  time.Time `validate:"ltecsfield=Value"`
1017         }
1018
1019         tst := Test2{
1020                 Value: Other{Value: "StringVal"},
1021                 Time:  then,
1022         }
1023
1024         errs = validate.Struct(tst)
1025         NotEqual(t, errs, nil)
1026         AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltecsfield")
1027 }
1028
1029 func TestCrossStructLtFieldValidation(t *testing.T) {
1030
1031         type Inner struct {
1032                 CreatedAt *time.Time
1033                 String    string
1034                 Int       int
1035                 Uint      uint
1036                 Float     float64
1037                 Array     []string
1038         }
1039
1040         type Test struct {
1041                 Inner     *Inner
1042                 CreatedAt *time.Time `validate:"ltcsfield=Inner.CreatedAt"`
1043                 String    string     `validate:"ltcsfield=Inner.String"`
1044                 Int       int        `validate:"ltcsfield=Inner.Int"`
1045                 Uint      uint       `validate:"ltcsfield=Inner.Uint"`
1046                 Float     float64    `validate:"ltcsfield=Inner.Float"`
1047                 Array     []string   `validate:"ltcsfield=Inner.Array"`
1048         }
1049
1050         now := time.Now().UTC()
1051         then := now.Add(time.Hour * 5)
1052
1053         inner := &Inner{
1054                 CreatedAt: &then,
1055                 String:    "abcd",
1056                 Int:       13,
1057                 Uint:      13,
1058                 Float:     1.13,
1059                 Array:     []string{"val1", "val2"},
1060         }
1061
1062         test := &Test{
1063                 Inner:     inner,
1064                 CreatedAt: &now,
1065                 String:    "abc",
1066                 Int:       12,
1067                 Uint:      12,
1068                 Float:     1.12,
1069                 Array:     []string{"val1"},
1070         }
1071
1072         validate := New()
1073         errs := validate.Struct(test)
1074         Equal(t, errs, nil)
1075
1076         test.CreatedAt = &then
1077         test.String = "abcd"
1078         test.Int = 13
1079         test.Uint = 13
1080         test.Float = 1.13
1081         test.Array = []string{"val1", "val2"}
1082
1083         errs = validate.Struct(test)
1084         NotEqual(t, errs, nil)
1085         AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltcsfield")
1086         AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltcsfield")
1087         AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltcsfield")
1088         AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltcsfield")
1089         AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltcsfield")
1090         AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltcsfield")
1091
1092         errs = validate.VarWithValue(1, "", "ltcsfield")
1093         NotEqual(t, errs, nil)
1094         AssertError(t, errs, "", "", "", "", "ltcsfield")
1095
1096         // this test is for the WARNING about unforseen validation issues.
1097         errs = validate.VarWithValue(test, now, "ltcsfield")
1098         NotEqual(t, errs, nil)
1099         AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltcsfield")
1100         AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltcsfield")
1101         AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltcsfield")
1102         AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltcsfield")
1103         AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltcsfield")
1104         AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltcsfield")
1105
1106         type Other struct {
1107                 Value string
1108         }
1109
1110         type Test2 struct {
1111                 Value Other
1112                 Time  time.Time `validate:"ltcsfield=Value"`
1113         }
1114
1115         tst := Test2{
1116                 Value: Other{Value: "StringVal"},
1117                 Time:  then,
1118         }
1119
1120         errs = validate.Struct(tst)
1121         NotEqual(t, errs, nil)
1122         AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltcsfield")
1123 }
1124
1125 func TestCrossStructGteFieldValidation(t *testing.T) {
1126
1127         type Inner struct {
1128                 CreatedAt *time.Time
1129                 String    string
1130                 Int       int
1131                 Uint      uint
1132                 Float     float64
1133                 Array     []string
1134         }
1135
1136         type Test struct {
1137                 Inner     *Inner
1138                 CreatedAt *time.Time `validate:"gtecsfield=Inner.CreatedAt"`
1139                 String    string     `validate:"gtecsfield=Inner.String"`
1140                 Int       int        `validate:"gtecsfield=Inner.Int"`
1141                 Uint      uint       `validate:"gtecsfield=Inner.Uint"`
1142                 Float     float64    `validate:"gtecsfield=Inner.Float"`
1143                 Array     []string   `validate:"gtecsfield=Inner.Array"`
1144         }
1145
1146         now := time.Now().UTC()
1147         then := now.Add(time.Hour * -5)
1148
1149         inner := &Inner{
1150                 CreatedAt: &then,
1151                 String:    "abcd",
1152                 Int:       13,
1153                 Uint:      13,
1154                 Float:     1.13,
1155                 Array:     []string{"val1", "val2"},
1156         }
1157
1158         test := &Test{
1159                 Inner:     inner,
1160                 CreatedAt: &now,
1161                 String:    "abcde",
1162                 Int:       14,
1163                 Uint:      14,
1164                 Float:     1.14,
1165                 Array:     []string{"val1", "val2", "val3"},
1166         }
1167
1168         validate := New()
1169         errs := validate.Struct(test)
1170         Equal(t, errs, nil)
1171
1172         test.CreatedAt = &then
1173         test.String = "abcd"
1174         test.Int = 13
1175         test.Uint = 13
1176         test.Float = 1.13
1177         test.Array = []string{"val1", "val2"}
1178
1179         errs = validate.Struct(test)
1180         Equal(t, errs, nil)
1181
1182         before := now.Add(time.Hour * -10)
1183
1184         test.CreatedAt = &before
1185         test.String = "abc"
1186         test.Int = 12
1187         test.Uint = 12
1188         test.Float = 1.12
1189         test.Array = []string{"val1"}
1190
1191         errs = validate.Struct(test)
1192         NotEqual(t, errs, nil)
1193         AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtecsfield")
1194         AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtecsfield")
1195         AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtecsfield")
1196         AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtecsfield")
1197         AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtecsfield")
1198         AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtecsfield")
1199
1200         errs = validate.VarWithValue(1, "", "gtecsfield")
1201         NotEqual(t, errs, nil)
1202         AssertError(t, errs, "", "", "", "", "gtecsfield")
1203
1204         // this test is for the WARNING about unforseen validation issues.
1205         errs = validate.VarWithValue(test, now, "gtecsfield")
1206         NotEqual(t, errs, nil)
1207         AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtecsfield")
1208         AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtecsfield")
1209         AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtecsfield")
1210         AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtecsfield")
1211         AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtecsfield")
1212         AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtecsfield")
1213
1214         type Other struct {
1215                 Value string
1216         }
1217
1218         type Test2 struct {
1219                 Value Other
1220                 Time  time.Time `validate:"gtecsfield=Value"`
1221         }
1222
1223         tst := Test2{
1224                 Value: Other{Value: "StringVal"},
1225                 Time:  then,
1226         }
1227
1228         errs = validate.Struct(tst)
1229         NotEqual(t, errs, nil)
1230         AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtecsfield")
1231 }
1232
1233 func TestCrossStructGtFieldValidation(t *testing.T) {
1234
1235         type Inner struct {
1236                 CreatedAt *time.Time
1237                 String    string
1238                 Int       int
1239                 Uint      uint
1240                 Float     float64
1241                 Array     []string
1242         }
1243
1244         type Test struct {
1245                 Inner     *Inner
1246                 CreatedAt *time.Time `validate:"gtcsfield=Inner.CreatedAt"`
1247                 String    string     `validate:"gtcsfield=Inner.String"`
1248                 Int       int        `validate:"gtcsfield=Inner.Int"`
1249                 Uint      uint       `validate:"gtcsfield=Inner.Uint"`
1250                 Float     float64    `validate:"gtcsfield=Inner.Float"`
1251                 Array     []string   `validate:"gtcsfield=Inner.Array"`
1252         }
1253
1254         now := time.Now().UTC()
1255         then := now.Add(time.Hour * -5)
1256
1257         inner := &Inner{
1258                 CreatedAt: &then,
1259                 String:    "abcd",
1260                 Int:       13,
1261                 Uint:      13,
1262                 Float:     1.13,
1263                 Array:     []string{"val1", "val2"},
1264         }
1265
1266         test := &Test{
1267                 Inner:     inner,
1268                 CreatedAt: &now,
1269                 String:    "abcde",
1270                 Int:       14,
1271                 Uint:      14,
1272                 Float:     1.14,
1273                 Array:     []string{"val1", "val2", "val3"},
1274         }
1275
1276         validate := New()
1277         errs := validate.Struct(test)
1278         Equal(t, errs, nil)
1279
1280         test.CreatedAt = &then
1281         test.String = "abcd"
1282         test.Int = 13
1283         test.Uint = 13
1284         test.Float = 1.13
1285         test.Array = []string{"val1", "val2"}
1286
1287         errs = validate.Struct(test)
1288         NotEqual(t, errs, nil)
1289         AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtcsfield")
1290         AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtcsfield")
1291         AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtcsfield")
1292         AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtcsfield")
1293         AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtcsfield")
1294         AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtcsfield")
1295
1296         errs = validate.VarWithValue(1, "", "gtcsfield")
1297         NotEqual(t, errs, nil)
1298         AssertError(t, errs, "", "", "", "", "gtcsfield")
1299
1300         // this test is for the WARNING about unforseen validation issues.
1301         errs = validate.VarWithValue(test, now, "gtcsfield")
1302         NotEqual(t, errs, nil)
1303         AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtcsfield")
1304         AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtcsfield")
1305         AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtcsfield")
1306         AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtcsfield")
1307         AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtcsfield")
1308         AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtcsfield")
1309
1310         type Other struct {
1311                 Value string
1312         }
1313
1314         type Test2 struct {
1315                 Value Other
1316                 Time  time.Time `validate:"gtcsfield=Value"`
1317         }
1318
1319         tst := Test2{
1320                 Value: Other{Value: "StringVal"},
1321                 Time:  then,
1322         }
1323
1324         errs = validate.Struct(tst)
1325         NotEqual(t, errs, nil)
1326         AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtcsfield")
1327 }
1328
1329 func TestCrossStructNeFieldValidation(t *testing.T) {
1330
1331         type Inner struct {
1332                 CreatedAt *time.Time
1333         }
1334
1335         type Test struct {
1336                 Inner     *Inner
1337                 CreatedAt *time.Time `validate:"necsfield=Inner.CreatedAt"`
1338         }
1339
1340         now := time.Now().UTC()
1341         then := now.Add(time.Hour * 5)
1342
1343         inner := &Inner{
1344                 CreatedAt: &then,
1345         }
1346
1347         test := &Test{
1348                 Inner:     inner,
1349                 CreatedAt: &now,
1350         }
1351
1352         validate := New()
1353         errs := validate.Struct(test)
1354         Equal(t, errs, nil)
1355
1356         test.CreatedAt = &then
1357
1358         errs = validate.Struct(test)
1359         NotEqual(t, errs, nil)
1360         AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "necsfield")
1361
1362         var j uint64
1363         var k float64
1364         var j2 uint64
1365         var k2 float64
1366         s := "abcd"
1367         i := 1
1368         j = 1
1369         k = 1.543
1370         arr := []string{"test"}
1371
1372         s2 := "abcd"
1373         i2 := 1
1374         j2 = 1
1375         k2 = 1.543
1376         arr2 := []string{"test"}
1377         arr3 := []string{"test", "test2"}
1378         now2 := now
1379
1380         errs = validate.VarWithValue(s, s2, "necsfield")
1381         NotEqual(t, errs, nil)
1382         AssertError(t, errs, "", "", "", "", "necsfield")
1383
1384         errs = validate.VarWithValue(i2, i, "necsfield")
1385         NotEqual(t, errs, nil)
1386         AssertError(t, errs, "", "", "", "", "necsfield")
1387
1388         errs = validate.VarWithValue(j2, j, "necsfield")
1389         NotEqual(t, errs, nil)
1390         AssertError(t, errs, "", "", "", "", "necsfield")
1391
1392         errs = validate.VarWithValue(k2, k, "necsfield")
1393         NotEqual(t, errs, nil)
1394         AssertError(t, errs, "", "", "", "", "necsfield")
1395
1396         errs = validate.VarWithValue(arr2, arr, "necsfield")
1397         NotEqual(t, errs, nil)
1398         AssertError(t, errs, "", "", "", "", "necsfield")
1399
1400         errs = validate.VarWithValue(now2, now, "necsfield")
1401         NotEqual(t, errs, nil)
1402         AssertError(t, errs, "", "", "", "", "necsfield")
1403
1404         errs = validate.VarWithValue(arr3, arr, "necsfield")
1405         Equal(t, errs, nil)
1406
1407         type SInner struct {
1408                 Name string
1409         }
1410
1411         type TStruct struct {
1412                 Inner     *SInner
1413                 CreatedAt *time.Time `validate:"necsfield=Inner"`
1414         }
1415
1416         sinner := &SInner{
1417                 Name: "NAME",
1418         }
1419
1420         test2 := &TStruct{
1421                 Inner:     sinner,
1422                 CreatedAt: &now,
1423         }
1424
1425         errs = validate.Struct(test2)
1426         Equal(t, errs, nil)
1427
1428         test2.Inner = nil
1429         errs = validate.Struct(test2)
1430         Equal(t, errs, nil)
1431
1432         errs = validate.VarWithValue(nil, 1, "necsfield")
1433         NotEqual(t, errs, nil)
1434         AssertError(t, errs, "", "", "", "", "necsfield")
1435 }
1436
1437 func TestCrossStructEqFieldValidation(t *testing.T) {
1438
1439         type Inner struct {
1440                 CreatedAt *time.Time
1441         }
1442
1443         type Test struct {
1444                 Inner     *Inner
1445                 CreatedAt *time.Time `validate:"eqcsfield=Inner.CreatedAt"`
1446         }
1447
1448         now := time.Now().UTC()
1449
1450         inner := &Inner{
1451                 CreatedAt: &now,
1452         }
1453
1454         test := &Test{
1455                 Inner:     inner,
1456                 CreatedAt: &now,
1457         }
1458
1459         validate := New()
1460         errs := validate.Struct(test)
1461         Equal(t, errs, nil)
1462
1463         newTime := time.Now().UTC()
1464         test.CreatedAt = &newTime
1465
1466         errs = validate.Struct(test)
1467         NotEqual(t, errs, nil)
1468         AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield")
1469
1470         var j uint64
1471         var k float64
1472         s := "abcd"
1473         i := 1
1474         j = 1
1475         k = 1.543
1476         arr := []string{"test"}
1477
1478         var j2 uint64
1479         var k2 float64
1480         s2 := "abcd"
1481         i2 := 1
1482         j2 = 1
1483         k2 = 1.543
1484         arr2 := []string{"test"}
1485         arr3 := []string{"test", "test2"}
1486         now2 := now
1487
1488         errs = validate.VarWithValue(s, s2, "eqcsfield")
1489         Equal(t, errs, nil)
1490
1491         errs = validate.VarWithValue(i2, i, "eqcsfield")
1492         Equal(t, errs, nil)
1493
1494         errs = validate.VarWithValue(j2, j, "eqcsfield")
1495         Equal(t, errs, nil)
1496
1497         errs = validate.VarWithValue(k2, k, "eqcsfield")
1498         Equal(t, errs, nil)
1499
1500         errs = validate.VarWithValue(arr2, arr, "eqcsfield")
1501         Equal(t, errs, nil)
1502
1503         errs = validate.VarWithValue(now2, now, "eqcsfield")
1504         Equal(t, errs, nil)
1505
1506         errs = validate.VarWithValue(arr3, arr, "eqcsfield")
1507         NotEqual(t, errs, nil)
1508         AssertError(t, errs, "", "", "", "", "eqcsfield")
1509
1510         type SInner struct {
1511                 Name string
1512         }
1513
1514         type TStruct struct {
1515                 Inner     *SInner
1516                 CreatedAt *time.Time `validate:"eqcsfield=Inner"`
1517         }
1518
1519         sinner := &SInner{
1520                 Name: "NAME",
1521         }
1522
1523         test2 := &TStruct{
1524                 Inner:     sinner,
1525                 CreatedAt: &now,
1526         }
1527
1528         errs = validate.Struct(test2)
1529         NotEqual(t, errs, nil)
1530         AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield")
1531
1532         test2.Inner = nil
1533         errs = validate.Struct(test2)
1534         NotEqual(t, errs, nil)
1535         AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield")
1536
1537         errs = validate.VarWithValue(nil, 1, "eqcsfield")
1538         NotEqual(t, errs, nil)
1539         AssertError(t, errs, "", "", "", "", "eqcsfield")
1540 }
1541
1542 func TestCrossNamespaceFieldValidation(t *testing.T) {
1543
1544         type SliceStruct struct {
1545                 Name string
1546         }
1547
1548         type MapStruct struct {
1549                 Name string
1550         }
1551
1552         type Inner struct {
1553                 CreatedAt        *time.Time
1554                 Slice            []string
1555                 SliceStructs     []*SliceStruct
1556                 SliceSlice       [][]string
1557                 SliceSliceStruct [][]*SliceStruct
1558                 SliceMap         []map[string]string
1559                 Map              map[string]string
1560                 MapMap           map[string]map[string]string
1561                 MapStructs       map[string]*SliceStruct
1562                 MapMapStruct     map[string]map[string]*SliceStruct
1563                 MapSlice         map[string][]string
1564                 MapInt           map[int]string
1565                 MapInt8          map[int8]string
1566                 MapInt16         map[int16]string
1567                 MapInt32         map[int32]string
1568                 MapInt64         map[int64]string
1569                 MapUint          map[uint]string
1570                 MapUint8         map[uint8]string
1571                 MapUint16        map[uint16]string
1572                 MapUint32        map[uint32]string
1573                 MapUint64        map[uint64]string
1574                 MapFloat32       map[float32]string
1575                 MapFloat64       map[float64]string
1576                 MapBool          map[bool]string
1577         }
1578
1579         type Test struct {
1580                 Inner     *Inner
1581                 CreatedAt *time.Time
1582         }
1583
1584         now := time.Now()
1585
1586         inner := &Inner{
1587                 CreatedAt:        &now,
1588                 Slice:            []string{"val1", "val2", "val3"},
1589                 SliceStructs:     []*SliceStruct{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}},
1590                 SliceSlice:       [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}},
1591                 SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}},
1592                 SliceMap:         []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}},
1593                 Map:              map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"},
1594                 MapStructs:       map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}},
1595                 MapMap:           map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}},
1596                 MapMapStruct:     map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}},
1597                 MapSlice:         map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}},
1598                 MapInt:           map[int]string{1: "val1", 2: "val2", 3: "val3"},
1599                 MapInt8:          map[int8]string{1: "val1", 2: "val2", 3: "val3"},
1600                 MapInt16:         map[int16]string{1: "val1", 2: "val2", 3: "val3"},
1601                 MapInt32:         map[int32]string{1: "val1", 2: "val2", 3: "val3"},
1602                 MapInt64:         map[int64]string{1: "val1", 2: "val2", 3: "val3"},
1603                 MapUint:          map[uint]string{1: "val1", 2: "val2", 3: "val3"},
1604                 MapUint8:         map[uint8]string{1: "val1", 2: "val2", 3: "val3"},
1605                 MapUint16:        map[uint16]string{1: "val1", 2: "val2", 3: "val3"},
1606                 MapUint32:        map[uint32]string{1: "val1", 2: "val2", 3: "val3"},
1607                 MapUint64:        map[uint64]string{1: "val1", 2: "val2", 3: "val3"},
1608                 MapFloat32:       map[float32]string{1.01: "val1", 2.02: "val2", 3.03: "val3"},
1609                 MapFloat64:       map[float64]string{1.01: "val1", 2.02: "val2", 3.03: "val3"},
1610                 MapBool:          map[bool]string{true: "val1", false: "val2"},
1611         }
1612
1613         test := &Test{
1614                 Inner:     inner,
1615                 CreatedAt: &now,
1616         }
1617
1618         val := reflect.ValueOf(test)
1619
1620         vd := New()
1621         v := &validate{
1622                 v: vd,
1623         }
1624
1625         current, kind, ok := v.getStructFieldOKInternal(val, "Inner.CreatedAt")
1626         Equal(t, ok, true)
1627         Equal(t, kind, reflect.Struct)
1628         tm, ok := current.Interface().(time.Time)
1629         Equal(t, ok, true)
1630         Equal(t, tm, now)
1631
1632         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.Slice[1]")
1633         Equal(t, ok, true)
1634         Equal(t, kind, reflect.String)
1635         Equal(t, current.String(), "val2")
1636
1637         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.CrazyNonExistantField")
1638         Equal(t, ok, false)
1639
1640         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.Slice[101]")
1641         Equal(t, ok, false)
1642
1643         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.Map[key3]")
1644         Equal(t, ok, true)
1645         Equal(t, kind, reflect.String)
1646         Equal(t, current.String(), "val3")
1647
1648         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapMap[key2][key2-1]")
1649         Equal(t, ok, true)
1650         Equal(t, kind, reflect.String)
1651         Equal(t, current.String(), "val2")
1652
1653         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapStructs[key2].Name")
1654         Equal(t, ok, true)
1655         Equal(t, kind, reflect.String)
1656         Equal(t, current.String(), "name2")
1657
1658         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapMapStruct[key3][key3-1].Name")
1659         Equal(t, ok, true)
1660         Equal(t, kind, reflect.String)
1661         Equal(t, current.String(), "name3")
1662
1663         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.SliceSlice[2][0]")
1664         Equal(t, ok, true)
1665         Equal(t, kind, reflect.String)
1666         Equal(t, current.String(), "7")
1667
1668         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.SliceSliceStruct[2][1].Name")
1669         Equal(t, ok, true)
1670         Equal(t, kind, reflect.String)
1671         Equal(t, current.String(), "name8")
1672
1673         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.SliceMap[1][key5]")
1674         Equal(t, ok, true)
1675         Equal(t, kind, reflect.String)
1676         Equal(t, current.String(), "val5")
1677
1678         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapSlice[key3][2]")
1679         Equal(t, ok, true)
1680         Equal(t, kind, reflect.String)
1681         Equal(t, current.String(), "9")
1682
1683         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapInt[2]")
1684         Equal(t, ok, true)
1685         Equal(t, kind, reflect.String)
1686         Equal(t, current.String(), "val2")
1687
1688         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapInt8[2]")
1689         Equal(t, ok, true)
1690         Equal(t, kind, reflect.String)
1691         Equal(t, current.String(), "val2")
1692
1693         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapInt16[2]")
1694         Equal(t, ok, true)
1695         Equal(t, kind, reflect.String)
1696         Equal(t, current.String(), "val2")
1697
1698         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapInt32[2]")
1699         Equal(t, ok, true)
1700         Equal(t, kind, reflect.String)
1701         Equal(t, current.String(), "val2")
1702
1703         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapInt64[2]")
1704         Equal(t, ok, true)
1705         Equal(t, kind, reflect.String)
1706         Equal(t, current.String(), "val2")
1707
1708         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapUint[2]")
1709         Equal(t, ok, true)
1710         Equal(t, kind, reflect.String)
1711         Equal(t, current.String(), "val2")
1712
1713         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapUint8[2]")
1714         Equal(t, ok, true)
1715         Equal(t, kind, reflect.String)
1716         Equal(t, current.String(), "val2")
1717
1718         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapUint16[2]")
1719         Equal(t, ok, true)
1720         Equal(t, kind, reflect.String)
1721         Equal(t, current.String(), "val2")
1722
1723         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapUint32[2]")
1724         Equal(t, ok, true)
1725         Equal(t, kind, reflect.String)
1726         Equal(t, current.String(), "val2")
1727
1728         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapUint64[2]")
1729         Equal(t, ok, true)
1730         Equal(t, kind, reflect.String)
1731         Equal(t, current.String(), "val2")
1732
1733         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapFloat32[3.03]")
1734         Equal(t, ok, true)
1735         Equal(t, kind, reflect.String)
1736         Equal(t, current.String(), "val3")
1737
1738         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapFloat64[2.02]")
1739         Equal(t, ok, true)
1740         Equal(t, kind, reflect.String)
1741         Equal(t, current.String(), "val2")
1742
1743         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.MapBool[true]")
1744         Equal(t, ok, true)
1745         Equal(t, kind, reflect.String)
1746         Equal(t, current.String(), "val1")
1747
1748         inner = &Inner{
1749                 CreatedAt:        &now,
1750                 Slice:            []string{"val1", "val2", "val3"},
1751                 SliceStructs:     []*SliceStruct{{Name: "name1"}, {Name: "name2"}, nil},
1752                 SliceSlice:       [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}},
1753                 SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}},
1754                 SliceMap:         []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}},
1755                 Map:              map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"},
1756                 MapStructs:       map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}},
1757                 MapMap:           map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}},
1758                 MapMapStruct:     map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}},
1759                 MapSlice:         map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}},
1760         }
1761
1762         test = &Test{
1763                 Inner:     inner,
1764                 CreatedAt: nil,
1765         }
1766
1767         val = reflect.ValueOf(test)
1768
1769         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.SliceStructs[2]")
1770         Equal(t, ok, true)
1771         Equal(t, kind, reflect.Ptr)
1772         Equal(t, current.String(), "<*validator.SliceStruct Value>")
1773         Equal(t, current.IsNil(), true)
1774
1775         current, kind, ok = v.getStructFieldOKInternal(val, "Inner.SliceStructs[2].Name")
1776         Equal(t, ok, false)
1777         Equal(t, kind, reflect.Ptr)
1778         Equal(t, current.String(), "<*validator.SliceStruct Value>")
1779         Equal(t, current.IsNil(), true)
1780
1781         PanicMatches(t, func() { v.getStructFieldOKInternal(reflect.ValueOf(1), "crazyinput") }, "Invalid field namespace")
1782 }
1783
1784 func TestExistsValidation(t *testing.T) {
1785
1786         jsonText := "{ \"truthiness2\": true }"
1787
1788         type Thing struct {
1789                 Truthiness *bool `json:"truthiness" validate:"required"`
1790         }
1791
1792         var ting Thing
1793
1794         err := json.Unmarshal([]byte(jsonText), &ting)
1795         Equal(t, err, nil)
1796         NotEqual(t, ting, nil)
1797         Equal(t, ting.Truthiness, nil)
1798
1799         validate := New()
1800         errs := validate.Struct(ting)
1801         NotEqual(t, errs, nil)
1802         AssertError(t, errs, "Thing.Truthiness", "Thing.Truthiness", "Truthiness", "Truthiness", "required")
1803
1804         jsonText = "{ \"truthiness\": true }"
1805
1806         err = json.Unmarshal([]byte(jsonText), &ting)
1807         Equal(t, err, nil)
1808         NotEqual(t, ting, nil)
1809         Equal(t, ting.Truthiness, true)
1810
1811         errs = validate.Struct(ting)
1812         Equal(t, errs, nil)
1813 }
1814
1815 func TestSQLValue2Validation(t *testing.T) {
1816
1817         validate := New()
1818         validate.RegisterCustomTypeFunc(ValidateValuerType, valuer{}, (*driver.Valuer)(nil), sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
1819         validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
1820         validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1)
1821
1822         val := valuer{
1823                 Name: "",
1824         }
1825
1826         errs := validate.Var(val, "required")
1827         NotEqual(t, errs, nil)
1828         AssertError(t, errs, "", "", "", "", "required")
1829
1830         val.Name = "Valid Name"
1831         errs = validate.VarCtx(context.Background(), val, "required")
1832         Equal(t, errs, nil)
1833
1834         val.Name = "errorme"
1835
1836         PanicMatches(t, func() { validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error")
1837
1838         type myValuer valuer
1839
1840         myVal := valuer{
1841                 Name: "",
1842         }
1843
1844         errs = validate.Var(myVal, "required")
1845         NotEqual(t, errs, nil)
1846         AssertError(t, errs, "", "", "", "", "required")
1847
1848         cust := MadeUpCustomType{
1849                 FirstName: "Joey",
1850                 LastName:  "Bloggs",
1851         }
1852
1853         c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
1854
1855         errs = validate.Struct(c)
1856         Equal(t, errs, nil)
1857
1858         c.MadeUp.FirstName = ""
1859         c.OverriddenInt = 1
1860
1861         errs = validate.Struct(c)
1862         NotEqual(t, errs, nil)
1863         Equal(t, len(errs.(ValidationErrors)), 2)
1864         AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "CustomMadeUpStruct.MadeUp", "MadeUp", "MadeUp", "required")
1865         AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "OverriddenInt", "gt")
1866 }
1867
1868 func TestSQLValueValidation(t *testing.T) {
1869
1870         validate := New()
1871         validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{})
1872         validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
1873         validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1)
1874
1875         val := valuer{
1876                 Name: "",
1877         }
1878
1879         errs := validate.Var(val, "required")
1880         NotEqual(t, errs, nil)
1881         AssertError(t, errs, "", "", "", "", "required")
1882
1883         val.Name = "Valid Name"
1884         errs = validate.Var(val, "required")
1885         Equal(t, errs, nil)
1886
1887         val.Name = "errorme"
1888
1889         PanicMatches(t, func() { errs = validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error")
1890
1891         type myValuer valuer
1892
1893         myVal := valuer{
1894                 Name: "",
1895         }
1896
1897         errs = validate.Var(myVal, "required")
1898         NotEqual(t, errs, nil)
1899         AssertError(t, errs, "", "", "", "", "required")
1900
1901         cust := MadeUpCustomType{
1902                 FirstName: "Joey",
1903                 LastName:  "Bloggs",
1904         }
1905
1906         c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
1907
1908         errs = validate.Struct(c)
1909         Equal(t, errs, nil)
1910
1911         c.MadeUp.FirstName = ""
1912         c.OverriddenInt = 1
1913
1914         errs = validate.Struct(c)
1915         NotEqual(t, errs, nil)
1916         Equal(t, len(errs.(ValidationErrors)), 2)
1917         AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "CustomMadeUpStruct.MadeUp", "MadeUp", "MadeUp", "required")
1918         AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "OverriddenInt", "gt")
1919 }
1920
1921 func TestMACValidation(t *testing.T) {
1922         tests := []struct {
1923                 param    string
1924                 expected bool
1925         }{
1926                 {"3D:F2:C9:A6:B3:4F", true},
1927                 {"3D-F2-C9-A6-B3:4F", false},
1928                 {"123", false},
1929                 {"", false},
1930                 {"abacaba", false},
1931                 {"00:25:96:FF:FE:12:34:56", true},
1932                 {"0025:96FF:FE12:3456", false},
1933         }
1934
1935         validate := New()
1936
1937         for i, test := range tests {
1938
1939                 errs := validate.Var(test.param, "mac")
1940
1941                 if test.expected {
1942                         if !IsEqual(errs, nil) {
1943                                 t.Fatalf("Index: %d mac failed Error: %s", i, errs)
1944                         }
1945                 } else {
1946                         if IsEqual(errs, nil) {
1947                                 t.Fatalf("Index: %d mac failed Error: %s", i, errs)
1948                         } else {
1949                                 val := getError(errs, "", "")
1950                                 if val.Tag() != "mac" {
1951                                         t.Fatalf("Index: %d mac failed Error: %s", i, errs)
1952                                 }
1953                         }
1954                 }
1955         }
1956 }
1957
1958 func TestIPValidation(t *testing.T) {
1959         tests := []struct {
1960                 param    string
1961                 expected bool
1962         }{
1963                 {"", false},
1964                 {"10.0.0.1", true},
1965                 {"172.16.0.1", true},
1966                 {"192.168.0.1", true},
1967                 {"192.168.255.254", true},
1968                 {"192.168.255.256", false},
1969                 {"172.16.255.254", true},
1970                 {"172.16.256.255", false},
1971                 {"2001:cdba:0000:0000:0000:0000:3257:9652", true},
1972                 {"2001:cdba:0:0:0:0:3257:9652", true},
1973                 {"2001:cdba::3257:9652", true},
1974         }
1975
1976         validate := New()
1977
1978         for i, test := range tests {
1979
1980                 errs := validate.Var(test.param, "ip")
1981
1982                 if test.expected {
1983                         if !IsEqual(errs, nil) {
1984                                 t.Fatalf("Index: %d ip failed Error: %s", i, errs)
1985                         }
1986                 } else {
1987                         if IsEqual(errs, nil) {
1988                                 t.Fatalf("Index: %d ip failed Error: %s", i, errs)
1989                         } else {
1990                                 val := getError(errs, "", "")
1991                                 if val.Tag() != "ip" {
1992                                         t.Fatalf("Index: %d ip failed Error: %s", i, errs)
1993                                 }
1994                         }
1995                 }
1996         }
1997 }
1998
1999 func TestIPv6Validation(t *testing.T) {
2000         tests := []struct {
2001                 param    string
2002                 expected bool
2003         }{
2004                 {"10.0.0.1", false},
2005                 {"172.16.0.1", false},
2006                 {"192.168.0.1", false},
2007                 {"192.168.255.254", false},
2008                 {"192.168.255.256", false},
2009                 {"172.16.255.254", false},
2010                 {"172.16.256.255", false},
2011                 {"2001:cdba:0000:0000:0000:0000:3257:9652", true},
2012                 {"2001:cdba:0:0:0:0:3257:9652", true},
2013                 {"2001:cdba::3257:9652", true},
2014         }
2015
2016         validate := New()
2017
2018         for i, test := range tests {
2019
2020                 errs := validate.Var(test.param, "ipv6")
2021
2022                 if test.expected {
2023                         if !IsEqual(errs, nil) {
2024                                 t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
2025                         }
2026                 } else {
2027                         if IsEqual(errs, nil) {
2028                                 t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
2029                         } else {
2030                                 val := getError(errs, "", "")
2031                                 if val.Tag() != "ipv6" {
2032                                         t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
2033                                 }
2034                         }
2035                 }
2036         }
2037 }
2038
2039 func TestIPv4Validation(t *testing.T) {
2040         tests := []struct {
2041                 param    string
2042                 expected bool
2043         }{
2044                 {"10.0.0.1", true},
2045                 {"172.16.0.1", true},
2046                 {"192.168.0.1", true},
2047                 {"192.168.255.254", true},
2048                 {"192.168.255.256", false},
2049                 {"172.16.255.254", true},
2050                 {"172.16.256.255", false},
2051                 {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
2052                 {"2001:cdba:0:0:0:0:3257:9652", false},
2053                 {"2001:cdba::3257:9652", false},
2054         }
2055
2056         validate := New()
2057
2058         for i, test := range tests {
2059
2060                 errs := validate.Var(test.param, "ipv4")
2061
2062                 if test.expected {
2063                         if !IsEqual(errs, nil) {
2064                                 t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
2065                         }
2066                 } else {
2067                         if IsEqual(errs, nil) {
2068                                 t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
2069                         } else {
2070                                 val := getError(errs, "", "")
2071                                 if val.Tag() != "ipv4" {
2072                                         t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
2073                                 }
2074                         }
2075                 }
2076         }
2077 }
2078
2079 func TestCIDRValidation(t *testing.T) {
2080         tests := []struct {
2081                 param    string
2082                 expected bool
2083         }{
2084                 {"10.0.0.0/0", true},
2085                 {"10.0.0.1/8", true},
2086                 {"172.16.0.1/16", true},
2087                 {"192.168.0.1/24", true},
2088                 {"192.168.255.254/24", true},
2089                 {"192.168.255.254/48", false},
2090                 {"192.168.255.256/24", false},
2091                 {"172.16.255.254/16", true},
2092                 {"172.16.256.255/16", false},
2093                 {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true},
2094                 {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
2095                 {"2001:cdba:0:0:0:0:3257:9652/32", true},
2096                 {"2001:cdba::3257:9652/16", true},
2097         }
2098
2099         validate := New()
2100
2101         for i, test := range tests {
2102
2103                 errs := validate.Var(test.param, "cidr")
2104
2105                 if test.expected {
2106                         if !IsEqual(errs, nil) {
2107                                 t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
2108                         }
2109                 } else {
2110                         if IsEqual(errs, nil) {
2111                                 t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
2112                         } else {
2113                                 val := getError(errs, "", "")
2114                                 if val.Tag() != "cidr" {
2115                                         t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
2116                                 }
2117                         }
2118                 }
2119         }
2120 }
2121
2122 func TestCIDRv6Validation(t *testing.T) {
2123         tests := []struct {
2124                 param    string
2125                 expected bool
2126         }{
2127                 {"10.0.0.0/0", false},
2128                 {"10.0.0.1/8", false},
2129                 {"172.16.0.1/16", false},
2130                 {"192.168.0.1/24", false},
2131                 {"192.168.255.254/24", false},
2132                 {"192.168.255.254/48", false},
2133                 {"192.168.255.256/24", false},
2134                 {"172.16.255.254/16", false},
2135                 {"172.16.256.255/16", false},
2136                 {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true},
2137                 {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
2138                 {"2001:cdba:0:0:0:0:3257:9652/32", true},
2139                 {"2001:cdba::3257:9652/16", true},
2140         }
2141
2142         validate := New()
2143
2144         for i, test := range tests {
2145
2146                 errs := validate.Var(test.param, "cidrv6")
2147
2148                 if test.expected {
2149                         if !IsEqual(errs, nil) {
2150                                 t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
2151                         }
2152                 } else {
2153                         if IsEqual(errs, nil) {
2154                                 t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
2155                         } else {
2156                                 val := getError(errs, "", "")
2157                                 if val.Tag() != "cidrv6" {
2158                                         t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
2159                                 }
2160                         }
2161                 }
2162         }
2163 }
2164
2165 func TestCIDRv4Validation(t *testing.T) {
2166         tests := []struct {
2167                 param    string
2168                 expected bool
2169         }{
2170                 {"10.0.0.0/0", true},
2171                 {"10.0.0.1/8", true},
2172                 {"172.16.0.1/16", true},
2173                 {"192.168.0.1/24", true},
2174                 {"192.168.255.254/24", true},
2175                 {"192.168.255.254/48", false},
2176                 {"192.168.255.256/24", false},
2177                 {"172.16.255.254/16", true},
2178                 {"172.16.256.255/16", false},
2179                 {"2001:cdba:0000:0000:0000:0000:3257:9652/64", false},
2180                 {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
2181                 {"2001:cdba:0:0:0:0:3257:9652/32", false},
2182                 {"2001:cdba::3257:9652/16", false},
2183         }
2184
2185         validate := New()
2186
2187         for i, test := range tests {
2188
2189                 errs := validate.Var(test.param, "cidrv4")
2190
2191                 if test.expected {
2192                         if !IsEqual(errs, nil) {
2193                                 t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
2194                         }
2195                 } else {
2196                         if IsEqual(errs, nil) {
2197                                 t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
2198                         } else {
2199                                 val := getError(errs, "", "")
2200                                 if val.Tag() != "cidrv4" {
2201                                         t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
2202                                 }
2203                         }
2204                 }
2205         }
2206 }
2207
2208 func TestTCPAddrValidation(t *testing.T) {
2209         tests := []struct {
2210                 param    string
2211                 expected bool
2212         }{
2213                 {"", false},
2214                 {":80", false},
2215                 {"127.0.0.1:80", true},
2216                 {"[::1]:80", true},
2217                 {"256.0.0.0:1", false},
2218                 {"[::1]", false},
2219         }
2220
2221         validate := New()
2222
2223         for i, test := range tests {
2224                 errs := validate.Var(test.param, "tcp_addr")
2225                 if test.expected {
2226                         if !IsEqual(errs, nil) {
2227                                 t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
2228                         }
2229                 } else {
2230                         if IsEqual(errs, nil) {
2231                                 t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
2232                         } else {
2233                                 val := getError(errs, "", "")
2234                                 if val.Tag() != "tcp_addr" {
2235                                         t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
2236                                 }
2237                         }
2238                 }
2239         }
2240 }
2241
2242 func TestTCP6AddrValidation(t *testing.T) {
2243         tests := []struct {
2244                 param    string
2245                 expected bool
2246         }{
2247                 {"", false},
2248                 {":80", false},
2249                 {"127.0.0.1:80", false},
2250                 {"[::1]:80", true},
2251                 {"256.0.0.0:1", false},
2252                 {"[::1]", false},
2253         }
2254
2255         validate := New()
2256
2257         for i, test := range tests {
2258                 errs := validate.Var(test.param, "tcp6_addr")
2259                 if test.expected {
2260                         if !IsEqual(errs, nil) {
2261                                 t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
2262                         }
2263                 } else {
2264                         if IsEqual(errs, nil) {
2265                                 t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
2266                         } else {
2267                                 val := getError(errs, "", "")
2268                                 if val.Tag() != "tcp6_addr" {
2269                                         t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
2270                                 }
2271                         }
2272                 }
2273         }
2274 }
2275
2276 func TestTCP4AddrValidation(t *testing.T) {
2277         tests := []struct {
2278                 param    string
2279                 expected bool
2280         }{
2281                 {"", false},
2282                 {":80", false},
2283                 {"127.0.0.1:80", true},
2284                 {"[::1]:80", false}, // https://github.com/golang/go/issues/14037
2285                 {"256.0.0.0:1", false},
2286                 {"[::1]", false},
2287         }
2288
2289         validate := New()
2290
2291         for i, test := range tests {
2292                 errs := validate.Var(test.param, "tcp4_addr")
2293                 if test.expected {
2294                         if !IsEqual(errs, nil) {
2295                                 t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
2296                         }
2297                 } else {
2298                         if IsEqual(errs, nil) {
2299                                 t.Log(test.param, IsEqual(errs, nil))
2300                                 t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
2301                         } else {
2302                                 val := getError(errs, "", "")
2303                                 if val.Tag() != "tcp4_addr" {
2304                                         t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
2305                                 }
2306                         }
2307                 }
2308         }
2309 }
2310
2311 func TestUDPAddrValidation(t *testing.T) {
2312         tests := []struct {
2313                 param    string
2314                 expected bool
2315         }{
2316                 {"", false},
2317                 {":80", false},
2318                 {"127.0.0.1:80", true},
2319                 {"[::1]:80", true},
2320                 {"256.0.0.0:1", false},
2321                 {"[::1]", false},
2322         }
2323
2324         validate := New()
2325
2326         for i, test := range tests {
2327                 errs := validate.Var(test.param, "udp_addr")
2328                 if test.expected {
2329                         if !IsEqual(errs, nil) {
2330                                 t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
2331                         }
2332                 } else {
2333                         if IsEqual(errs, nil) {
2334                                 t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
2335                         } else {
2336                                 val := getError(errs, "", "")
2337                                 if val.Tag() != "udp_addr" {
2338                                         t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
2339                                 }
2340                         }
2341                 }
2342         }
2343 }
2344
2345 func TestUDP6AddrValidation(t *testing.T) {
2346         tests := []struct {
2347                 param    string
2348                 expected bool
2349         }{
2350                 {"", false},
2351                 {":80", false},
2352                 {"127.0.0.1:80", false},
2353                 {"[::1]:80", true},
2354                 {"256.0.0.0:1", false},
2355                 {"[::1]", false},
2356         }
2357
2358         validate := New()
2359
2360         for i, test := range tests {
2361                 errs := validate.Var(test.param, "udp6_addr")
2362                 if test.expected {
2363                         if !IsEqual(errs, nil) {
2364                                 t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
2365                         }
2366                 } else {
2367                         if IsEqual(errs, nil) {
2368                                 t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
2369                         } else {
2370                                 val := getError(errs, "", "")
2371                                 if val.Tag() != "udp6_addr" {
2372                                         t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
2373                                 }
2374                         }
2375                 }
2376         }
2377 }
2378
2379 func TestUDP4AddrValidation(t *testing.T) {
2380         tests := []struct {
2381                 param    string
2382                 expected bool
2383         }{
2384                 {"", false},
2385                 {":80", false},
2386                 {"127.0.0.1:80", true},
2387                 {"[::1]:80", false}, // https://github.com/golang/go/issues/14037
2388                 {"256.0.0.0:1", false},
2389                 {"[::1]", false},
2390         }
2391
2392         validate := New()
2393
2394         for i, test := range tests {
2395                 errs := validate.Var(test.param, "udp4_addr")
2396                 if test.expected {
2397                         if !IsEqual(errs, nil) {
2398                                 t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
2399                         }
2400                 } else {
2401                         if IsEqual(errs, nil) {
2402                                 t.Log(test.param, IsEqual(errs, nil))
2403                                 t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
2404                         } else {
2405                                 val := getError(errs, "", "")
2406                                 if val.Tag() != "udp4_addr" {
2407                                         t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
2408                                 }
2409                         }
2410                 }
2411         }
2412 }
2413
2414 func TestIPAddrValidation(t *testing.T) {
2415         tests := []struct {
2416                 param    string
2417                 expected bool
2418         }{
2419                 {"", false},
2420                 {"127.0.0.1", true},
2421                 {"127.0.0.1:80", false},
2422                 {"::1", true},
2423                 {"256.0.0.0", false},
2424                 {"localhost", false},
2425         }
2426
2427         validate := New()
2428
2429         for i, test := range tests {
2430                 errs := validate.Var(test.param, "ip_addr")
2431                 if test.expected {
2432                         if !IsEqual(errs, nil) {
2433                                 t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
2434                         }
2435                 } else {
2436                         if IsEqual(errs, nil) {
2437                                 t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
2438                         } else {
2439                                 val := getError(errs, "", "")
2440                                 if val.Tag() != "ip_addr" {
2441                                         t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
2442                                 }
2443                         }
2444                 }
2445         }
2446 }
2447
2448 func TestIP6AddrValidation(t *testing.T) {
2449         tests := []struct {
2450                 param    string
2451                 expected bool
2452         }{
2453                 {"", false},
2454                 {"127.0.0.1", false}, // https://github.com/golang/go/issues/14037
2455                 {"127.0.0.1:80", false},
2456                 {"::1", true},
2457                 {"0:0:0:0:0:0:0:1", true},
2458                 {"256.0.0.0", false},
2459         }
2460
2461         validate := New()
2462
2463         for i, test := range tests {
2464                 errs := validate.Var(test.param, "ip6_addr")
2465                 if test.expected {
2466                         if !IsEqual(errs, nil) {
2467                                 t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
2468                         }
2469                 } else {
2470                         if IsEqual(errs, nil) {
2471                                 t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
2472                         } else {
2473                                 val := getError(errs, "", "")
2474                                 if val.Tag() != "ip6_addr" {
2475                                         t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
2476                                 }
2477                         }
2478                 }
2479         }
2480 }
2481
2482 func TestIP4AddrValidation(t *testing.T) {
2483         tests := []struct {
2484                 param    string
2485                 expected bool
2486         }{
2487                 {"", false},
2488                 {"127.0.0.1", true},
2489                 {"127.0.0.1:80", false},
2490                 {"::1", false}, // https://github.com/golang/go/issues/14037
2491                 {"256.0.0.0", false},
2492                 {"localhost", false},
2493         }
2494
2495         validate := New()
2496
2497         for i, test := range tests {
2498                 errs := validate.Var(test.param, "ip4_addr")
2499                 if test.expected {
2500                         if !IsEqual(errs, nil) {
2501                                 t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
2502                         }
2503                 } else {
2504                         if IsEqual(errs, nil) {
2505                                 t.Log(test.param, IsEqual(errs, nil))
2506                                 t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
2507                         } else {
2508                                 val := getError(errs, "", "")
2509                                 if val.Tag() != "ip4_addr" {
2510                                         t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
2511                                 }
2512                         }
2513                 }
2514         }
2515 }
2516
2517 func TestUnixAddrValidation(t *testing.T) {
2518         tests := []struct {
2519                 param    string
2520                 expected bool
2521         }{
2522                 {"", true},
2523                 {"v.sock", true},
2524         }
2525
2526         validate := New()
2527
2528         for i, test := range tests {
2529                 errs := validate.Var(test.param, "unix_addr")
2530                 if test.expected {
2531                         if !IsEqual(errs, nil) {
2532                                 t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
2533                         }
2534                 } else {
2535                         if IsEqual(errs, nil) {
2536                                 t.Log(test.param, IsEqual(errs, nil))
2537                                 t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
2538                         } else {
2539                                 val := getError(errs, "", "")
2540                                 if val.Tag() != "unix_addr" {
2541                                         t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
2542                                 }
2543                         }
2544                 }
2545         }
2546 }
2547
2548 func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {
2549
2550         validate := New()
2551
2552         var m map[string]string
2553
2554         errs := validate.Var(m, "required")
2555         NotEqual(t, errs, nil)
2556         AssertError(t, errs, "", "", "", "", "required")
2557
2558         m = map[string]string{}
2559         errs = validate.Var(m, "required")
2560         Equal(t, errs, nil)
2561
2562         var arr [5]string
2563         errs = validate.Var(arr, "required")
2564         NotEqual(t, errs, nil)
2565         AssertError(t, errs, "", "", "", "", "required")
2566
2567         arr[0] = "ok"
2568         errs = validate.Var(arr, "required")
2569         Equal(t, errs, nil)
2570
2571         var s []string
2572         errs = validate.Var(s, "required")
2573         NotEqual(t, errs, nil)
2574         AssertError(t, errs, "", "", "", "", "required")
2575
2576         s = []string{}
2577         errs = validate.Var(s, "required")
2578         Equal(t, errs, nil)
2579
2580         var c chan string
2581         errs = validate.Var(c, "required")
2582         NotEqual(t, errs, nil)
2583         AssertError(t, errs, "", "", "", "", "required")
2584
2585         c = make(chan string)
2586         errs = validate.Var(c, "required")
2587         Equal(t, errs, nil)
2588
2589         var tst *int
2590         errs = validate.Var(tst, "required")
2591         NotEqual(t, errs, nil)
2592         AssertError(t, errs, "", "", "", "", "required")
2593
2594         one := 1
2595         tst = &one
2596         errs = validate.Var(tst, "required")
2597         Equal(t, errs, nil)
2598
2599         var iface interface{}
2600
2601         errs = validate.Var(iface, "required")
2602         NotEqual(t, errs, nil)
2603         AssertError(t, errs, "", "", "", "", "required")
2604
2605         errs = validate.Var(iface, "omitempty,required")
2606         Equal(t, errs, nil)
2607
2608         errs = validate.Var(iface, "")
2609         Equal(t, errs, nil)
2610
2611         errs = validate.VarWithValue(nil, iface, "")
2612         Equal(t, errs, nil)
2613
2614         var f func(string)
2615
2616         errs = validate.Var(f, "required")
2617         NotEqual(t, errs, nil)
2618         AssertError(t, errs, "", "", "", "", "required")
2619
2620         f = func(name string) {}
2621
2622         errs = validate.Var(f, "required")
2623         Equal(t, errs, nil)
2624 }
2625
2626 func TestDatePtrValidationIssueValidation(t *testing.T) {
2627
2628         type Test struct {
2629                 LastViewed *time.Time
2630                 Reminder   *time.Time
2631         }
2632
2633         test := &Test{}
2634
2635         validate := New()
2636         errs := validate.Struct(test)
2637         Equal(t, errs, nil)
2638 }
2639
2640 func TestCommaAndPipeObfuscationValidation(t *testing.T) {
2641         s := "My Name Is, |joeybloggs|"
2642
2643         validate := New()
2644
2645         errs := validate.Var(s, "excludesall=0x2C")
2646         NotEqual(t, errs, nil)
2647         AssertError(t, errs, "", "", "", "", "excludesall")
2648
2649         errs = validate.Var(s, "excludesall=0x7C")
2650         NotEqual(t, errs, nil)
2651         AssertError(t, errs, "", "", "", "", "excludesall")
2652 }
2653
2654 func TestBadKeyValidation(t *testing.T) {
2655         type Test struct {
2656                 Name string `validate:"required, "`
2657         }
2658
2659         tst := &Test{
2660                 Name: "test",
2661         }
2662
2663         validate := New()
2664
2665         PanicMatches(t, func() { validate.Struct(tst) }, "Undefined validation function ' ' on field 'Name'")
2666
2667         type Test2 struct {
2668                 Name string `validate:"required,,len=2"`
2669         }
2670
2671         tst2 := &Test2{
2672                 Name: "test",
2673         }
2674
2675         PanicMatches(t, func() { validate.Struct(tst2) }, "Invalid validation tag on field 'Name'")
2676 }
2677
2678 func TestInterfaceErrValidation(t *testing.T) {
2679
2680         var v1 interface{}
2681         var v2 interface{}
2682
2683         v2 = 1
2684         v1 = v2
2685
2686         validate := New()
2687         errs := validate.Var(v1, "len=1")
2688         Equal(t, errs, nil)
2689
2690         errs = validate.Var(v2, "len=1")
2691         Equal(t, errs, nil)
2692
2693         type ExternalCMD struct {
2694                 Userid string      `json:"userid"`
2695                 Action uint32      `json:"action"`
2696                 Data   interface{} `json:"data,omitempty" validate:"required"`
2697         }
2698
2699         s := &ExternalCMD{
2700                 Userid: "123456",
2701                 Action: 10000,
2702                 // Data:   1,
2703         }
2704
2705         errs = validate.Struct(s)
2706         NotEqual(t, errs, nil)
2707         Equal(t, len(errs.(ValidationErrors)), 1)
2708         AssertError(t, errs, "ExternalCMD.Data", "ExternalCMD.Data", "Data", "Data", "required")
2709
2710         type ExternalCMD2 struct {
2711                 Userid string      `json:"userid"`
2712                 Action uint32      `json:"action"`
2713                 Data   interface{} `json:"data,omitempty" validate:"len=1"`
2714         }
2715
2716         s2 := &ExternalCMD2{
2717                 Userid: "123456",
2718                 Action: 10000,
2719                 // Data:   1,
2720         }
2721
2722         errs = validate.Struct(s2)
2723         NotEqual(t, errs, nil)
2724         Equal(t, len(errs.(ValidationErrors)), 1)
2725         AssertError(t, errs, "ExternalCMD2.Data", "ExternalCMD2.Data", "Data", "Data", "len")
2726
2727         s3 := &ExternalCMD2{
2728                 Userid: "123456",
2729                 Action: 10000,
2730                 Data:   2,
2731         }
2732
2733         errs = validate.Struct(s3)
2734         NotEqual(t, errs, nil)
2735         Equal(t, len(errs.(ValidationErrors)), 1)
2736         AssertError(t, errs, "ExternalCMD2.Data", "ExternalCMD2.Data", "Data", "Data", "len")
2737
2738         type Inner struct {
2739                 Name string `validate:"required"`
2740         }
2741
2742         inner := &Inner{
2743                 Name: "",
2744         }
2745
2746         s4 := &ExternalCMD{
2747                 Userid: "123456",
2748                 Action: 10000,
2749                 Data:   inner,
2750         }
2751
2752         errs = validate.Struct(s4)
2753         NotEqual(t, errs, nil)
2754         Equal(t, len(errs.(ValidationErrors)), 1)
2755         AssertError(t, errs, "ExternalCMD.Data.Name", "ExternalCMD.Data.Name", "Name", "Name", "required")
2756
2757         type TestMapStructPtr struct {
2758                 Errs map[int]interface{} `validate:"gt=0,dive,len=2"`
2759         }
2760
2761         mip := map[int]interface{}{0: &Inner{"ok"}, 3: nil, 4: &Inner{"ok"}}
2762
2763         msp := &TestMapStructPtr{
2764                 Errs: mip,
2765         }
2766
2767         errs = validate.Struct(msp)
2768         NotEqual(t, errs, nil)
2769         Equal(t, len(errs.(ValidationErrors)), 1)
2770         AssertError(t, errs, "TestMapStructPtr.Errs[3]", "TestMapStructPtr.Errs[3]", "Errs[3]", "Errs[3]", "len")
2771
2772         type TestMultiDimensionalStructs struct {
2773                 Errs [][]interface{} `validate:"gt=0,dive,dive"`
2774         }
2775
2776         var errStructArray [][]interface{}
2777
2778         errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
2779         errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
2780
2781         tms := &TestMultiDimensionalStructs{
2782                 Errs: errStructArray,
2783         }
2784
2785         errs = validate.Struct(tms)
2786         NotEqual(t, errs, nil)
2787         Equal(t, len(errs.(ValidationErrors)), 4)
2788         AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "Name", "required")
2789         AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "Name", "required")
2790         AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "Name", "required")
2791         AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "Name", "required")
2792
2793         type TestMultiDimensionalStructsPtr2 struct {
2794                 Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
2795         }
2796
2797         var errStructPtr2Array [][]*Inner
2798
2799         errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
2800         errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
2801         errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
2802
2803         tmsp2 := &TestMultiDimensionalStructsPtr2{
2804                 Errs: errStructPtr2Array,
2805         }
2806
2807         errs = validate.Struct(tmsp2)
2808         NotEqual(t, errs, nil)
2809         Equal(t, len(errs.(ValidationErrors)), 6)
2810         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "Name", "required")
2811         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "Name", "required")
2812         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "Name", "required")
2813         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "Name", "required")
2814         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "Name", "required")
2815         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required")
2816
2817         m := map[int]interface{}{0: "ok", 3: "", 4: "ok"}
2818
2819         errs = validate.Var(m, "len=3,dive,len=2")
2820         NotEqual(t, errs, nil)
2821         Equal(t, len(errs.(ValidationErrors)), 1)
2822         AssertError(t, errs, "[3]", "[3]", "[3]", "[3]", "len")
2823
2824         errs = validate.Var(m, "len=2,dive,required")
2825         NotEqual(t, errs, nil)
2826         Equal(t, len(errs.(ValidationErrors)), 1)
2827         AssertError(t, errs, "", "", "", "", "len")
2828
2829         arr := []interface{}{"ok", "", "ok"}
2830
2831         errs = validate.Var(arr, "len=3,dive,len=2")
2832         NotEqual(t, errs, nil)
2833         Equal(t, len(errs.(ValidationErrors)), 1)
2834         AssertError(t, errs, "[1]", "[1]", "[1]", "[1]", "len")
2835
2836         errs = validate.Var(arr, "len=2,dive,required")
2837         NotEqual(t, errs, nil)
2838         Equal(t, len(errs.(ValidationErrors)), 1)
2839         AssertError(t, errs, "", "", "", "", "len")
2840
2841         type MyStruct struct {
2842                 A, B string
2843                 C    interface{}
2844         }
2845
2846         var a MyStruct
2847
2848         a.A = "value"
2849         a.C = "nu"
2850
2851         errs = validate.Struct(a)
2852         Equal(t, errs, nil)
2853 }
2854
2855 func TestMapDiveValidation(t *testing.T) {
2856
2857         validate := New()
2858
2859         n := map[int]interface{}{0: nil}
2860         errs := validate.Var(n, "omitempty,required")
2861         Equal(t, errs, nil)
2862
2863         m := map[int]string{0: "ok", 3: "", 4: "ok"}
2864
2865         errs = validate.Var(m, "len=3,dive,required")
2866         NotEqual(t, errs, nil)
2867         Equal(t, len(errs.(ValidationErrors)), 1)
2868         AssertError(t, errs, "[3]", "[3]", "[3]", "[3]", "required")
2869
2870         errs = validate.Var(m, "len=2,dive,required")
2871         NotEqual(t, errs, nil)
2872         Equal(t, len(errs.(ValidationErrors)), 1)
2873         AssertError(t, errs, "", "", "", "", "len")
2874
2875         type Inner struct {
2876                 Name string `validate:"required"`
2877         }
2878
2879         type TestMapStruct struct {
2880                 Errs map[int]Inner `validate:"gt=0,dive"`
2881         }
2882
2883         mi := map[int]Inner{0: {"ok"}, 3: {""}, 4: {"ok"}}
2884
2885         ms := &TestMapStruct{
2886                 Errs: mi,
2887         }
2888
2889         errs = validate.Struct(ms)
2890         NotEqual(t, errs, nil)
2891         Equal(t, len(errs.(ValidationErrors)), 1)
2892         AssertError(t, errs, "TestMapStruct.Errs[3].Name", "TestMapStruct.Errs[3].Name", "Name", "Name", "required")
2893
2894         // for full test coverage
2895         s := fmt.Sprint(errs.Error())
2896         NotEqual(t, s, "")
2897
2898         type TestMapTimeStruct struct {
2899                 Errs map[int]*time.Time `validate:"gt=0,dive,required"`
2900         }
2901
2902         t1 := time.Now().UTC()
2903
2904         mta := map[int]*time.Time{0: &t1, 3: nil, 4: nil}
2905
2906         mt := &TestMapTimeStruct{
2907                 Errs: mta,
2908         }
2909
2910         errs = validate.Struct(mt)
2911         NotEqual(t, errs, nil)
2912         Equal(t, len(errs.(ValidationErrors)), 2)
2913         AssertError(t, errs, "TestMapTimeStruct.Errs[3]", "TestMapTimeStruct.Errs[3]", "Errs[3]", "Errs[3]", "required")
2914         AssertError(t, errs, "TestMapTimeStruct.Errs[4]", "TestMapTimeStruct.Errs[4]", "Errs[4]", "Errs[4]", "required")
2915
2916         type TestMapStructPtr struct {
2917                 Errs map[int]*Inner `validate:"gt=0,dive,required"`
2918         }
2919
2920         mip := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
2921
2922         msp := &TestMapStructPtr{
2923                 Errs: mip,
2924         }
2925
2926         errs = validate.Struct(msp)
2927         NotEqual(t, errs, nil)
2928         Equal(t, len(errs.(ValidationErrors)), 1)
2929         AssertError(t, errs, "TestMapStructPtr.Errs[3]", "TestMapStructPtr.Errs[3]", "Errs[3]", "Errs[3]", "required")
2930
2931         type TestMapStructPtr2 struct {
2932                 Errs map[int]*Inner `validate:"gt=0,dive,omitempty,required"`
2933         }
2934
2935         mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
2936
2937         msp2 := &TestMapStructPtr2{
2938                 Errs: mip2,
2939         }
2940
2941         errs = validate.Struct(msp2)
2942         Equal(t, errs, nil)
2943
2944         v2 := New()
2945         v2.RegisterTagNameFunc(func(fld reflect.StructField) string {
2946                 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
2947
2948                 if name == "-" {
2949                         return ""
2950                 }
2951
2952                 return name
2953         })
2954
2955         type MapDiveJSONTest struct {
2956                 Map map[string]string `validate:"required,gte=1,dive,gte=1" json:"MyName"`
2957         }
2958
2959         mdjt := &MapDiveJSONTest{
2960                 Map: map[string]string{
2961                         "Key1": "Value1",
2962                         "Key2": "",
2963                 },
2964         }
2965
2966         err := v2.Struct(mdjt)
2967         NotEqual(t, err, nil)
2968
2969         errs = err.(ValidationErrors)
2970         fe := getError(errs, "MapDiveJSONTest.MyName[Key2]", "MapDiveJSONTest.Map[Key2]")
2971         NotEqual(t, fe, nil)
2972         Equal(t, fe.Tag(), "gte")
2973         Equal(t, fe.ActualTag(), "gte")
2974         Equal(t, fe.Field(), "MyName[Key2]")
2975         Equal(t, fe.StructField(), "Map[Key2]")
2976 }
2977
2978 func TestArrayDiveValidation(t *testing.T) {
2979
2980         validate := New()
2981
2982         arr := []string{"ok", "", "ok"}
2983
2984         errs := validate.Var(arr, "len=3,dive,required")
2985         NotEqual(t, errs, nil)
2986         Equal(t, len(errs.(ValidationErrors)), 1)
2987         AssertError(t, errs, "[1]", "[1]", "[1]", "[1]", "required")
2988
2989         errs = validate.Var(arr, "len=2,dive,required")
2990         NotEqual(t, errs, nil)
2991         Equal(t, len(errs.(ValidationErrors)), 1)
2992         AssertError(t, errs, "", "", "", "", "len")
2993
2994         type BadDive struct {
2995                 Name string `validate:"dive"`
2996         }
2997
2998         bd := &BadDive{
2999                 Name: "TEST",
3000         }
3001
3002         PanicMatches(t, func() { validate.Struct(bd) }, "dive error! can't dive on a non slice or map")
3003
3004         type Test struct {
3005                 Errs []string `validate:"gt=0,dive,required"`
3006         }
3007
3008         test := &Test{
3009                 Errs: []string{"ok", "", "ok"},
3010         }
3011
3012         errs = validate.Struct(test)
3013         NotEqual(t, errs, nil)
3014         Equal(t, len(errs.(ValidationErrors)), 1)
3015         AssertError(t, errs, "Test.Errs[1]", "Test.Errs[1]", "Errs[1]", "Errs[1]", "required")
3016
3017         test = &Test{
3018                 Errs: []string{"ok", "ok", ""},
3019         }
3020
3021         errs = validate.Struct(test)
3022         NotEqual(t, errs, nil)
3023         Equal(t, len(errs.(ValidationErrors)), 1)
3024         AssertError(t, errs, "Test.Errs[2]", "Test.Errs[2]", "Errs[2]", "Errs[2]", "required")
3025
3026         type TestMultiDimensional struct {
3027                 Errs [][]string `validate:"gt=0,dive,dive,required"`
3028         }
3029
3030         var errArray [][]string
3031
3032         errArray = append(errArray, []string{"ok", "", ""})
3033         errArray = append(errArray, []string{"ok", "", ""})
3034
3035         tm := &TestMultiDimensional{
3036                 Errs: errArray,
3037         }
3038
3039         errs = validate.Struct(tm)
3040         NotEqual(t, errs, nil)
3041         Equal(t, len(errs.(ValidationErrors)), 4)
3042         AssertError(t, errs, "TestMultiDimensional.Errs[0][1]", "TestMultiDimensional.Errs[0][1]", "Errs[0][1]", "Errs[0][1]", "required")
3043         AssertError(t, errs, "TestMultiDimensional.Errs[0][2]", "TestMultiDimensional.Errs[0][2]", "Errs[0][2]", "Errs[0][2]", "required")
3044         AssertError(t, errs, "TestMultiDimensional.Errs[1][1]", "TestMultiDimensional.Errs[1][1]", "Errs[1][1]", "Errs[1][1]", "required")
3045         AssertError(t, errs, "TestMultiDimensional.Errs[1][2]", "TestMultiDimensional.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required")
3046
3047         type Inner struct {
3048                 Name string `validate:"required"`
3049         }
3050
3051         type TestMultiDimensionalStructs struct {
3052                 Errs [][]Inner `validate:"gt=0,dive,dive"`
3053         }
3054
3055         var errStructArray [][]Inner
3056
3057         errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
3058         errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
3059
3060         tms := &TestMultiDimensionalStructs{
3061                 Errs: errStructArray,
3062         }
3063
3064         errs = validate.Struct(tms)
3065         NotEqual(t, errs, nil)
3066         Equal(t, len(errs.(ValidationErrors)), 4)
3067         AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "Name", "required")
3068         AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "Name", "required")
3069         AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "Name", "required")
3070         AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "Name", "required")
3071
3072         type TestMultiDimensionalStructsPtr struct {
3073                 Errs [][]*Inner `validate:"gt=0,dive,dive"`
3074         }
3075
3076         var errStructPtrArray [][]*Inner
3077
3078         errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
3079         errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
3080         errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, nil})
3081
3082         tmsp := &TestMultiDimensionalStructsPtr{
3083                 Errs: errStructPtrArray,
3084         }
3085
3086         errs = validate.Struct(tmsp)
3087         NotEqual(t, errs, nil)
3088         Equal(t, len(errs.(ValidationErrors)), 5)
3089         AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][1].Name", "TestMultiDimensionalStructsPtr.Errs[0][1].Name", "Name", "Name", "required")
3090         AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "Name", "Name", "required")
3091         AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "Name", "Name", "required")
3092         AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "Name", "Name", "required")
3093         AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[2][1].Name", "TestMultiDimensionalStructsPtr.Errs[2][1].Name", "Name", "Name", "required")
3094
3095         // for full test coverage
3096         s := fmt.Sprint(errs.Error())
3097         NotEqual(t, s, "")
3098
3099         type TestMultiDimensionalStructsPtr2 struct {
3100                 Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
3101         }
3102
3103         var errStructPtr2Array [][]*Inner
3104
3105         errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
3106         errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
3107         errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
3108
3109         tmsp2 := &TestMultiDimensionalStructsPtr2{
3110                 Errs: errStructPtr2Array,
3111         }
3112
3113         errs = validate.Struct(tmsp2)
3114         NotEqual(t, errs, nil)
3115         Equal(t, len(errs.(ValidationErrors)), 6)
3116         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "Name", "required")
3117         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "Name", "required")
3118         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "Name", "required")
3119         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "Name", "required")
3120         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "Name", "required")
3121         AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required")
3122
3123         type TestMultiDimensionalStructsPtr3 struct {
3124                 Errs [][]*Inner `validate:"gt=0,dive,dive,omitempty"`
3125         }
3126
3127         var errStructPtr3Array [][]*Inner
3128
3129         errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
3130         errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
3131         errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, nil})
3132
3133         tmsp3 := &TestMultiDimensionalStructsPtr3{
3134                 Errs: errStructPtr3Array,
3135         }
3136
3137         errs = validate.Struct(tmsp3)
3138         NotEqual(t, errs, nil)
3139         Equal(t, len(errs.(ValidationErrors)), 5)
3140         AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][1].Name", "TestMultiDimensionalStructsPtr3.Errs[0][1].Name", "Name", "Name", "required")
3141         AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "Name", "Name", "required")
3142         AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "Name", "Name", "required")
3143         AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "Name", "Name", "required")
3144         AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[2][1].Name", "TestMultiDimensionalStructsPtr3.Errs[2][1].Name", "Name", "Name", "required")
3145
3146         type TestMultiDimensionalTimeTime struct {
3147                 Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
3148         }
3149
3150         var errTimePtr3Array [][]*time.Time
3151
3152         t1 := time.Now().UTC()
3153         t2 := time.Now().UTC()
3154         t3 := time.Now().UTC().Add(time.Hour * 24)
3155
3156         errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, &t3})
3157         errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, nil})
3158         errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, nil, nil})
3159
3160         tmtp3 := &TestMultiDimensionalTimeTime{
3161                 Errs: errTimePtr3Array,
3162         }
3163
3164         errs = validate.Struct(tmtp3)
3165         NotEqual(t, errs, nil)
3166         Equal(t, len(errs.(ValidationErrors)), 3)
3167         AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[1][2]", "TestMultiDimensionalTimeTime.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required")
3168         AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][1]", "TestMultiDimensionalTimeTime.Errs[2][1]", "Errs[2][1]", "Errs[2][1]", "required")
3169         AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][2]", "TestMultiDimensionalTimeTime.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required")
3170
3171         type TestMultiDimensionalTimeTime2 struct {
3172                 Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
3173         }
3174
3175         var errTimeArray [][]*time.Time
3176
3177         t1 = time.Now().UTC()
3178         t2 = time.Now().UTC()
3179         t3 = time.Now().UTC().Add(time.Hour * 24)
3180
3181         errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, &t3})
3182         errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, nil})
3183         errTimeArray = append(errTimeArray, []*time.Time{&t1, nil, nil})
3184
3185         tmtp := &TestMultiDimensionalTimeTime2{
3186                 Errs: errTimeArray,
3187         }
3188
3189         errs = validate.Struct(tmtp)
3190         NotEqual(t, errs, nil)
3191         Equal(t, len(errs.(ValidationErrors)), 3)
3192         AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[1][2]", "TestMultiDimensionalTimeTime2.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required")
3193         AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][1]", "TestMultiDimensionalTimeTime2.Errs[2][1]", "Errs[2][1]", "Errs[2][1]", "required")
3194         AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][2]", "TestMultiDimensionalTimeTime2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required")
3195 }
3196
3197 func TestNilStructPointerValidation(t *testing.T) {
3198         type Inner struct {
3199                 Data string
3200         }
3201
3202         type Outer struct {
3203                 Inner *Inner `validate:"omitempty"`
3204         }
3205
3206         inner := &Inner{
3207                 Data: "test",
3208         }
3209
3210         outer := &Outer{
3211                 Inner: inner,
3212         }
3213
3214         validate := New()
3215         errs := validate.Struct(outer)
3216         Equal(t, errs, nil)
3217
3218         outer = &Outer{
3219                 Inner: nil,
3220         }
3221
3222         errs = validate.Struct(outer)
3223         Equal(t, errs, nil)
3224
3225         type Inner2 struct {
3226                 Data string
3227         }
3228
3229         type Outer2 struct {
3230                 Inner2 *Inner2 `validate:"required"`
3231         }
3232
3233         inner2 := &Inner2{
3234                 Data: "test",
3235         }
3236
3237         outer2 := &Outer2{
3238                 Inner2: inner2,
3239         }
3240
3241         errs = validate.Struct(outer2)
3242         Equal(t, errs, nil)
3243
3244         outer2 = &Outer2{
3245                 Inner2: nil,
3246         }
3247
3248         errs = validate.Struct(outer2)
3249         NotEqual(t, errs, nil)
3250         AssertError(t, errs, "Outer2.Inner2", "Outer2.Inner2", "Inner2", "Inner2", "required")
3251
3252         type Inner3 struct {
3253                 Data string
3254         }
3255
3256         type Outer3 struct {
3257                 Inner3 *Inner3
3258         }
3259
3260         inner3 := &Inner3{
3261                 Data: "test",
3262         }
3263
3264         outer3 := &Outer3{
3265                 Inner3: inner3,
3266         }
3267
3268         errs = validate.Struct(outer3)
3269         Equal(t, errs, nil)
3270
3271         type Inner4 struct {
3272                 Data string
3273         }
3274
3275         type Outer4 struct {
3276                 Inner4 *Inner4 `validate:"-"`
3277         }
3278
3279         inner4 := &Inner4{
3280                 Data: "test",
3281         }
3282
3283         outer4 := &Outer4{
3284                 Inner4: inner4,
3285         }
3286
3287         errs = validate.Struct(outer4)
3288         Equal(t, errs, nil)
3289 }
3290
3291 func TestSSNValidation(t *testing.T) {
3292         tests := []struct {
3293                 param    string
3294                 expected bool
3295         }{
3296                 {"", false},
3297                 {"00-90-8787", false},
3298                 {"66690-76", false},
3299                 {"191 60 2869", true},
3300                 {"191-60-2869", true},
3301         }
3302
3303         validate := New()
3304
3305         for i, test := range tests {
3306
3307                 errs := validate.Var(test.param, "ssn")
3308
3309                 if test.expected {
3310                         if !IsEqual(errs, nil) {
3311                                 t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
3312                         }
3313                 } else {
3314                         if IsEqual(errs, nil) {
3315                                 t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
3316                         } else {
3317                                 val := getError(errs, "", "")
3318                                 if val.Tag() != "ssn" {
3319                                         t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
3320                                 }
3321                         }
3322                 }
3323         }
3324 }
3325
3326 func TestLongitudeValidation(t *testing.T) {
3327         tests := []struct {
3328                 param    string
3329                 expected bool
3330         }{
3331                 {"", false},
3332                 {"-180.000", true},
3333                 {"180.1", false},
3334                 {"+73.234", true},
3335                 {"+382.3811", false},
3336                 {"23.11111111", true},
3337         }
3338
3339         validate := New()
3340
3341         for i, test := range tests {
3342
3343                 errs := validate.Var(test.param, "longitude")
3344
3345                 if test.expected {
3346                         if !IsEqual(errs, nil) {
3347                                 t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
3348                         }
3349                 } else {
3350                         if IsEqual(errs, nil) {
3351                                 t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
3352                         } else {
3353                                 val := getError(errs, "", "")
3354                                 if val.Tag() != "longitude" {
3355                                         t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
3356                                 }
3357                         }
3358                 }
3359         }
3360 }
3361
3362 func TestLatitudeValidation(t *testing.T) {
3363         tests := []struct {
3364                 param    string
3365                 expected bool
3366         }{
3367                 {"", false},
3368                 {"-90.000", true},
3369                 {"+90", true},
3370                 {"47.1231231", true},
3371                 {"+99.9", false},
3372                 {"108", false},
3373         }
3374
3375         validate := New()
3376
3377         for i, test := range tests {
3378
3379                 errs := validate.Var(test.param, "latitude")
3380
3381                 if test.expected {
3382                         if !IsEqual(errs, nil) {
3383                                 t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
3384                         }
3385                 } else {
3386                         if IsEqual(errs, nil) {
3387                                 t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
3388                         } else {
3389                                 val := getError(errs, "", "")
3390                                 if val.Tag() != "latitude" {
3391                                         t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
3392                                 }
3393                         }
3394                 }
3395         }
3396 }
3397
3398 func TestDataURIValidation(t *testing.T) {
3399         tests := []struct {
3400                 param    string
3401                 expected bool
3402         }{
3403                 {"data:image/png;base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true},
3404                 {"data:text/plain;base64,Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true},
3405                 {"image/gif;base64,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
3406                 {"data:image/gif;base64,MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" +
3407                         "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" +
3408                         "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" +
3409                         "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" +
3410                         "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" +
3411                         "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true},
3412                 {"data:image/png;base64,12345", false},
3413                 {"", false},
3414                 {"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
3415         }
3416
3417         validate := New()
3418
3419         for i, test := range tests {
3420
3421                 errs := validate.Var(test.param, "datauri")
3422
3423                 if test.expected {
3424                         if !IsEqual(errs, nil) {
3425                                 t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
3426                         }
3427                 } else {
3428                         if IsEqual(errs, nil) {
3429                                 t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
3430                         } else {
3431                                 val := getError(errs, "", "")
3432                                 if val.Tag() != "datauri" {
3433                                         t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
3434                                 }
3435                         }
3436                 }
3437         }
3438 }
3439
3440 func TestMultibyteValidation(t *testing.T) {
3441         tests := []struct {
3442                 param    string
3443                 expected bool
3444         }{
3445                 {"", true},
3446                 {"abc", false},
3447                 {"123", false},
3448                 {"<>@;.-=", false},
3449                 {"ひらがな・カタカナ、.漢字", true},
3450                 {"あいうえお foobar", true},
3451                 {"test@example.com", true},
3452                 {"test@example.com", true},
3453                 {"1234abcDExyz", true},
3454                 {"カタカナ", true},
3455         }
3456
3457         validate := New()
3458
3459         for i, test := range tests {
3460
3461                 errs := validate.Var(test.param, "multibyte")
3462
3463                 if test.expected {
3464                         if !IsEqual(errs, nil) {
3465                                 t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
3466                         }
3467                 } else {
3468                         if IsEqual(errs, nil) {
3469                                 t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
3470                         } else {
3471                                 val := getError(errs, "", "")
3472                                 if val.Tag() != "multibyte" {
3473                                         t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
3474                                 }
3475                         }
3476                 }
3477         }
3478 }
3479
3480 func TestPrintableASCIIValidation(t *testing.T) {
3481         tests := []struct {
3482                 param    string
3483                 expected bool
3484         }{
3485                 {"", true},
3486                 {"foobar", false},
3487                 {"xyz098", false},
3488                 {"123456", false},
3489                 {"カタカナ", false},
3490                 {"foobar", true},
3491                 {"0987654321", true},
3492                 {"test@example.com", true},
3493                 {"1234abcDEF", true},
3494                 {"newline\n", false},
3495                 {"\x19test\x7F", false},
3496         }
3497
3498         validate := New()
3499
3500         for i, test := range tests {
3501
3502                 errs := validate.Var(test.param, "printascii")
3503
3504                 if test.expected {
3505                         if !IsEqual(errs, nil) {
3506                                 t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
3507                         }
3508                 } else {
3509                         if IsEqual(errs, nil) {
3510                                 t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
3511                         } else {
3512                                 val := getError(errs, "", "")
3513                                 if val.Tag() != "printascii" {
3514                                         t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
3515                                 }
3516                         }
3517                 }
3518         }
3519 }
3520
3521 func TestASCIIValidation(t *testing.T) {
3522         tests := []struct {
3523                 param    string
3524                 expected bool
3525         }{
3526                 {"", true},
3527                 {"foobar", false},
3528                 {"xyz098", false},
3529                 {"123456", false},
3530                 {"カタカナ", false},
3531                 {"foobar", true},
3532                 {"0987654321", true},
3533                 {"test@example.com", true},
3534                 {"1234abcDEF", true},
3535                 {"", true},
3536         }
3537
3538         validate := New()
3539
3540         for i, test := range tests {
3541
3542                 errs := validate.Var(test.param, "ascii")
3543
3544                 if test.expected {
3545                         if !IsEqual(errs, nil) {
3546                                 t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
3547                         }
3548                 } else {
3549                         if IsEqual(errs, nil) {
3550                                 t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
3551                         } else {
3552                                 val := getError(errs, "", "")
3553                                 if val.Tag() != "ascii" {
3554                                         t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
3555                                 }
3556                         }
3557                 }
3558         }
3559 }
3560
3561 func TestUUID5Validation(t *testing.T) {
3562         tests := []struct {
3563                 param    string
3564                 expected bool
3565         }{
3566
3567                 {"", false},
3568                 {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
3569                 {"9c858901-8a57-4791-81fe-4c455b099bc9", false},
3570                 {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
3571                 {"987fbc97-4bed-5078-af07-9141ba07c9f3", true},
3572                 {"987fbc97-4bed-5078-9f07-9141ba07c9f3", true},
3573         }
3574
3575         validate := New()
3576
3577         for i, test := range tests {
3578
3579                 errs := validate.Var(test.param, "uuid5")
3580
3581                 if test.expected {
3582                         if !IsEqual(errs, nil) {
3583                                 t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
3584                         }
3585                 } else {
3586                         if IsEqual(errs, nil) {
3587                                 t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
3588                         } else {
3589                                 val := getError(errs, "", "")
3590                                 if val.Tag() != "uuid5" {
3591                                         t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
3592                                 }
3593                         }
3594                 }
3595         }
3596 }
3597
3598 func TestUUID4Validation(t *testing.T) {
3599         tests := []struct {
3600                 param    string
3601                 expected bool
3602         }{
3603                 {"", false},
3604                 {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
3605                 {"a987fbc9-4bed-5078-af07-9141ba07c9f3", false},
3606                 {"934859", false},
3607                 {"57b73598-8764-4ad0-a76a-679bb6640eb1", true},
3608                 {"625e63f3-58f5-40b7-83a1-a72ad31acffb", true},
3609         }
3610
3611         validate := New()
3612
3613         for i, test := range tests {
3614
3615                 errs := validate.Var(test.param, "uuid4")
3616
3617                 if test.expected {
3618                         if !IsEqual(errs, nil) {
3619                                 t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
3620                         }
3621                 } else {
3622                         if IsEqual(errs, nil) {
3623                                 t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
3624                         } else {
3625                                 val := getError(errs, "", "")
3626                                 if val.Tag() != "uuid4" {
3627                                         t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
3628                                 }
3629                         }
3630                 }
3631         }
3632 }
3633
3634 func TestUUID3Validation(t *testing.T) {
3635         tests := []struct {
3636                 param    string
3637                 expected bool
3638         }{
3639                 {"", false},
3640                 {"412452646", false},
3641                 {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
3642                 {"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false},
3643                 {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
3644         }
3645
3646         validate := New()
3647
3648         for i, test := range tests {
3649
3650                 errs := validate.Var(test.param, "uuid3")
3651
3652                 if test.expected {
3653                         if !IsEqual(errs, nil) {
3654                                 t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
3655                         }
3656                 } else {
3657                         if IsEqual(errs, nil) {
3658                                 t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
3659                         } else {
3660                                 val := getError(errs, "", "")
3661                                 if val.Tag() != "uuid3" {
3662                                         t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
3663                                 }
3664                         }
3665                 }
3666         }
3667 }
3668
3669 func TestUUIDValidation(t *testing.T) {
3670         tests := []struct {
3671                 param    string
3672                 expected bool
3673         }{
3674                 {"", false},
3675                 {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
3676                 {"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false},
3677                 {"a987fbc94bed3078cf079141ba07c9f3", false},
3678                 {"934859", false},
3679                 {"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false},
3680                 {"aaaaaaaa-1111-1111-aaag-111111111111", false},
3681                 {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
3682         }
3683
3684         validate := New()
3685
3686         for i, test := range tests {
3687
3688                 errs := validate.Var(test.param, "uuid")
3689
3690                 if test.expected {
3691                         if !IsEqual(errs, nil) {
3692                                 t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
3693                         }
3694                 } else {
3695                         if IsEqual(errs, nil) {
3696                                 t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
3697                         } else {
3698                                 val := getError(errs, "", "")
3699                                 if val.Tag() != "uuid" {
3700                                         t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
3701                                 }
3702                         }
3703                 }
3704         }
3705 }
3706
3707 func TestISBNValidation(t *testing.T) {
3708         tests := []struct {
3709                 param    string
3710                 expected bool
3711         }{
3712                 {"", false},
3713                 {"foo", false},
3714                 {"3836221195", true},
3715                 {"1-61729-085-8", true},
3716                 {"3 423 21412 0", true},
3717                 {"3 401 01319 X", true},
3718                 {"9784873113685", true},
3719                 {"978-4-87311-368-5", true},
3720                 {"978 3401013190", true},
3721                 {"978-3-8362-2119-1", true},
3722         }
3723
3724         validate := New()
3725
3726         for i, test := range tests {
3727
3728                 errs := validate.Var(test.param, "isbn")
3729
3730                 if test.expected {
3731                         if !IsEqual(errs, nil) {
3732                                 t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
3733                         }
3734                 } else {
3735                         if IsEqual(errs, nil) {
3736                                 t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
3737                         } else {
3738                                 val := getError(errs, "", "")
3739                                 if val.Tag() != "isbn" {
3740                                         t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
3741                                 }
3742                         }
3743                 }
3744         }
3745 }
3746
3747 func TestISBN13Validation(t *testing.T) {
3748         tests := []struct {
3749                 param    string
3750                 expected bool
3751         }{
3752                 {"", false},
3753                 {"foo", false},
3754                 {"3-8362-2119-5", false},
3755                 {"01234567890ab", false},
3756                 {"978 3 8362 2119 0", false},
3757                 {"9784873113685", true},
3758                 {"978-4-87311-368-5", true},
3759                 {"978 3401013190", true},
3760                 {"978-3-8362-2119-1", true},
3761         }
3762
3763         validate := New()
3764
3765         for i, test := range tests {
3766
3767                 errs := validate.Var(test.param, "isbn13")
3768
3769                 if test.expected {
3770                         if !IsEqual(errs, nil) {
3771                                 t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
3772                         }
3773                 } else {
3774                         if IsEqual(errs, nil) {
3775                                 t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
3776                         } else {
3777                                 val := getError(errs, "", "")
3778                                 if val.Tag() != "isbn13" {
3779                                         t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
3780                                 }
3781                         }
3782                 }
3783         }
3784 }
3785
3786 func TestISBN10Validation(t *testing.T) {
3787         tests := []struct {
3788                 param    string
3789                 expected bool
3790         }{
3791                 {"", false},
3792                 {"foo", false},
3793                 {"3423214121", false},
3794                 {"978-3836221191", false},
3795                 {"3-423-21412-1", false},
3796                 {"3 423 21412 1", false},
3797                 {"3836221195", true},
3798                 {"1-61729-085-8", true},
3799                 {"3 423 21412 0", true},
3800                 {"3 401 01319 X", true},
3801         }
3802
3803         validate := New()
3804
3805         for i, test := range tests {
3806
3807                 errs := validate.Var(test.param, "isbn10")
3808
3809                 if test.expected {
3810                         if !IsEqual(errs, nil) {
3811                                 t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
3812                         }
3813                 } else {
3814                         if IsEqual(errs, nil) {
3815                                 t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
3816                         } else {
3817                                 val := getError(errs, "", "")
3818                                 if val.Tag() != "isbn10" {
3819                                         t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
3820                                 }
3821                         }
3822                 }
3823         }
3824 }
3825
3826 func TestExcludesRuneValidation(t *testing.T) {
3827
3828         tests := []struct {
3829                 Value       string `validate:"excludesrune=☻"`
3830                 Tag         string
3831                 ExpectedNil bool
3832         }{
3833                 {Value: "a☺b☻c☹d", Tag: "excludesrune=☻", ExpectedNil: false},
3834                 {Value: "abcd", Tag: "excludesrune=☻", ExpectedNil: true},
3835         }
3836
3837         validate := New()
3838
3839         for i, s := range tests {
3840                 errs := validate.Var(s.Value, s.Tag)
3841
3842                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3843                         t.Fatalf("Index: %d failed Error: %s", i, errs)
3844                 }
3845
3846                 errs = validate.Struct(s)
3847
3848                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3849                         t.Fatalf("Index: %d failed Error: %s", i, errs)
3850                 }
3851         }
3852 }
3853
3854 func TestExcludesAllValidation(t *testing.T) {
3855
3856         tests := []struct {
3857                 Value       string `validate:"excludesall=@!{}[]"`
3858                 Tag         string
3859                 ExpectedNil bool
3860         }{
3861                 {Value: "abcd@!jfk", Tag: "excludesall=@!{}[]", ExpectedNil: false},
3862                 {Value: "abcdefg", Tag: "excludesall=@!{}[]", ExpectedNil: true},
3863         }
3864
3865         validate := New()
3866
3867         for i, s := range tests {
3868                 errs := validate.Var(s.Value, s.Tag)
3869
3870                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3871                         t.Fatalf("Index: %d failed Error: %s", i, errs)
3872                 }
3873
3874                 errs = validate.Struct(s)
3875
3876                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3877                         t.Fatalf("Index: %d failed Error: %s", i, errs)
3878                 }
3879         }
3880
3881         username := "joeybloggs "
3882
3883         errs := validate.Var(username, "excludesall=@ ")
3884         NotEqual(t, errs, nil)
3885         AssertError(t, errs, "", "", "", "", "excludesall")
3886
3887         excluded := ","
3888
3889         errs = validate.Var(excluded, "excludesall=!@#$%^&*()_+.0x2C?")
3890         NotEqual(t, errs, nil)
3891         AssertError(t, errs, "", "", "", "", "excludesall")
3892
3893         excluded = "="
3894
3895         errs = validate.Var(excluded, "excludesall=!@#$%^&*()_+.0x2C=?")
3896         NotEqual(t, errs, nil)
3897         AssertError(t, errs, "", "", "", "", "excludesall")
3898 }
3899
3900 func TestExcludesValidation(t *testing.T) {
3901
3902         tests := []struct {
3903                 Value       string `validate:"excludes=@"`
3904                 Tag         string
3905                 ExpectedNil bool
3906         }{
3907                 {Value: "abcd@!jfk", Tag: "excludes=@", ExpectedNil: false},
3908                 {Value: "abcdq!jfk", Tag: "excludes=@", ExpectedNil: true},
3909         }
3910
3911         validate := New()
3912
3913         for i, s := range tests {
3914                 errs := validate.Var(s.Value, s.Tag)
3915
3916                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3917                         t.Fatalf("Index: %d failed Error: %s", i, errs)
3918                 }
3919
3920                 errs = validate.Struct(s)
3921
3922                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3923                         t.Fatalf("Index: %d failed Error: %s", i, errs)
3924                 }
3925         }
3926 }
3927
3928 func TestContainsRuneValidation(t *testing.T) {
3929
3930         tests := []struct {
3931                 Value       string `validate:"containsrune=☻"`
3932                 Tag         string
3933                 ExpectedNil bool
3934         }{
3935                 {Value: "a☺b☻c☹d", Tag: "containsrune=☻", ExpectedNil: true},
3936                 {Value: "abcd", Tag: "containsrune=☻", ExpectedNil: false},
3937         }
3938
3939         validate := New()
3940
3941         for i, s := range tests {
3942                 errs := validate.Var(s.Value, s.Tag)
3943
3944                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3945                         t.Fatalf("Index: %d failed Error: %s", i, errs)
3946                 }
3947
3948                 errs = validate.Struct(s)
3949
3950                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3951                         t.Fatalf("Index: %d failed Error: %s", i, errs)
3952                 }
3953         }
3954 }
3955
3956 func TestContainsAnyValidation(t *testing.T) {
3957
3958         tests := []struct {
3959                 Value       string `validate:"containsany=@!{}[]"`
3960                 Tag         string
3961                 ExpectedNil bool
3962         }{
3963                 {Value: "abcd@!jfk", Tag: "containsany=@!{}[]", ExpectedNil: true},
3964                 {Value: "abcdefg", Tag: "containsany=@!{}[]", ExpectedNil: false},
3965         }
3966
3967         validate := New()
3968
3969         for i, s := range tests {
3970                 errs := validate.Var(s.Value, s.Tag)
3971
3972                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3973                         t.Fatalf("Index: %d failed Error: %s", i, errs)
3974                 }
3975
3976                 errs = validate.Struct(s)
3977
3978                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3979                         t.Fatalf("Index: %d failed Error: %s", i, errs)
3980                 }
3981         }
3982 }
3983
3984 func TestContainsValidation(t *testing.T) {
3985
3986         tests := []struct {
3987                 Value       string `validate:"contains=@"`
3988                 Tag         string
3989                 ExpectedNil bool
3990         }{
3991                 {Value: "abcd@!jfk", Tag: "contains=@", ExpectedNil: true},
3992                 {Value: "abcdq!jfk", Tag: "contains=@", ExpectedNil: false},
3993         }
3994
3995         validate := New()
3996
3997         for i, s := range tests {
3998                 errs := validate.Var(s.Value, s.Tag)
3999
4000                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
4001                         t.Fatalf("Index: %d failed Error: %s", i, errs)
4002                 }
4003
4004                 errs = validate.Struct(s)
4005
4006                 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
4007                         t.Fatalf("Index: %d failed Error: %s", i, errs)
4008                 }
4009         }
4010 }
4011
4012 func TestIsNeFieldValidation(t *testing.T) {
4013
4014         validate := New()
4015
4016         var j uint64
4017         var k float64
4018         s := "abcd"
4019         i := 1
4020         j = 1
4021         k = 1.543
4022         arr := []string{"test"}
4023         now := time.Now().UTC()
4024
4025         var j2 uint64
4026         var k2 float64
4027         s2 := "abcdef"
4028         i2 := 3
4029         j2 = 2
4030         k2 = 1.5434456
4031         arr2 := []string{"test", "test2"}
4032         arr3 := []string{"test"}
4033         now2 := now
4034
4035         errs := validate.VarWithValue(s, s2, "nefield")
4036         Equal(t, errs, nil)
4037
4038         errs = validate.VarWithValue(i2, i, "nefield")
4039         Equal(t, errs, nil)
4040
4041         errs = validate.VarWithValue(j2, j, "nefield")
4042         Equal(t, errs, nil)
4043
4044         errs = validate.VarWithValue(k2, k, "nefield")
4045         Equal(t, errs, nil)
4046
4047         errs = validate.VarWithValue(arr2, arr, "nefield")
4048         Equal(t, errs, nil)
4049
4050         errs = validate.VarWithValue(now2, now, "nefield")
4051         NotEqual(t, errs, nil)
4052         AssertError(t, errs, "", "", "", "", "nefield")
4053
4054         errs = validate.VarWithValue(arr3, arr, "nefield")
4055         NotEqual(t, errs, nil)
4056         AssertError(t, errs, "", "", "", "", "nefield")
4057
4058         type Test struct {
4059                 Start *time.Time `validate:"nefield=End"`
4060                 End   *time.Time
4061         }
4062
4063         sv := &Test{
4064                 Start: &now,
4065                 End:   &now,
4066         }
4067
4068         errs = validate.Struct(sv)
4069         NotEqual(t, errs, nil)
4070         AssertError(t, errs, "Test.Start", "Test.Start", "Start", "Start", "nefield")
4071
4072         now3 := time.Now().UTC()
4073
4074         sv = &Test{
4075                 Start: &now,
4076                 End:   &now3,
4077         }
4078
4079         errs = validate.Struct(sv)
4080         Equal(t, errs, nil)
4081
4082         errs = validate.VarWithValue(nil, 1, "nefield")
4083         NotEqual(t, errs, nil)
4084         AssertError(t, errs, "", "", "", "", "nefield")
4085
4086         errs = validate.VarWithValue(sv, now, "nefield")
4087         Equal(t, errs, nil)
4088
4089         type Test2 struct {
4090                 Start *time.Time `validate:"nefield=NonExistantField"`
4091                 End   *time.Time
4092         }
4093
4094         sv2 := &Test2{
4095                 Start: &now,
4096                 End:   &now,
4097         }
4098
4099         errs = validate.Struct(sv2)
4100         Equal(t, errs, nil)
4101
4102         type Other struct {
4103                 Value string
4104         }
4105
4106         type Test3 struct {
4107                 Value Other
4108                 Time  time.Time `validate:"nefield=Value"`
4109         }
4110
4111         tst := Test3{
4112                 Value: Other{Value: "StringVal"},
4113                 Time:  now,
4114         }
4115
4116         errs = validate.Struct(tst)
4117         Equal(t, errs, nil)
4118 }
4119
4120 func TestIsNeValidation(t *testing.T) {
4121
4122         validate := New()
4123
4124         var j uint64
4125         var k float64
4126         s := "abcdef"
4127         i := 3
4128         j = 2
4129         k = 1.5434
4130         arr := []string{"test"}
4131         now := time.Now().UTC()
4132
4133         errs := validate.Var(s, "ne=abcd")
4134         Equal(t, errs, nil)
4135
4136         errs = validate.Var(i, "ne=1")
4137         Equal(t, errs, nil)
4138
4139         errs = validate.Var(j, "ne=1")
4140         Equal(t, errs, nil)
4141
4142         errs = validate.Var(k, "ne=1.543")
4143         Equal(t, errs, nil)
4144
4145         errs = validate.Var(arr, "ne=2")
4146         Equal(t, errs, nil)
4147
4148         errs = validate.Var(arr, "ne=1")
4149         NotEqual(t, errs, nil)
4150         AssertError(t, errs, "", "", "", "", "ne")
4151
4152         PanicMatches(t, func() { validate.Var(now, "ne=now") }, "Bad field type time.Time")
4153 }
4154
4155 func TestIsEqFieldValidation(t *testing.T) {
4156
4157         validate := New()
4158
4159         var j uint64
4160         var k float64
4161         s := "abcd"
4162         i := 1
4163         j = 1
4164         k = 1.543
4165         arr := []string{"test"}
4166         now := time.Now().UTC()
4167
4168         var j2 uint64
4169         var k2 float64
4170         s2 := "abcd"
4171         i2 := 1
4172         j2 = 1
4173         k2 = 1.543
4174         arr2 := []string{"test"}
4175         arr3 := []string{"test", "test2"}
4176         now2 := now
4177
4178         errs := validate.VarWithValue(s, s2, "eqfield")
4179         Equal(t, errs, nil)
4180
4181         errs = validate.VarWithValue(i2, i, "eqfield")
4182         Equal(t, errs, nil)
4183
4184         errs = validate.VarWithValue(j2, j, "eqfield")
4185         Equal(t, errs, nil)
4186
4187         errs = validate.VarWithValue(k2, k, "eqfield")
4188         Equal(t, errs, nil)
4189
4190         errs = validate.VarWithValue(arr2, arr, "eqfield")
4191         Equal(t, errs, nil)
4192
4193         errs = validate.VarWithValue(now2, now, "eqfield")
4194         Equal(t, errs, nil)
4195
4196         errs = validate.VarWithValue(arr3, arr, "eqfield")
4197         NotEqual(t, errs, nil)
4198         AssertError(t, errs, "", "", "", "", "eqfield")
4199
4200         type Test struct {
4201                 Start *time.Time `validate:"eqfield=End"`
4202                 End   *time.Time
4203         }
4204
4205         sv := &Test{
4206                 Start: &now,
4207                 End:   &now,
4208         }
4209
4210         errs = validate.Struct(sv)
4211         Equal(t, errs, nil)
4212
4213         now3 := time.Now().UTC()
4214
4215         sv = &Test{
4216                 Start: &now,
4217                 End:   &now3,
4218         }
4219
4220         errs = validate.Struct(sv)
4221         NotEqual(t, errs, nil)
4222         AssertError(t, errs, "Test.Start", "Test.Start", "Start", "Start", "eqfield")
4223
4224         errs = validate.VarWithValue(nil, 1, "eqfield")
4225         NotEqual(t, errs, nil)
4226         AssertError(t, errs, "", "", "", "", "eqfield")
4227
4228         channel := make(chan string)
4229         errs = validate.VarWithValue(5, channel, "eqfield")
4230         NotEqual(t, errs, nil)
4231         AssertError(t, errs, "", "", "", "", "eqfield")
4232
4233         errs = validate.VarWithValue(5, now, "eqfield")
4234         NotEqual(t, errs, nil)
4235         AssertError(t, errs, "", "", "", "", "eqfield")
4236
4237         type Test2 struct {
4238                 Start *time.Time `validate:"eqfield=NonExistantField"`
4239                 End   *time.Time
4240         }
4241
4242         sv2 := &Test2{
4243                 Start: &now,
4244                 End:   &now,
4245         }
4246
4247         errs = validate.Struct(sv2)
4248         NotEqual(t, errs, nil)
4249         AssertError(t, errs, "Test2.Start", "Test2.Start", "Start", "Start", "eqfield")
4250
4251         type Inner struct {
4252                 Name string
4253         }
4254
4255         type TStruct struct {
4256                 Inner     *Inner
4257                 CreatedAt *time.Time `validate:"eqfield=Inner"`
4258         }
4259
4260         inner := &Inner{
4261                 Name: "NAME",
4262         }
4263
4264         test := &TStruct{
4265                 Inner:     inner,
4266                 CreatedAt: &now,
4267         }
4268
4269         errs = validate.Struct(test)
4270         NotEqual(t, errs, nil)
4271         AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqfield")
4272 }
4273
4274 func TestIsEqValidation(t *testing.T) {
4275
4276         validate := New()
4277
4278         var j uint64
4279         var k float64
4280         s := "abcd"
4281         i := 1
4282         j = 1
4283         k = 1.543
4284         arr := []string{"test"}
4285         now := time.Now().UTC()
4286
4287         errs := validate.Var(s, "eq=abcd")
4288         Equal(t, errs, nil)
4289
4290         errs = validate.Var(i, "eq=1")
4291         Equal(t, errs, nil)
4292
4293         errs = validate.Var(j, "eq=1")
4294         Equal(t, errs, nil)
4295
4296         errs = validate.Var(k, "eq=1.543")
4297         Equal(t, errs, nil)
4298
4299         errs = validate.Var(arr, "eq=1")
4300         Equal(t, errs, nil)
4301
4302         errs = validate.Var(arr, "eq=2")
4303         NotEqual(t, errs, nil)
4304         AssertError(t, errs, "", "", "", "", "eq")
4305
4306         PanicMatches(t, func() { validate.Var(now, "eq=now") }, "Bad field type time.Time")
4307 }
4308
4309 func TestBase64Validation(t *testing.T) {
4310
4311         validate := New()
4312
4313         s := "dW5pY29ybg=="
4314
4315         errs := validate.Var(s, "base64")
4316         Equal(t, errs, nil)
4317
4318         s = "dGhpIGlzIGEgdGVzdCBiYXNlNjQ="
4319         errs = validate.Var(s, "base64")
4320         Equal(t, errs, nil)
4321
4322         s = ""
4323         errs = validate.Var(s, "base64")
4324         NotEqual(t, errs, nil)
4325         AssertError(t, errs, "", "", "", "", "base64")
4326
4327         s = "dW5pY29ybg== foo bar"
4328         errs = validate.Var(s, "base64")
4329         NotEqual(t, errs, nil)
4330         AssertError(t, errs, "", "", "", "", "base64")
4331 }
4332
4333 func TestNoStructLevelValidation(t *testing.T) {
4334
4335         type Inner struct {
4336                 Test string `validate:"len=5"`
4337         }
4338
4339         type Outer struct {
4340                 InnerStruct *Inner `validate:"required,nostructlevel"`
4341         }
4342
4343         outer := &Outer{
4344                 InnerStruct: nil,
4345         }
4346
4347         validate := New()
4348
4349         errs := validate.Struct(outer)
4350         NotEqual(t, errs, nil)
4351         AssertError(t, errs, "Outer.InnerStruct", "Outer.InnerStruct", "InnerStruct", "InnerStruct", "required")
4352
4353         inner := &Inner{
4354                 Test: "1234",
4355         }
4356
4357         outer = &Outer{
4358                 InnerStruct: inner,
4359         }
4360
4361         errs = validate.Struct(outer)
4362         Equal(t, errs, nil)
4363 }
4364
4365 func TestStructOnlyValidation(t *testing.T) {
4366
4367         type Inner struct {
4368                 Test string `validate:"len=5"`
4369         }
4370
4371         type Outer struct {
4372                 InnerStruct *Inner `validate:"required,structonly"`
4373         }
4374
4375         outer := &Outer{
4376                 InnerStruct: nil,
4377         }
4378
4379         validate := New()
4380
4381         errs := validate.Struct(outer)
4382         NotEqual(t, errs, nil)
4383         AssertError(t, errs, "Outer.InnerStruct", "Outer.InnerStruct", "InnerStruct", "InnerStruct", "required")
4384
4385         inner := &Inner{
4386                 Test: "1234",
4387         }
4388
4389         outer = &Outer{
4390                 InnerStruct: inner,
4391         }
4392
4393         errs = validate.Struct(outer)
4394         Equal(t, errs, nil)
4395
4396         // Address houses a users address information
4397         type Address struct {
4398                 Street string `validate:"required"`
4399                 City   string `validate:"required"`
4400                 Planet string `validate:"required"`
4401                 Phone  string `validate:"required"`
4402         }
4403
4404         type User struct {
4405                 FirstName      string     `json:"fname"`
4406                 LastName       string     `json:"lname"`
4407                 Age            uint8      `validate:"gte=0,lte=130"`
4408                 Email          string     `validate:"required,email"`
4409                 FavouriteColor string     `validate:"hexcolor|rgb|rgba"`
4410                 Addresses      []*Address `validate:"required"`   // a person can have a home and cottage...
4411                 Address        Address    `validate:"structonly"` // a person can have a home and cottage...
4412         }
4413
4414         address := &Address{
4415                 Street: "Eavesdown Docks",
4416                 Planet: "Persphone",
4417                 Phone:  "none",
4418                 City:   "Unknown",
4419         }
4420
4421         user := &User{
4422                 FirstName:      "",
4423                 LastName:       "",
4424                 Age:            45,
4425                 Email:          "Badger.Smith@gmail.com",
4426                 FavouriteColor: "#000",
4427                 Addresses:      []*Address{address},
4428                 Address: Address{
4429                         // Street: "Eavesdown Docks",
4430                         Planet: "Persphone",
4431                         Phone:  "none",
4432                         City:   "Unknown",
4433                 },
4434         }
4435
4436         errs = validate.Struct(user)
4437         Equal(t, errs, nil)
4438 }
4439
4440 func TestGtField(t *testing.T) {
4441
4442         validate := New()
4443
4444         type TimeTest struct {
4445                 Start *time.Time `validate:"required,gt"`
4446                 End   *time.Time `validate:"required,gt,gtfield=Start"`
4447         }
4448
4449         now := time.Now()
4450         start := now.Add(time.Hour * 24)
4451         end := start.Add(time.Hour * 24)
4452
4453         timeTest := &TimeTest{
4454                 Start: &start,
4455                 End:   &end,
4456         }
4457
4458         errs := validate.Struct(timeTest)
4459         Equal(t, errs, nil)
4460
4461         timeTest = &TimeTest{
4462                 Start: &end,
4463                 End:   &start,
4464         }
4465
4466         errs = validate.Struct(timeTest)
4467         NotEqual(t, errs, nil)
4468         AssertError(t, errs, "TimeTest.End", "TimeTest.End", "End", "End", "gtfield")
4469
4470         errs = validate.VarWithValue(&end, &start, "gtfield")
4471         Equal(t, errs, nil)
4472
4473         errs = validate.VarWithValue(&start, &end, "gtfield")
4474         NotEqual(t, errs, nil)
4475         AssertError(t, errs, "", "", "", "", "gtfield")
4476
4477         errs = validate.VarWithValue(&end, &start, "gtfield")
4478         Equal(t, errs, nil)
4479
4480         errs = validate.VarWithValue(&timeTest, &end, "gtfield")
4481         NotEqual(t, errs, nil)
4482
4483         errs = validate.VarWithValue("test bigger", "test", "gtfield")
4484         Equal(t, errs, nil)
4485
4486         type IntTest struct {
4487                 Val1 int `validate:"required"`
4488                 Val2 int `validate:"required,gtfield=Val1"`
4489         }
4490
4491         intTest := &IntTest{
4492                 Val1: 1,
4493                 Val2: 5,
4494         }
4495
4496         errs = validate.Struct(intTest)
4497         Equal(t, errs, nil)
4498
4499         intTest = &IntTest{
4500                 Val1: 5,
4501                 Val2: 1,
4502         }
4503
4504         errs = validate.Struct(intTest)
4505         NotEqual(t, errs, nil)
4506         AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "gtfield")
4507
4508         errs = validate.VarWithValue(int(5), int(1), "gtfield")
4509         Equal(t, errs, nil)
4510
4511         errs = validate.VarWithValue(int(1), int(5), "gtfield")
4512         NotEqual(t, errs, nil)
4513         AssertError(t, errs, "", "", "", "", "gtfield")
4514
4515         type UIntTest struct {
4516                 Val1 uint `validate:"required"`
4517                 Val2 uint `validate:"required,gtfield=Val1"`
4518         }
4519
4520         uIntTest := &UIntTest{
4521                 Val1: 1,
4522                 Val2: 5,
4523         }
4524
4525         errs = validate.Struct(uIntTest)
4526         Equal(t, errs, nil)
4527
4528         uIntTest = &UIntTest{
4529                 Val1: 5,
4530                 Val2: 1,
4531         }
4532
4533         errs = validate.Struct(uIntTest)
4534         NotEqual(t, errs, nil)
4535         AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "gtfield")
4536
4537         errs = validate.VarWithValue(uint(5), uint(1), "gtfield")
4538         Equal(t, errs, nil)
4539
4540         errs = validate.VarWithValue(uint(1), uint(5), "gtfield")
4541         NotEqual(t, errs, nil)
4542         AssertError(t, errs, "", "", "", "", "gtfield")
4543
4544         type FloatTest struct {
4545                 Val1 float64 `validate:"required"`
4546                 Val2 float64 `validate:"required,gtfield=Val1"`
4547         }
4548
4549         floatTest := &FloatTest{
4550                 Val1: 1,
4551                 Val2: 5,
4552         }
4553
4554         errs = validate.Struct(floatTest)
4555         Equal(t, errs, nil)
4556
4557         floatTest = &FloatTest{
4558                 Val1: 5,
4559                 Val2: 1,
4560         }
4561
4562         errs = validate.Struct(floatTest)
4563         NotEqual(t, errs, nil)
4564         AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "gtfield")
4565
4566         errs = validate.VarWithValue(float32(5), float32(1), "gtfield")
4567         Equal(t, errs, nil)
4568
4569         errs = validate.VarWithValue(float32(1), float32(5), "gtfield")
4570         NotEqual(t, errs, nil)
4571         AssertError(t, errs, "", "", "", "", "gtfield")
4572
4573         errs = validate.VarWithValue(nil, 1, "gtfield")
4574         NotEqual(t, errs, nil)
4575         AssertError(t, errs, "", "", "", "", "gtfield")
4576
4577         errs = validate.VarWithValue(5, "T", "gtfield")
4578         NotEqual(t, errs, nil)
4579         AssertError(t, errs, "", "", "", "", "gtfield")
4580
4581         errs = validate.VarWithValue(5, start, "gtfield")
4582         NotEqual(t, errs, nil)
4583         AssertError(t, errs, "", "", "", "", "gtfield")
4584
4585         type TimeTest2 struct {
4586                 Start *time.Time `validate:"required"`
4587                 End   *time.Time `validate:"required,gtfield=NonExistantField"`
4588         }
4589
4590         timeTest2 := &TimeTest2{
4591                 Start: &start,
4592                 End:   &end,
4593         }
4594
4595         errs = validate.Struct(timeTest2)
4596         NotEqual(t, errs, nil)
4597         AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "gtfield")
4598
4599         type Other struct {
4600                 Value string
4601         }
4602
4603         type Test struct {
4604                 Value Other
4605                 Time  time.Time `validate:"gtfield=Value"`
4606         }
4607
4608         tst := Test{
4609                 Value: Other{Value: "StringVal"},
4610                 Time:  end,
4611         }
4612
4613         errs = validate.Struct(tst)
4614         NotEqual(t, errs, nil)
4615         AssertError(t, errs, "Test.Time", "Test.Time", "Time", "Time", "gtfield")
4616 }
4617
4618 func TestLtField(t *testing.T) {
4619
4620         validate := New()
4621
4622         type TimeTest struct {
4623                 Start *time.Time `validate:"required,lt,ltfield=End"`
4624                 End   *time.Time `validate:"required,lt"`
4625         }
4626
4627         now := time.Now()
4628         start := now.Add(time.Hour * 24 * -1 * 2)
4629         end := start.Add(time.Hour * 24)
4630
4631         timeTest := &TimeTest{
4632                 Start: &start,
4633                 End:   &end,
4634         }
4635
4636         errs := validate.Struct(timeTest)
4637         Equal(t, errs, nil)
4638
4639         timeTest = &TimeTest{
4640                 Start: &end,
4641                 End:   &start,
4642         }
4643
4644         errs = validate.Struct(timeTest)
4645         NotEqual(t, errs, nil)
4646         AssertError(t, errs, "TimeTest.Start", "TimeTest.Start", "Start", "Start", "ltfield")
4647
4648         errs = validate.VarWithValue(&start, &end, "ltfield")
4649         Equal(t, errs, nil)
4650
4651         errs = validate.VarWithValue(&end, &start, "ltfield")
4652         NotEqual(t, errs, nil)
4653         AssertError(t, errs, "", "", "", "", "ltfield")
4654
4655         errs = validate.VarWithValue(&end, timeTest, "ltfield")
4656         NotEqual(t, errs, nil)
4657         AssertError(t, errs, "", "", "", "", "ltfield")
4658
4659         errs = validate.VarWithValue("tes", "test", "ltfield")
4660         Equal(t, errs, nil)
4661
4662         type IntTest struct {
4663                 Val1 int `validate:"required"`
4664                 Val2 int `validate:"required,ltfield=Val1"`
4665         }
4666
4667         intTest := &IntTest{
4668                 Val1: 5,
4669                 Val2: 1,
4670         }
4671
4672         errs = validate.Struct(intTest)
4673         Equal(t, errs, nil)
4674
4675         intTest = &IntTest{
4676                 Val1: 1,
4677                 Val2: 5,
4678         }
4679
4680         errs = validate.Struct(intTest)
4681         NotEqual(t, errs, nil)
4682         AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "ltfield")
4683
4684         errs = validate.VarWithValue(int(1), int(5), "ltfield")
4685         Equal(t, errs, nil)
4686
4687         errs = validate.VarWithValue(int(5), int(1), "ltfield")
4688         NotEqual(t, errs, nil)
4689         AssertError(t, errs, "", "", "", "", "ltfield")
4690
4691         type UIntTest struct {
4692                 Val1 uint `validate:"required"`
4693                 Val2 uint `validate:"required,ltfield=Val1"`
4694         }
4695
4696         uIntTest := &UIntTest{
4697                 Val1: 5,
4698                 Val2: 1,
4699         }
4700
4701         errs = validate.Struct(uIntTest)
4702         Equal(t, errs, nil)
4703
4704         uIntTest = &UIntTest{
4705                 Val1: 1,
4706                 Val2: 5,
4707         }
4708
4709         errs = validate.Struct(uIntTest)
4710         NotEqual(t, errs, nil)
4711         AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "ltfield")
4712
4713         errs = validate.VarWithValue(uint(1), uint(5), "ltfield")
4714         Equal(t, errs, nil)
4715
4716         errs = validate.VarWithValue(uint(5), uint(1), "ltfield")
4717         NotEqual(t, errs, nil)
4718         AssertError(t, errs, "", "", "", "", "ltfield")
4719
4720         type FloatTest struct {
4721                 Val1 float64 `validate:"required"`
4722                 Val2 float64 `validate:"required,ltfield=Val1"`
4723         }
4724
4725         floatTest := &FloatTest{
4726                 Val1: 5,
4727                 Val2: 1,
4728         }
4729
4730         errs = validate.Struct(floatTest)
4731         Equal(t, errs, nil)
4732
4733         floatTest = &FloatTest{
4734                 Val1: 1,
4735                 Val2: 5,
4736         }
4737
4738         errs = validate.Struct(floatTest)
4739         NotEqual(t, errs, nil)
4740         AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "ltfield")
4741
4742         errs = validate.VarWithValue(float32(1), float32(5), "ltfield")
4743         Equal(t, errs, nil)
4744
4745         errs = validate.VarWithValue(float32(5), float32(1), "ltfield")
4746         NotEqual(t, errs, nil)
4747         AssertError(t, errs, "", "", "", "", "ltfield")
4748
4749         errs = validate.VarWithValue(nil, 5, "ltfield")
4750         NotEqual(t, errs, nil)
4751         AssertError(t, errs, "", "", "", "", "ltfield")
4752
4753         errs = validate.VarWithValue(1, "T", "ltfield")
4754         NotEqual(t, errs, nil)
4755         AssertError(t, errs, "", "", "", "", "ltfield")
4756
4757         errs = validate.VarWithValue(1, end, "ltfield")
4758         NotEqual(t, errs, nil)
4759         AssertError(t, errs, "", "", "", "", "ltfield")
4760
4761         type TimeTest2 struct {
4762                 Start *time.Time `validate:"required"`
4763                 End   *time.Time `validate:"required,ltfield=NonExistantField"`
4764         }
4765
4766         timeTest2 := &TimeTest2{
4767                 Start: &end,
4768                 End:   &start,
4769         }
4770
4771         errs = validate.Struct(timeTest2)
4772         NotEqual(t, errs, nil)
4773         AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "ltfield")
4774 }
4775
4776 func TestLteField(t *testing.T) {
4777
4778         validate := New()
4779
4780         type TimeTest struct {
4781                 Start *time.Time `validate:"required,lte,ltefield=End"`
4782                 End   *time.Time `validate:"required,lte"`
4783         }
4784
4785         now := time.Now()
4786         start := now.Add(time.Hour * 24 * -1 * 2)
4787         end := start.Add(time.Hour * 24)
4788
4789         timeTest := &TimeTest{
4790                 Start: &start,
4791                 End:   &end,
4792         }
4793
4794         errs := validate.Struct(timeTest)
4795         Equal(t, errs, nil)
4796
4797         timeTest = &TimeTest{
4798                 Start: &end,
4799                 End:   &start,
4800         }
4801
4802         errs = validate.Struct(timeTest)
4803         NotEqual(t, errs, nil)
4804         AssertError(t, errs, "TimeTest.Start", "TimeTest.Start", "Start", "Start", "ltefield")
4805
4806         errs = validate.VarWithValue(&start, &end, "ltefield")
4807         Equal(t, errs, nil)
4808
4809         errs = validate.VarWithValue(&end, &start, "ltefield")
4810         NotEqual(t, errs, nil)
4811         AssertError(t, errs, "", "", "", "", "ltefield")
4812
4813         errs = validate.VarWithValue(&end, timeTest, "ltefield")
4814         NotEqual(t, errs, nil)
4815         AssertError(t, errs, "", "", "", "", "ltefield")
4816
4817         errs = validate.VarWithValue("tes", "test", "ltefield")
4818         Equal(t, errs, nil)
4819
4820         errs = validate.VarWithValue("test", "test", "ltefield")
4821         Equal(t, errs, nil)
4822
4823         type IntTest struct {
4824                 Val1 int `validate:"required"`
4825                 Val2 int `validate:"required,ltefield=Val1"`
4826         }
4827
4828         intTest := &IntTest{
4829                 Val1: 5,
4830                 Val2: 1,
4831         }
4832
4833         errs = validate.Struct(intTest)
4834         Equal(t, errs, nil)
4835
4836         intTest = &IntTest{
4837                 Val1: 1,
4838                 Val2: 5,
4839         }
4840
4841         errs = validate.Struct(intTest)
4842         NotEqual(t, errs, nil)
4843         AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "ltefield")
4844
4845         errs = validate.VarWithValue(int(1), int(5), "ltefield")
4846         Equal(t, errs, nil)
4847
4848         errs = validate.VarWithValue(int(5), int(1), "ltefield")
4849         NotEqual(t, errs, nil)
4850         AssertError(t, errs, "", "", "", "", "ltefield")
4851
4852         type UIntTest struct {
4853                 Val1 uint `validate:"required"`
4854                 Val2 uint `validate:"required,ltefield=Val1"`
4855         }
4856
4857         uIntTest := &UIntTest{
4858                 Val1: 5,
4859                 Val2: 1,
4860         }
4861
4862         errs = validate.Struct(uIntTest)
4863         Equal(t, errs, nil)
4864
4865         uIntTest = &UIntTest{
4866                 Val1: 1,
4867                 Val2: 5,
4868         }
4869
4870         errs = validate.Struct(uIntTest)
4871         NotEqual(t, errs, nil)
4872         AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "ltefield")
4873
4874         errs = validate.VarWithValue(uint(1), uint(5), "ltefield")
4875         Equal(t, errs, nil)
4876
4877         errs = validate.VarWithValue(uint(5), uint(1), "ltefield")
4878         NotEqual(t, errs, nil)
4879         AssertError(t, errs, "", "", "", "", "ltefield")
4880
4881         type FloatTest struct {
4882                 Val1 float64 `validate:"required"`
4883                 Val2 float64 `validate:"required,ltefield=Val1"`
4884         }
4885
4886         floatTest := &FloatTest{
4887                 Val1: 5,
4888                 Val2: 1,
4889         }
4890
4891         errs = validate.Struct(floatTest)
4892         Equal(t, errs, nil)
4893
4894         floatTest = &FloatTest{
4895                 Val1: 1,
4896                 Val2: 5,
4897         }
4898
4899         errs = validate.Struct(floatTest)
4900         NotEqual(t, errs, nil)
4901         AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "ltefield")
4902
4903         errs = validate.VarWithValue(float32(1), float32(5), "ltefield")
4904         Equal(t, errs, nil)
4905
4906         errs = validate.VarWithValue(float32(5), float32(1), "ltefield")
4907         NotEqual(t, errs, nil)
4908         AssertError(t, errs, "", "", "", "", "ltefield")
4909
4910         errs = validate.VarWithValue(nil, 5, "ltefield")
4911         NotEqual(t, errs, nil)
4912         AssertError(t, errs, "", "", "", "", "ltefield")
4913
4914         errs = validate.VarWithValue(1, "T", "ltefield")
4915         NotEqual(t, errs, nil)
4916         AssertError(t, errs, "", "", "", "", "ltefield")
4917
4918         errs = validate.VarWithValue(1, end, "ltefield")
4919         NotEqual(t, errs, nil)
4920         AssertError(t, errs, "", "", "", "", "ltefield")
4921
4922         type TimeTest2 struct {
4923                 Start *time.Time `validate:"required"`
4924                 End   *time.Time `validate:"required,ltefield=NonExistantField"`
4925         }
4926
4927         timeTest2 := &TimeTest2{
4928                 Start: &end,
4929                 End:   &start,
4930         }
4931
4932         errs = validate.Struct(timeTest2)
4933         NotEqual(t, errs, nil)
4934         AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "ltefield")
4935 }
4936
4937 func TestGteField(t *testing.T) {
4938
4939         validate := New()
4940
4941         type TimeTest struct {
4942                 Start *time.Time `validate:"required,gte"`
4943                 End   *time.Time `validate:"required,gte,gtefield=Start"`
4944         }
4945
4946         now := time.Now()
4947         start := now.Add(time.Hour * 24)
4948         end := start.Add(time.Hour * 24)
4949
4950         timeTest := &TimeTest{
4951                 Start: &start,
4952                 End:   &end,
4953         }
4954
4955         errs := validate.Struct(timeTest)
4956         Equal(t, errs, nil)
4957
4958         timeTest = &TimeTest{
4959                 Start: &end,
4960                 End:   &start,
4961         }
4962
4963         errs = validate.Struct(timeTest)
4964         NotEqual(t, errs, nil)
4965         AssertError(t, errs, "TimeTest.End", "TimeTest.End", "End", "End", "gtefield")
4966
4967         errs = validate.VarWithValue(&end, &start, "gtefield")
4968         Equal(t, errs, nil)
4969
4970         errs = validate.VarWithValue(&start, &end, "gtefield")
4971         NotEqual(t, errs, nil)
4972         AssertError(t, errs, "", "", "", "", "gtefield")
4973
4974         errs = validate.VarWithValue(&start, timeTest, "gtefield")
4975         NotEqual(t, errs, nil)
4976         AssertError(t, errs, "", "", "", "", "gtefield")
4977
4978         errs = validate.VarWithValue("test", "test", "gtefield")
4979         Equal(t, errs, nil)
4980
4981         errs = validate.VarWithValue("test bigger", "test", "gtefield")
4982         Equal(t, errs, nil)
4983
4984         type IntTest struct {
4985                 Val1 int `validate:"required"`
4986                 Val2 int `validate:"required,gtefield=Val1"`
4987         }
4988
4989         intTest := &IntTest{
4990                 Val1: 1,
4991                 Val2: 5,
4992         }
4993
4994         errs = validate.Struct(intTest)
4995         Equal(t, errs, nil)
4996
4997         intTest = &IntTest{
4998                 Val1: 5,
4999                 Val2: 1,
5000         }
5001
5002         errs = validate.Struct(intTest)
5003         NotEqual(t, errs, nil)
5004         AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "gtefield")
5005
5006         errs = validate.VarWithValue(int(5), int(1), "gtefield")
5007         Equal(t, errs, nil)
5008
5009         errs = validate.VarWithValue(int(1), int(5), "gtefield")
5010         NotEqual(t, errs, nil)
5011         AssertError(t, errs, "", "", "", "", "gtefield")
5012
5013         type UIntTest struct {
5014                 Val1 uint `validate:"required"`
5015                 Val2 uint `validate:"required,gtefield=Val1"`
5016         }
5017
5018         uIntTest := &UIntTest{
5019                 Val1: 1,
5020                 Val2: 5,
5021         }
5022
5023         errs = validate.Struct(uIntTest)
5024         Equal(t, errs, nil)
5025
5026         uIntTest = &UIntTest{
5027                 Val1: 5,
5028                 Val2: 1,
5029         }
5030
5031         errs = validate.Struct(uIntTest)
5032         NotEqual(t, errs, nil)
5033         AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "gtefield")
5034
5035         errs = validate.VarWithValue(uint(5), uint(1), "gtefield")
5036         Equal(t, errs, nil)
5037
5038         errs = validate.VarWithValue(uint(1), uint(5), "gtefield")
5039         NotEqual(t, errs, nil)
5040         AssertError(t, errs, "", "", "", "", "gtefield")
5041
5042         type FloatTest struct {
5043                 Val1 float64 `validate:"required"`
5044                 Val2 float64 `validate:"required,gtefield=Val1"`
5045         }
5046
5047         floatTest := &FloatTest{
5048                 Val1: 1,
5049                 Val2: 5,
5050         }
5051
5052         errs = validate.Struct(floatTest)
5053         Equal(t, errs, nil)
5054
5055         floatTest = &FloatTest{
5056                 Val1: 5,
5057                 Val2: 1,
5058         }
5059
5060         errs = validate.Struct(floatTest)
5061         NotEqual(t, errs, nil)
5062         AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "gtefield")
5063
5064         errs = validate.VarWithValue(float32(5), float32(1), "gtefield")
5065         Equal(t, errs, nil)
5066
5067         errs = validate.VarWithValue(float32(1), float32(5), "gtefield")
5068         NotEqual(t, errs, nil)
5069         AssertError(t, errs, "", "", "", "", "gtefield")
5070
5071         errs = validate.VarWithValue(nil, 1, "gtefield")
5072         NotEqual(t, errs, nil)
5073         AssertError(t, errs, "", "", "", "", "gtefield")
5074
5075         errs = validate.VarWithValue(5, "T", "gtefield")
5076         NotEqual(t, errs, nil)
5077         AssertError(t, errs, "", "", "", "", "gtefield")
5078
5079         errs = validate.VarWithValue(5, start, "gtefield")
5080         NotEqual(t, errs, nil)
5081         AssertError(t, errs, "", "", "", "", "gtefield")
5082
5083         type TimeTest2 struct {
5084                 Start *time.Time `validate:"required"`
5085                 End   *time.Time `validate:"required,gtefield=NonExistantField"`
5086         }
5087
5088         timeTest2 := &TimeTest2{
5089                 Start: &start,
5090                 End:   &end,
5091         }
5092
5093         errs = validate.Struct(timeTest2)
5094         NotEqual(t, errs, nil)
5095         AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "gtefield")
5096 }
5097
5098 func TestValidateByTagAndValue(t *testing.T) {
5099
5100         validate := New()
5101
5102         val := "test"
5103         field := "test"
5104         errs := validate.VarWithValue(val, field, "required")
5105         Equal(t, errs, nil)
5106
5107         fn := func(fl FieldLevel) bool {
5108
5109                 return fl.Parent().String() == fl.Field().String()
5110         }
5111
5112         validate.RegisterValidation("isequaltestfunc", fn)
5113
5114         errs = validate.VarWithValue(val, field, "isequaltestfunc")
5115         Equal(t, errs, nil)
5116
5117         val = "unequal"
5118
5119         errs = validate.VarWithValue(val, field, "isequaltestfunc")
5120         NotEqual(t, errs, nil)
5121         AssertError(t, errs, "", "", "", "", "isequaltestfunc")
5122 }
5123
5124 func TestAddFunctions(t *testing.T) {
5125
5126         fn := func(fl FieldLevel) bool {
5127
5128                 return true
5129         }
5130
5131         fnCtx := func(ctx context.Context, fl FieldLevel) bool {
5132                 return true
5133         }
5134
5135         validate := New()
5136
5137         errs := validate.RegisterValidation("new", fn)
5138         Equal(t, errs, nil)
5139
5140         errs = validate.RegisterValidation("", fn)
5141         NotEqual(t, errs, nil)
5142
5143         validate.RegisterValidation("new", nil)
5144         NotEqual(t, errs, nil)
5145
5146         errs = validate.RegisterValidation("new", fn)
5147         Equal(t, errs, nil)
5148
5149         errs = validate.RegisterValidationCtx("new", fnCtx)
5150         Equal(t, errs, nil)
5151
5152         PanicMatches(t, func() { validate.RegisterValidation("dive", fn) }, "Tag 'dive' either contains restricted characters or is the same as a restricted tag needed for normal operation")
5153 }
5154
5155 func TestChangeTag(t *testing.T) {
5156
5157         validate := New()
5158         validate.SetTagName("val")
5159
5160         type Test struct {
5161                 Name string `val:"len=4"`
5162         }
5163         s := &Test{
5164                 Name: "TEST",
5165         }
5166
5167         errs := validate.Struct(s)
5168         Equal(t, errs, nil)
5169
5170         s.Name = ""
5171
5172         errs = validate.Struct(s)
5173         NotEqual(t, errs, nil)
5174         AssertError(t, errs, "Test.Name", "Test.Name", "Name", "Name", "len")
5175 }
5176
5177 func TestUnexposedStruct(t *testing.T) {
5178
5179         validate := New()
5180
5181         type Test struct {
5182                 Name      string
5183                 unexposed struct {
5184                         A string `validate:"required"`
5185                 }
5186         }
5187
5188         s := &Test{
5189                 Name: "TEST",
5190         }
5191
5192         errs := validate.Struct(s)
5193         Equal(t, errs, nil)
5194 }
5195
5196 func TestBadParams(t *testing.T) {
5197
5198         validate := New()
5199
5200         i := 1
5201         errs := validate.Var(i, "-")
5202         Equal(t, errs, nil)
5203
5204         PanicMatches(t, func() { validate.Var(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
5205         PanicMatches(t, func() { validate.Var(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
5206
5207         var ui uint = 1
5208         PanicMatches(t, func() { validate.Var(ui, "len=a") }, "strconv.ParseUint: parsing \"a\": invalid syntax")
5209
5210         f := 1.23
5211         PanicMatches(t, func() { validate.Var(f, "len=a") }, "strconv.ParseFloat: parsing \"a\": invalid syntax")
5212 }
5213
5214 func TestLength(t *testing.T) {
5215
5216         validate := New()
5217
5218         i := true
5219         PanicMatches(t, func() { validate.Var(i, "len") }, "Bad field type bool")
5220 }
5221
5222 func TestIsGt(t *testing.T) {
5223
5224         validate := New()
5225
5226         myMap := map[string]string{}
5227         errs := validate.Var(myMap, "gt=0")
5228         NotEqual(t, errs, nil)
5229
5230         f := 1.23
5231         errs = validate.Var(f, "gt=5")
5232         NotEqual(t, errs, nil)
5233         AssertError(t, errs, "", "", "", "", "gt")
5234
5235         var ui uint = 5
5236         errs = validate.Var(ui, "gt=10")
5237         NotEqual(t, errs, nil)
5238         AssertError(t, errs, "", "", "", "", "gt")
5239
5240         i := true
5241         PanicMatches(t, func() { validate.Var(i, "gt") }, "Bad field type bool")
5242
5243         tm := time.Now().UTC()
5244         tm = tm.Add(time.Hour * 24)
5245
5246         errs = validate.Var(tm, "gt")
5247         Equal(t, errs, nil)
5248
5249         t2 := time.Now().UTC().Add(-time.Hour)
5250
5251         errs = validate.Var(t2, "gt")
5252         NotEqual(t, errs, nil)
5253         AssertError(t, errs, "", "", "", "", "gt")
5254
5255         type Test struct {
5256                 Now *time.Time `validate:"gt"`
5257         }
5258         s := &Test{
5259                 Now: &tm,
5260         }
5261
5262         errs = validate.Struct(s)
5263         Equal(t, errs, nil)
5264
5265         s = &Test{
5266                 Now: &t2,
5267         }
5268
5269         errs = validate.Struct(s)
5270         NotEqual(t, errs, nil)
5271         AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gt")
5272 }
5273
5274 func TestIsGte(t *testing.T) {
5275
5276         validate := New()
5277
5278         i := true
5279         PanicMatches(t, func() { validate.Var(i, "gte") }, "Bad field type bool")
5280
5281         t1 := time.Now().UTC()
5282         t1 = t1.Add(time.Hour * 24)
5283
5284         errs := validate.Var(t1, "gte")
5285         Equal(t, errs, nil)
5286
5287         t2 := time.Now().UTC().Add(-time.Hour)
5288
5289         errs = validate.Var(t2, "gte")
5290         NotEqual(t, errs, nil)
5291         AssertError(t, errs, "", "", "", "", "gte")
5292
5293         type Test struct {
5294                 Now *time.Time `validate:"gte"`
5295         }
5296         s := &Test{
5297                 Now: &t1,
5298         }
5299
5300         errs = validate.Struct(s)
5301         Equal(t, errs, nil)
5302
5303         s = &Test{
5304                 Now: &t2,
5305         }
5306
5307         errs = validate.Struct(s)
5308         NotEqual(t, errs, nil)
5309         AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gte")
5310 }
5311
5312 func TestIsLt(t *testing.T) {
5313
5314         validate := New()
5315
5316         myMap := map[string]string{}
5317         errs := validate.Var(myMap, "lt=0")
5318         NotEqual(t, errs, nil)
5319         AssertError(t, errs, "", "", "", "", "lt")
5320
5321         f := 1.23
5322         errs = validate.Var(f, "lt=0")
5323         NotEqual(t, errs, nil)
5324         AssertError(t, errs, "", "", "", "", "lt")
5325
5326         var ui uint = 5
5327         errs = validate.Var(ui, "lt=0")
5328         NotEqual(t, errs, nil)
5329         AssertError(t, errs, "", "", "", "", "lt")
5330
5331         i := true
5332         PanicMatches(t, func() { validate.Var(i, "lt") }, "Bad field type bool")
5333
5334         t1 := time.Now().UTC().Add(-time.Hour)
5335
5336         errs = validate.Var(t1, "lt")
5337         Equal(t, errs, nil)
5338
5339         t2 := time.Now().UTC()
5340         t2 = t2.Add(time.Hour * 24)
5341
5342         errs = validate.Var(t2, "lt")
5343         NotEqual(t, errs, nil)
5344         AssertError(t, errs, "", "", "", "", "lt")
5345
5346         type Test struct {
5347                 Now *time.Time `validate:"lt"`
5348         }
5349
5350         s := &Test{
5351                 Now: &t1,
5352         }
5353
5354         errs = validate.Struct(s)
5355         Equal(t, errs, nil)
5356
5357         s = &Test{
5358                 Now: &t2,
5359         }
5360
5361         errs = validate.Struct(s)
5362         NotEqual(t, errs, nil)
5363         AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "lt")
5364 }
5365
5366 func TestIsLte(t *testing.T) {
5367
5368         validate := New()
5369
5370         i := true
5371         PanicMatches(t, func() { validate.Var(i, "lte") }, "Bad field type bool")
5372
5373         t1 := time.Now().UTC().Add(-time.Hour)
5374
5375         errs := validate.Var(t1, "lte")
5376         Equal(t, errs, nil)
5377
5378         t2 := time.Now().UTC()
5379         t2 = t2.Add(time.Hour * 24)
5380
5381         errs = validate.Var(t2, "lte")
5382         NotEqual(t, errs, nil)
5383         AssertError(t, errs, "", "", "", "", "lte")
5384
5385         type Test struct {
5386                 Now *time.Time `validate:"lte"`
5387         }
5388
5389         s := &Test{
5390                 Now: &t1,
5391         }
5392
5393         errs = validate.Struct(s)
5394         Equal(t, errs, nil)
5395
5396         s = &Test{
5397                 Now: &t2,
5398         }
5399
5400         errs = validate.Struct(s)
5401         NotEqual(t, errs, nil)
5402 }
5403
5404 func TestUrl(t *testing.T) {
5405
5406         var tests = []struct {
5407                 param    string
5408                 expected bool
5409         }{
5410                 {"http://foo.bar#com", true},
5411                 {"http://foobar.com", true},
5412                 {"https://foobar.com", true},
5413                 {"foobar.com", false},
5414                 {"http://foobar.coffee/", true},
5415                 {"http://foobar.中文网/", true},
5416                 {"http://foobar.org/", true},
5417                 {"http://foobar.org:8080/", true},
5418                 {"ftp://foobar.ru/", true},
5419                 {"http://user:pass@www.foobar.com/", true},
5420                 {"http://127.0.0.1/", true},
5421                 {"http://duckduckgo.com/?q=%2F", true},
5422                 {"http://localhost:3000/", true},
5423                 {"http://foobar.com/?foo=bar#baz=qux", true},
5424                 {"http://foobar.com?foo=bar", true},
5425                 {"http://www.xn--froschgrn-x9a.net/", true},
5426                 {"", false},
5427                 {"xyz://foobar.com", true},
5428                 {"invalid.", false},
5429                 {".com", false},
5430                 {"rtmp://foobar.com", true},
5431                 {"http://www.foo_bar.com/", true},
5432                 {"http://localhost:3000/", true},
5433                 {"http://foobar.com/#baz", true},
5434                 {"http://foobar.com#baz=qux", true},
5435                 {"http://foobar.com/t$-_.+!*\\'(),", true},
5436                 {"http://www.foobar.com/~foobar", true},
5437                 {"http://www.-foobar.com/", true},
5438                 {"http://www.foo---bar.com/", true},
5439                 {"mailto:someone@example.com", true},
5440                 {"irc://irc.server.org/channel", true},
5441                 {"irc://#channel@network", true},
5442                 {"/abs/test/dir", false},
5443                 {"./rel/test/dir", false},
5444         }
5445
5446         validate := New()
5447
5448         for i, test := range tests {
5449
5450                 errs := validate.Var(test.param, "url")
5451
5452                 if test.expected {
5453                         if !IsEqual(errs, nil) {
5454                                 t.Fatalf("Index: %d URL failed Error: %s", i, errs)
5455                         }
5456                 } else {
5457                         if IsEqual(errs, nil) {
5458                                 t.Fatalf("Index: %d URL failed Error: %s", i, errs)
5459                         } else {
5460                                 val := getError(errs, "", "")
5461                                 if val.Tag() != "url" {
5462                                         t.Fatalf("Index: %d URL failed Error: %s", i, errs)
5463                                 }
5464                         }
5465                 }
5466         }
5467
5468         i := 1
5469         PanicMatches(t, func() { validate.Var(i, "url") }, "Bad field type int")
5470 }
5471
5472 func TestUri(t *testing.T) {
5473
5474         var tests = []struct {
5475                 param    string
5476                 expected bool
5477         }{
5478                 {"http://foo.bar#com", true},
5479                 {"http://foobar.com", true},
5480                 {"https://foobar.com", true},
5481                 {"foobar.com", false},
5482                 {"http://foobar.coffee/", true},
5483                 {"http://foobar.中文网/", true},
5484                 {"http://foobar.org/", true},
5485                 {"http://foobar.org:8080/", true},
5486                 {"ftp://foobar.ru/", true},
5487                 {"http://user:pass@www.foobar.com/", true},
5488                 {"http://127.0.0.1/", true},
5489                 {"http://duckduckgo.com/?q=%2F", true},
5490                 {"http://localhost:3000/", true},
5491                 {"http://foobar.com/?foo=bar#baz=qux", true},
5492                 {"http://foobar.com?foo=bar", true},
5493                 {"http://www.xn--froschgrn-x9a.net/", true},
5494                 {"", false},
5495                 {"xyz://foobar.com", true},
5496                 {"invalid.", false},
5497                 {".com", false},
5498                 {"rtmp://foobar.com", true},
5499                 {"http://www.foo_bar.com/", true},
5500                 {"http://localhost:3000/", true},
5501                 {"http://foobar.com#baz=qux", true},
5502                 {"http://foobar.com/t$-_.+!*\\'(),", true},
5503                 {"http://www.foobar.com/~foobar", true},
5504                 {"http://www.-foobar.com/", true},
5505                 {"http://www.foo---bar.com/", true},
5506                 {"mailto:someone@example.com", true},
5507                 {"irc://irc.server.org/channel", true},
5508                 {"irc://#channel@network", true},
5509                 {"/abs/test/dir", true},
5510                 {"./rel/test/dir", false},
5511         }
5512
5513         validate := New()
5514
5515         for i, test := range tests {
5516
5517                 errs := validate.Var(test.param, "uri")
5518
5519                 if test.expected {
5520                         if !IsEqual(errs, nil) {
5521                                 t.Fatalf("Index: %d URI failed Error: %s", i, errs)
5522                         }
5523                 } else {
5524                         if IsEqual(errs, nil) {
5525                                 t.Fatalf("Index: %d URI failed Error: %s", i, errs)
5526                         } else {
5527                                 val := getError(errs, "", "")
5528                                 if val.Tag() != "uri" {
5529                                         t.Fatalf("Index: %d URI failed Error: %s", i, errs)
5530                                 }
5531                         }
5532                 }
5533         }
5534
5535         i := 1
5536         PanicMatches(t, func() { validate.Var(i, "uri") }, "Bad field type int")
5537 }
5538
5539 func TestOrTag(t *testing.T) {
5540
5541         validate := New()
5542
5543         s := "rgba(0,31,255,0.5)"
5544         errs := validate.Var(s, "rgb|rgba")
5545         Equal(t, errs, nil)
5546
5547         s = "rgba(0,31,255,0.5)"
5548         errs = validate.Var(s, "rgb|rgba|len=18")
5549         Equal(t, errs, nil)
5550
5551         s = "this ain't right"
5552         errs = validate.Var(s, "rgb|rgba")
5553         NotEqual(t, errs, nil)
5554         AssertError(t, errs, "", "", "", "", "rgb|rgba")
5555
5556         s = "this ain't right"
5557         errs = validate.Var(s, "rgb|rgba|len=10")
5558         NotEqual(t, errs, nil)
5559         AssertError(t, errs, "", "", "", "", "rgb|rgba|len=10")
5560
5561         s = "this is right"
5562         errs = validate.Var(s, "rgb|rgba|len=13")
5563         Equal(t, errs, nil)
5564
5565         s = ""
5566         errs = validate.Var(s, "omitempty,rgb|rgba")
5567         Equal(t, errs, nil)
5568
5569         s = "this is right, but a blank or isn't"
5570
5571         PanicMatches(t, func() { validate.Var(s, "rgb||len=13") }, "Invalid validation tag on field ''")
5572         PanicMatches(t, func() { validate.Var(s, "rgb|rgbaa|len=13") }, "Undefined validation function 'rgbaa' on field ''")
5573
5574         v2 := New()
5575         v2.RegisterTagNameFunc(func(fld reflect.StructField) string {
5576
5577                 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
5578
5579                 if name == "-" {
5580                         return ""
5581                 }
5582
5583                 return name
5584         })
5585
5586         type Colors struct {
5587                 Fav string `validate:"rgb|rgba" json:"fc"`
5588         }
5589
5590         c := Colors{Fav: "this ain't right"}
5591
5592         err := v2.Struct(c)
5593         NotEqual(t, err, nil)
5594
5595         errs = err.(ValidationErrors)
5596         fe := getError(errs, "Colors.fc", "Colors.Fav")
5597         NotEqual(t, fe, nil)
5598 }
5599
5600 func TestHsla(t *testing.T) {
5601
5602         validate := New()
5603
5604         s := "hsla(360,100%,100%,1)"
5605         errs := validate.Var(s, "hsla")
5606         Equal(t, errs, nil)
5607
5608         s = "hsla(360,100%,100%,0.5)"
5609         errs = validate.Var(s, "hsla")
5610         Equal(t, errs, nil)
5611
5612         s = "hsla(0,0%,0%, 0)"
5613         errs = validate.Var(s, "hsla")
5614         Equal(t, errs, nil)
5615
5616         s = "hsl(361,100%,50%,1)"
5617         errs = validate.Var(s, "hsla")
5618         NotEqual(t, errs, nil)
5619         AssertError(t, errs, "", "", "", "", "hsla")
5620
5621         s = "hsl(361,100%,50%)"
5622         errs = validate.Var(s, "hsla")
5623         NotEqual(t, errs, nil)
5624         AssertError(t, errs, "", "", "", "", "hsla")
5625
5626         s = "hsla(361,100%,50%)"
5627         errs = validate.Var(s, "hsla")
5628         NotEqual(t, errs, nil)
5629         AssertError(t, errs, "", "", "", "", "hsla")
5630
5631         s = "hsla(360,101%,50%)"
5632         errs = validate.Var(s, "hsla")
5633         NotEqual(t, errs, nil)
5634         AssertError(t, errs, "", "", "", "", "hsla")
5635
5636         s = "hsla(360,100%,101%)"
5637         errs = validate.Var(s, "hsla")
5638         NotEqual(t, errs, nil)
5639         AssertError(t, errs, "", "", "", "", "hsla")
5640
5641         i := 1
5642         validate.Var(i, "hsla")
5643         NotEqual(t, errs, nil)
5644         AssertError(t, errs, "", "", "", "", "hsla")
5645 }
5646
5647 func TestHsl(t *testing.T) {
5648
5649         validate := New()
5650
5651         s := "hsl(360,100%,50%)"
5652         errs := validate.Var(s, "hsl")
5653         Equal(t, errs, nil)
5654
5655         s = "hsl(0,0%,0%)"
5656         errs = validate.Var(s, "hsl")
5657         Equal(t, errs, nil)
5658
5659         s = "hsl(361,100%,50%)"
5660         errs = validate.Var(s, "hsl")
5661         NotEqual(t, errs, nil)
5662         AssertError(t, errs, "", "", "", "", "hsl")
5663
5664         s = "hsl(361,101%,50%)"
5665         errs = validate.Var(s, "hsl")
5666         NotEqual(t, errs, nil)
5667         AssertError(t, errs, "", "", "", "", "hsl")
5668
5669         s = "hsl(361,100%,101%)"
5670         errs = validate.Var(s, "hsl")
5671         NotEqual(t, errs, nil)
5672         AssertError(t, errs, "", "", "", "", "hsl")
5673
5674         s = "hsl(-10,100%,100%)"
5675         errs = validate.Var(s, "hsl")
5676         NotEqual(t, errs, nil)
5677         AssertError(t, errs, "", "", "", "", "hsl")
5678
5679         i := 1
5680         errs = validate.Var(i, "hsl")
5681         NotEqual(t, errs, nil)
5682         AssertError(t, errs, "", "", "", "", "hsl")
5683 }
5684
5685 func TestRgba(t *testing.T) {
5686
5687         validate := New()
5688
5689         s := "rgba(0,31,255,0.5)"
5690         errs := validate.Var(s, "rgba")
5691         Equal(t, errs, nil)
5692
5693         s = "rgba(0,31,255,0.12)"
5694         errs = validate.Var(s, "rgba")
5695         Equal(t, errs, nil)
5696
5697         s = "rgba(12%,55%,100%,0.12)"
5698         errs = validate.Var(s, "rgba")
5699         Equal(t, errs, nil)
5700
5701         s = "rgba( 0,  31, 255, 0.5)"
5702         errs = validate.Var(s, "rgba")
5703         Equal(t, errs, nil)
5704
5705         s = "rgba(12%,55,100%,0.12)"
5706         errs = validate.Var(s, "rgba")
5707         NotEqual(t, errs, nil)
5708         AssertError(t, errs, "", "", "", "", "rgba")
5709
5710         s = "rgb(0,  31, 255)"
5711         errs = validate.Var(s, "rgba")
5712         NotEqual(t, errs, nil)
5713         AssertError(t, errs, "", "", "", "", "rgba")
5714
5715         s = "rgb(1,349,275,0.5)"
5716         errs = validate.Var(s, "rgba")
5717         NotEqual(t, errs, nil)
5718         AssertError(t, errs, "", "", "", "", "rgba")
5719
5720         s = "rgb(01,31,255,0.5)"
5721         errs = validate.Var(s, "rgba")
5722         NotEqual(t, errs, nil)
5723         AssertError(t, errs, "", "", "", "", "rgba")
5724
5725         i := 1
5726         errs = validate.Var(i, "rgba")
5727         NotEqual(t, errs, nil)
5728         AssertError(t, errs, "", "", "", "", "rgba")
5729 }
5730
5731 func TestRgb(t *testing.T) {
5732
5733         validate := New()
5734
5735         s := "rgb(0,31,255)"
5736         errs := validate.Var(s, "rgb")
5737         Equal(t, errs, nil)
5738
5739         s = "rgb(0,  31, 255)"
5740         errs = validate.Var(s, "rgb")
5741         Equal(t, errs, nil)
5742
5743         s = "rgb(10%,  50%, 100%)"
5744         errs = validate.Var(s, "rgb")
5745         Equal(t, errs, nil)
5746
5747         s = "rgb(10%,  50%, 55)"
5748         errs = validate.Var(s, "rgb")
5749         NotEqual(t, errs, nil)
5750         AssertError(t, errs, "", "", "", "", "rgb")
5751
5752         s = "rgb(1,349,275)"
5753         errs = validate.Var(s, "rgb")
5754         NotEqual(t, errs, nil)
5755         AssertError(t, errs, "", "", "", "", "rgb")
5756
5757         s = "rgb(01,31,255)"
5758         errs = validate.Var(s, "rgb")
5759         NotEqual(t, errs, nil)
5760         AssertError(t, errs, "", "", "", "", "rgb")
5761
5762         s = "rgba(0,31,255)"
5763         errs = validate.Var(s, "rgb")
5764         NotEqual(t, errs, nil)
5765         AssertError(t, errs, "", "", "", "", "rgb")
5766
5767         i := 1
5768         errs = validate.Var(i, "rgb")
5769         NotEqual(t, errs, nil)
5770         AssertError(t, errs, "", "", "", "", "rgb")
5771 }
5772
5773 func TestEmail(t *testing.T) {
5774
5775         validate := New()
5776
5777         s := "test@mail.com"
5778         errs := validate.Var(s, "email")
5779         Equal(t, errs, nil)
5780
5781         s = "Dörte@Sörensen.example.com"
5782         errs = validate.Var(s, "email")
5783         Equal(t, errs, nil)
5784
5785         s = "θσερ@εχαμπλε.ψομ"
5786         errs = validate.Var(s, "email")
5787         Equal(t, errs, nil)
5788
5789         s = "юзер@екзампл.ком"
5790         errs = validate.Var(s, "email")
5791         Equal(t, errs, nil)
5792
5793         s = "उपयोगकर्ता@उदाहरण.कॉम"
5794         errs = validate.Var(s, "email")
5795         Equal(t, errs, nil)
5796
5797         s = "用户@例子.广告"
5798         errs = validate.Var(s, "email")
5799         Equal(t, errs, nil)
5800
5801         s = ""
5802         errs = validate.Var(s, "email")
5803         NotEqual(t, errs, nil)
5804         AssertError(t, errs, "", "", "", "", "email")
5805
5806         s = "test@email"
5807         errs = validate.Var(s, "email")
5808         NotEqual(t, errs, nil)
5809         AssertError(t, errs, "", "", "", "", "email")
5810
5811         s = "test@email."
5812         errs = validate.Var(s, "email")
5813         NotEqual(t, errs, nil)
5814         AssertError(t, errs, "", "", "", "", "email")
5815
5816         s = "@email.com"
5817         errs = validate.Var(s, "email")
5818         NotEqual(t, errs, nil)
5819         AssertError(t, errs, "", "", "", "", "email")
5820
5821         i := true
5822         errs = validate.Var(i, "email")
5823         NotEqual(t, errs, nil)
5824         AssertError(t, errs, "", "", "", "", "email")
5825 }
5826
5827 func TestHexColor(t *testing.T) {
5828
5829         validate := New()
5830
5831         s := "#fff"
5832         errs := validate.Var(s, "hexcolor")
5833         Equal(t, errs, nil)
5834
5835         s = "#c2c2c2"
5836         errs = validate.Var(s, "hexcolor")
5837         Equal(t, errs, nil)
5838
5839         s = "fff"
5840         errs = validate.Var(s, "hexcolor")
5841         NotEqual(t, errs, nil)
5842         AssertError(t, errs, "", "", "", "", "hexcolor")
5843
5844         s = "fffFF"
5845         errs = validate.Var(s, "hexcolor")
5846         NotEqual(t, errs, nil)
5847         AssertError(t, errs, "", "", "", "", "hexcolor")
5848
5849         i := true
5850         errs = validate.Var(i, "hexcolor")
5851         NotEqual(t, errs, nil)
5852         AssertError(t, errs, "", "", "", "", "hexcolor")
5853 }
5854
5855 func TestHexadecimal(t *testing.T) {
5856
5857         validate := New()
5858
5859         s := "ff0044"
5860         errs := validate.Var(s, "hexadecimal")
5861         Equal(t, errs, nil)
5862
5863         s = "abcdefg"
5864         errs = validate.Var(s, "hexadecimal")
5865         NotEqual(t, errs, nil)
5866         AssertError(t, errs, "", "", "", "", "hexadecimal")
5867
5868         i := true
5869         errs = validate.Var(i, "hexadecimal")
5870         NotEqual(t, errs, nil)
5871         AssertError(t, errs, "", "", "", "", "hexadecimal")
5872 }
5873
5874 func TestNumber(t *testing.T) {
5875
5876         validate := New()
5877
5878         s := "1"
5879         errs := validate.Var(s, "number")
5880         Equal(t, errs, nil)
5881
5882         s = "+1"
5883         errs = validate.Var(s, "number")
5884         NotEqual(t, errs, nil)
5885         AssertError(t, errs, "", "", "", "", "number")
5886
5887         s = "-1"
5888         errs = validate.Var(s, "number")
5889         NotEqual(t, errs, nil)
5890         AssertError(t, errs, "", "", "", "", "number")
5891
5892         s = "1.12"
5893         errs = validate.Var(s, "number")
5894         NotEqual(t, errs, nil)
5895         AssertError(t, errs, "", "", "", "", "number")
5896
5897         s = "+1.12"
5898         errs = validate.Var(s, "number")
5899         NotEqual(t, errs, nil)
5900         AssertError(t, errs, "", "", "", "", "number")
5901
5902         s = "-1.12"
5903         errs = validate.Var(s, "number")
5904         NotEqual(t, errs, nil)
5905         AssertError(t, errs, "", "", "", "", "number")
5906
5907         s = "1."
5908         errs = validate.Var(s, "number")
5909         NotEqual(t, errs, nil)
5910         AssertError(t, errs, "", "", "", "", "number")
5911
5912         s = "1.o"
5913         errs = validate.Var(s, "number")
5914         NotEqual(t, errs, nil)
5915         AssertError(t, errs, "", "", "", "", "number")
5916
5917         i := 1
5918         errs = validate.Var(i, "number")
5919         NotEqual(t, errs, nil)
5920         AssertError(t, errs, "", "", "", "", "number")
5921 }
5922
5923 func TestNumeric(t *testing.T) {
5924
5925         validate := New()
5926
5927         s := "1"
5928         errs := validate.Var(s, "numeric")
5929         Equal(t, errs, nil)
5930
5931         s = "+1"
5932         errs = validate.Var(s, "numeric")
5933         Equal(t, errs, nil)
5934
5935         s = "-1"
5936         errs = validate.Var(s, "numeric")
5937         Equal(t, errs, nil)
5938
5939         s = "1.12"
5940         errs = validate.Var(s, "numeric")
5941         Equal(t, errs, nil)
5942
5943         s = "+1.12"
5944         errs = validate.Var(s, "numeric")
5945         Equal(t, errs, nil)
5946
5947         s = "-1.12"
5948         errs = validate.Var(s, "numeric")
5949         Equal(t, errs, nil)
5950
5951         s = "1."
5952         errs = validate.Var(s, "numeric")
5953         NotEqual(t, errs, nil)
5954         AssertError(t, errs, "", "", "", "", "numeric")
5955
5956         s = "1.o"
5957         errs = validate.Var(s, "numeric")
5958         NotEqual(t, errs, nil)
5959         AssertError(t, errs, "", "", "", "", "numeric")
5960
5961         i := 1
5962         errs = validate.Var(i, "numeric")
5963         NotEqual(t, errs, nil)
5964         AssertError(t, errs, "", "", "", "", "numeric")
5965 }
5966
5967 func TestAlphaNumeric(t *testing.T) {
5968
5969         validate := New()
5970
5971         s := "abcd123"
5972         errs := validate.Var(s, "alphanum")
5973         Equal(t, errs, nil)
5974
5975         s = "abc!23"
5976         errs = validate.Var(s, "alphanum")
5977         NotEqual(t, errs, nil)
5978         AssertError(t, errs, "", "", "", "", "alphanum")
5979
5980         errs = validate.Var(1, "alphanum")
5981         NotEqual(t, errs, nil)
5982         AssertError(t, errs, "", "", "", "", "alphanum")
5983 }
5984
5985 func TestAlpha(t *testing.T) {
5986
5987         validate := New()
5988
5989         s := "abcd"
5990         errs := validate.Var(s, "alpha")
5991         Equal(t, errs, nil)
5992
5993         s = "abc®"
5994         errs = validate.Var(s, "alpha")
5995         NotEqual(t, errs, nil)
5996         AssertError(t, errs, "", "", "", "", "alpha")
5997
5998         s = "abc÷"
5999         errs = validate.Var(s, "alpha")
6000         NotEqual(t, errs, nil)
6001         AssertError(t, errs, "", "", "", "", "alpha")
6002
6003         s = "abc1"
6004         errs = validate.Var(s, "alpha")
6005         NotEqual(t, errs, nil)
6006         AssertError(t, errs, "", "", "", "", "alpha")
6007
6008         s = "this is a test string"
6009         errs = validate.Var(s, "alpha")
6010         NotEqual(t, errs, nil)
6011         AssertError(t, errs, "", "", "", "", "alpha")
6012
6013         errs = validate.Var(1, "alpha")
6014         NotEqual(t, errs, nil)
6015         AssertError(t, errs, "", "", "", "", "alpha")
6016
6017 }
6018
6019 func TestStructStringValidation(t *testing.T) {
6020
6021         validate := New()
6022
6023         tSuccess := &TestString{
6024                 Required:  "Required",
6025                 Len:       "length==10",
6026                 Min:       "min=1",
6027                 Max:       "1234567890",
6028                 MinMax:    "12345",
6029                 Lt:        "012345678",
6030                 Lte:       "0123456789",
6031                 Gt:        "01234567890",
6032                 Gte:       "0123456789",
6033                 OmitEmpty: "",
6034                 Sub: &SubTest{
6035                         Test: "1",
6036                 },
6037                 SubIgnore: &SubTest{
6038                         Test: "",
6039                 },
6040                 Anonymous: struct {
6041                         A string `validate:"required"`
6042                 }{
6043                         A: "1",
6044                 },
6045                 Iface: &Impl{
6046                         F: "123",
6047                 },
6048         }
6049
6050         errs := validate.Struct(tSuccess)
6051         Equal(t, errs, nil)
6052
6053         tFail := &TestString{
6054                 Required:  "",
6055                 Len:       "",
6056                 Min:       "",
6057                 Max:       "12345678901",
6058                 MinMax:    "",
6059                 Lt:        "0123456789",
6060                 Lte:       "01234567890",
6061                 Gt:        "1",
6062                 Gte:       "1",
6063                 OmitEmpty: "12345678901",
6064                 Sub: &SubTest{
6065                         Test: "",
6066                 },
6067                 Anonymous: struct {
6068                         A string `validate:"required"`
6069                 }{
6070                         A: "",
6071                 },
6072                 Iface: &Impl{
6073                         F: "12",
6074                 },
6075         }
6076
6077         errs = validate.Struct(tFail)
6078
6079         // Assert Top Level
6080         NotEqual(t, errs, nil)
6081         Equal(t, len(errs.(ValidationErrors)), 13)
6082
6083         // Assert Fields
6084         AssertError(t, errs, "TestString.Required", "TestString.Required", "Required", "Required", "required")
6085         AssertError(t, errs, "TestString.Len", "TestString.Len", "Len", "Len", "len")
6086         AssertError(t, errs, "TestString.Min", "TestString.Min", "Min", "Min", "min")
6087         AssertError(t, errs, "TestString.Max", "TestString.Max", "Max", "Max", "max")
6088         AssertError(t, errs, "TestString.MinMax", "TestString.MinMax", "MinMax", "MinMax", "min")
6089         AssertError(t, errs, "TestString.Lt", "TestString.Lt", "Lt", "Lt", "lt")
6090         AssertError(t, errs, "TestString.Lte", "TestString.Lte", "Lte", "Lte", "lte")
6091         AssertError(t, errs, "TestString.Gt", "TestString.Gt", "Gt", "Gt", "gt")
6092         AssertError(t, errs, "TestString.Gte", "TestString.Gte", "Gte", "Gte", "gte")
6093         AssertError(t, errs, "TestString.OmitEmpty", "TestString.OmitEmpty", "OmitEmpty", "OmitEmpty", "max")
6094
6095         // Nested Struct Field Errs
6096         AssertError(t, errs, "TestString.Anonymous.A", "TestString.Anonymous.A", "A", "A", "required")
6097         AssertError(t, errs, "TestString.Sub.Test", "TestString.Sub.Test", "Test", "Test", "required")
6098         AssertError(t, errs, "TestString.Iface.F", "TestString.Iface.F", "F", "F", "len")
6099 }
6100
6101 func TestStructInt32Validation(t *testing.T) {
6102
6103         type TestInt32 struct {
6104                 Required  int `validate:"required"`
6105                 Len       int `validate:"len=10"`
6106                 Min       int `validate:"min=1"`
6107                 Max       int `validate:"max=10"`
6108                 MinMax    int `validate:"min=1,max=10"`
6109                 Lt        int `validate:"lt=10"`
6110                 Lte       int `validate:"lte=10"`
6111                 Gt        int `validate:"gt=10"`
6112                 Gte       int `validate:"gte=10"`
6113                 OmitEmpty int `validate:"omitempty,min=1,max=10"`
6114         }
6115
6116         tSuccess := &TestInt32{
6117                 Required:  1,
6118                 Len:       10,
6119                 Min:       1,
6120                 Max:       10,
6121                 MinMax:    5,
6122                 Lt:        9,
6123                 Lte:       10,
6124                 Gt:        11,
6125                 Gte:       10,
6126                 OmitEmpty: 0,
6127         }
6128
6129         validate := New()
6130         errs := validate.Struct(tSuccess)
6131         Equal(t, errs, nil)
6132
6133         tFail := &TestInt32{
6134                 Required:  0,
6135                 Len:       11,
6136                 Min:       -1,
6137                 Max:       11,
6138                 MinMax:    -1,
6139                 Lt:        10,
6140                 Lte:       11,
6141                 Gt:        10,
6142                 Gte:       9,
6143                 OmitEmpty: 11,
6144         }
6145
6146         errs = validate.Struct(tFail)
6147
6148         // Assert Top Level
6149         NotEqual(t, errs, nil)
6150         Equal(t, len(errs.(ValidationErrors)), 10)
6151
6152         // Assert Fields
6153         AssertError(t, errs, "TestInt32.Required", "TestInt32.Required", "Required", "Required", "required")
6154         AssertError(t, errs, "TestInt32.Len", "TestInt32.Len", "Len", "Len", "len")
6155         AssertError(t, errs, "TestInt32.Min", "TestInt32.Min", "Min", "Min", "min")
6156         AssertError(t, errs, "TestInt32.Max", "TestInt32.Max", "Max", "Max", "max")
6157         AssertError(t, errs, "TestInt32.MinMax", "TestInt32.MinMax", "MinMax", "MinMax", "min")
6158         AssertError(t, errs, "TestInt32.Lt", "TestInt32.Lt", "Lt", "Lt", "lt")
6159         AssertError(t, errs, "TestInt32.Lte", "TestInt32.Lte", "Lte", "Lte", "lte")
6160         AssertError(t, errs, "TestInt32.Gt", "TestInt32.Gt", "Gt", "Gt", "gt")
6161         AssertError(t, errs, "TestInt32.Gte", "TestInt32.Gte", "Gte", "Gte", "gte")
6162         AssertError(t, errs, "TestInt32.OmitEmpty", "TestInt32.OmitEmpty", "OmitEmpty", "OmitEmpty", "max")
6163 }
6164
6165 func TestStructUint64Validation(t *testing.T) {
6166
6167         validate := New()
6168
6169         tSuccess := &TestUint64{
6170                 Required:  1,
6171                 Len:       10,
6172                 Min:       1,
6173                 Max:       10,
6174                 MinMax:    5,
6175                 OmitEmpty: 0,
6176         }
6177
6178         errs := validate.Struct(tSuccess)
6179         Equal(t, errs, nil)
6180
6181         tFail := &TestUint64{
6182                 Required:  0,
6183                 Len:       11,
6184                 Min:       0,
6185                 Max:       11,
6186                 MinMax:    0,
6187                 OmitEmpty: 11,
6188         }
6189
6190         errs = validate.Struct(tFail)
6191
6192         // Assert Top Level
6193         NotEqual(t, errs, nil)
6194         Equal(t, len(errs.(ValidationErrors)), 6)
6195
6196         // Assert Fields
6197         AssertError(t, errs, "TestUint64.Required", "TestUint64.Required", "Required", "Required", "required")
6198         AssertError(t, errs, "TestUint64.Len", "TestUint64.Len", "Len", "Len", "len")
6199         AssertError(t, errs, "TestUint64.Min", "TestUint64.Min", "Min", "Min", "min")
6200         AssertError(t, errs, "TestUint64.Max", "TestUint64.Max", "Max", "Max", "max")
6201         AssertError(t, errs, "TestUint64.MinMax", "TestUint64.MinMax", "MinMax", "MinMax", "min")
6202         AssertError(t, errs, "TestUint64.OmitEmpty", "TestUint64.OmitEmpty", "OmitEmpty", "OmitEmpty", "max")
6203 }
6204
6205 func TestStructFloat64Validation(t *testing.T) {
6206
6207         validate := New()
6208
6209         tSuccess := &TestFloat64{
6210                 Required:  1,
6211                 Len:       10,
6212                 Min:       1,
6213                 Max:       10,
6214                 MinMax:    5,
6215                 OmitEmpty: 0,
6216         }
6217
6218         errs := validate.Struct(tSuccess)
6219         Equal(t, errs, nil)
6220
6221         tFail := &TestFloat64{
6222                 Required:  0,
6223                 Len:       11,
6224                 Min:       0,
6225                 Max:       11,
6226                 MinMax:    0,
6227                 OmitEmpty: 11,
6228         }
6229
6230         errs = validate.Struct(tFail)
6231
6232         // Assert Top Level
6233         NotEqual(t, errs, nil)
6234         Equal(t, len(errs.(ValidationErrors)), 6)
6235
6236         // Assert Fields
6237         AssertError(t, errs, "TestFloat64.Required", "TestFloat64.Required", "Required", "Required", "required")
6238         AssertError(t, errs, "TestFloat64.Len", "TestFloat64.Len", "Len", "Len", "len")
6239         AssertError(t, errs, "TestFloat64.Min", "TestFloat64.Min", "Min", "Min", "min")
6240         AssertError(t, errs, "TestFloat64.Max", "TestFloat64.Max", "Max", "Max", "max")
6241         AssertError(t, errs, "TestFloat64.MinMax", "TestFloat64.MinMax", "MinMax", "MinMax", "min")
6242         AssertError(t, errs, "TestFloat64.OmitEmpty", "TestFloat64.OmitEmpty", "OmitEmpty", "OmitEmpty", "max")
6243 }
6244
6245 func TestStructSliceValidation(t *testing.T) {
6246
6247         validate := New()
6248
6249         tSuccess := &TestSlice{
6250                 Required:  []int{1},
6251                 Len:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
6252                 Min:       []int{1, 2},
6253                 Max:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
6254                 MinMax:    []int{1, 2, 3, 4, 5},
6255                 OmitEmpty: nil,
6256         }
6257
6258         errs := validate.Struct(tSuccess)
6259         Equal(t, errs, nil)
6260
6261         tFail := &TestSlice{
6262                 Required:  nil,
6263                 Len:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
6264                 Min:       []int{},
6265                 Max:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
6266                 MinMax:    []int{},
6267                 OmitEmpty: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
6268         }
6269
6270         errs = validate.Struct(tFail)
6271         NotEqual(t, errs, nil)
6272         Equal(t, len(errs.(ValidationErrors)), 6)
6273
6274         // Assert Field Errors
6275         AssertError(t, errs, "TestSlice.Required", "TestSlice.Required", "Required", "Required", "required")
6276         AssertError(t, errs, "TestSlice.Len", "TestSlice.Len", "Len", "Len", "len")
6277         AssertError(t, errs, "TestSlice.Min", "TestSlice.Min", "Min", "Min", "min")
6278         AssertError(t, errs, "TestSlice.Max", "TestSlice.Max", "Max", "Max", "max")
6279         AssertError(t, errs, "TestSlice.MinMax", "TestSlice.MinMax", "MinMax", "MinMax", "min")
6280         AssertError(t, errs, "TestSlice.OmitEmpty", "TestSlice.OmitEmpty", "OmitEmpty", "OmitEmpty", "max")
6281
6282         fe := getError(errs, "TestSlice.Len", "TestSlice.Len")
6283         NotEqual(t, fe, nil)
6284         Equal(t, fe.Field(), "Len")
6285         Equal(t, fe.StructField(), "Len")
6286         Equal(t, fe.Namespace(), "TestSlice.Len")
6287         Equal(t, fe.StructNamespace(), "TestSlice.Len")
6288         Equal(t, fe.Tag(), "len")
6289         Equal(t, fe.ActualTag(), "len")
6290         Equal(t, fe.Param(), "10")
6291         Equal(t, fe.Kind(), reflect.Slice)
6292         Equal(t, fe.Type(), reflect.TypeOf([]int{}))
6293
6294         _, ok := fe.Value().([]int)
6295         Equal(t, ok, true)
6296
6297 }
6298
6299 func TestInvalidStruct(t *testing.T) {
6300
6301         validate := New()
6302
6303         s := &SubTest{
6304                 Test: "1",
6305         }
6306
6307         err := validate.Struct(s.Test)
6308         NotEqual(t, err, nil)
6309         Equal(t, err.Error(), "validator: (nil string)")
6310
6311         err = validate.Struct(nil)
6312         NotEqual(t, err, nil)
6313         Equal(t, err.Error(), "validator: (nil)")
6314
6315         err = validate.StructPartial(nil, "SubTest.Test")
6316         NotEqual(t, err, nil)
6317         Equal(t, err.Error(), "validator: (nil)")
6318
6319         err = validate.StructExcept(nil, "SubTest.Test")
6320         NotEqual(t, err, nil)
6321         Equal(t, err.Error(), "validator: (nil)")
6322 }
6323
6324 func TestInvalidValidatorFunction(t *testing.T) {
6325
6326         validate := New()
6327
6328         s := &SubTest{
6329                 Test: "1",
6330         }
6331
6332         PanicMatches(t, func() { validate.Var(s.Test, "zzxxBadFunction") }, "Undefined validation function 'zzxxBadFunction' on field ''")
6333 }
6334
6335 func TestCustomFieldName(t *testing.T) {
6336
6337         validate := New()
6338         validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
6339                 name := strings.SplitN(fld.Tag.Get("schema"), ",", 2)[0]
6340
6341                 if name == "-" {
6342                         return ""
6343                 }
6344
6345                 return name
6346         })
6347
6348         type A struct {
6349                 B string `schema:"b" validate:"required"`
6350                 C string `schema:"c" validate:"required"`
6351                 D []bool `schema:"d" validate:"required"`
6352                 E string `schema:"-" validate:"required"`
6353         }
6354
6355         a := &A{}
6356
6357         err := validate.Struct(a)
6358         NotEqual(t, err, nil)
6359
6360         errs := err.(ValidationErrors)
6361         Equal(t, len(errs), 4)
6362         Equal(t, getError(errs, "A.b", "A.B").Field(), "b")
6363         Equal(t, getError(errs, "A.c", "A.C").Field(), "c")
6364         Equal(t, getError(errs, "A.d", "A.D").Field(), "d")
6365         Equal(t, getError(errs, "A.E", "A.E").Field(), "E")
6366
6367         v2 := New()
6368         err = v2.Struct(a)
6369         NotEqual(t, err, nil)
6370
6371         errs = err.(ValidationErrors)
6372         Equal(t, len(errs), 4)
6373         Equal(t, getError(errs, "A.B", "A.B").Field(), "B")
6374         Equal(t, getError(errs, "A.C", "A.C").Field(), "C")
6375         Equal(t, getError(errs, "A.D", "A.D").Field(), "D")
6376         Equal(t, getError(errs, "A.E", "A.E").Field(), "E")
6377 }
6378
6379 func TestMutipleRecursiveExtractStructCache(t *testing.T) {
6380
6381         validate := New()
6382
6383         type Recursive struct {
6384                 Field *string `validate:"required,len=5,ne=string"`
6385         }
6386
6387         var test Recursive
6388
6389         current := reflect.ValueOf(test)
6390         name := "Recursive"
6391         proceed := make(chan struct{})
6392
6393         sc := validate.extractStructCache(current, name)
6394         ptr := fmt.Sprintf("%p", sc)
6395
6396         for i := 0; i < 100; i++ {
6397
6398                 go func() {
6399                         <-proceed
6400                         sc := validate.extractStructCache(current, name)
6401                         Equal(t, ptr, fmt.Sprintf("%p", sc))
6402                 }()
6403         }
6404
6405         close(proceed)
6406 }
6407
6408 // Thanks @robbrockbank, see https://github.com/go-playground/validator/issues/249
6409 func TestPointerAndOmitEmpty(t *testing.T) {
6410
6411         validate := New()
6412
6413         type Test struct {
6414                 MyInt *int `validate:"omitempty,gte=2,lte=255"`
6415         }
6416
6417         val1 := 0
6418         val2 := 256
6419
6420         t1 := Test{MyInt: &val1} // This should fail validation on gte because value is 0
6421         t2 := Test{MyInt: &val2} // This should fail validate on lte because value is 256
6422         t3 := Test{MyInt: nil}   // This should succeed validation because pointer is nil
6423
6424         errs := validate.Struct(t1)
6425         NotEqual(t, errs, nil)
6426         AssertError(t, errs, "Test.MyInt", "Test.MyInt", "MyInt", "MyInt", "gte")
6427
6428         errs = validate.Struct(t2)
6429         NotEqual(t, errs, nil)
6430         AssertError(t, errs, "Test.MyInt", "Test.MyInt", "MyInt", "MyInt", "lte")
6431
6432         errs = validate.Struct(t3)
6433         Equal(t, errs, nil)
6434
6435         type TestIface struct {
6436                 MyInt interface{} `validate:"omitempty,gte=2,lte=255"`
6437         }
6438
6439         ti1 := TestIface{MyInt: &val1} // This should fail validation on gte because value is 0
6440         ti2 := TestIface{MyInt: &val2} // This should fail validate on lte because value is 256
6441         ti3 := TestIface{MyInt: nil}   // This should succeed validation because pointer is nil
6442
6443         errs = validate.Struct(ti1)
6444         NotEqual(t, errs, nil)
6445         AssertError(t, errs, "TestIface.MyInt", "TestIface.MyInt", "MyInt", "MyInt", "gte")
6446
6447         errs = validate.Struct(ti2)
6448         NotEqual(t, errs, nil)
6449         AssertError(t, errs, "TestIface.MyInt", "TestIface.MyInt", "MyInt", "MyInt", "lte")
6450
6451         errs = validate.Struct(ti3)
6452         Equal(t, errs, nil)
6453 }
6454
6455 func TestRequired(t *testing.T) {
6456
6457         validate := New()
6458         validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
6459                 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
6460
6461                 if name == "-" {
6462                         return ""
6463                 }
6464
6465                 return name
6466         })
6467
6468         type Test struct {
6469                 Value interface{} `validate:"required"`
6470         }
6471
6472         var test Test
6473
6474         err := validate.Struct(test)
6475         NotEqual(t, err, nil)
6476         AssertError(t, err.(ValidationErrors), "Test.Value", "Test.Value", "Value", "Value", "required")
6477 }
6478
6479 func TestTranslations(t *testing.T) {
6480         en := en.New()
6481         uni := ut.New(en, en, fr.New())
6482
6483         trans, _ := uni.GetTranslator("en")
6484         fr, _ := uni.GetTranslator("fr")
6485
6486         validate := New()
6487         err := validate.RegisterTranslation("required", trans,
6488                 func(ut ut.Translator) (err error) {
6489
6490                         // using this stype because multiple translation may have to be added for the full translation
6491                         if err = ut.Add("required", "{0} is a required field", false); err != nil {
6492                                 return
6493                         }
6494
6495                         return
6496
6497                 }, func(ut ut.Translator, fe FieldError) string {
6498
6499                         t, err := ut.T(fe.Tag(), fe.Field())
6500                         if err != nil {
6501                                 fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
6502                                 return fe.(*fieldError).Error()
6503                         }
6504
6505                         return t
6506                 })
6507         Equal(t, err, nil)
6508
6509         err = validate.RegisterTranslation("required", fr,
6510                 func(ut ut.Translator) (err error) {
6511
6512                         // using this stype because multiple translation may have to be added for the full translation
6513                         if err = ut.Add("required", "{0} est un champ obligatoire", false); err != nil {
6514                                 return
6515                         }
6516
6517                         return
6518
6519                 }, func(ut ut.Translator, fe FieldError) string {
6520
6521                         t, err := ut.T(fe.Tag(), fe.Field())
6522                         if err != nil {
6523                                 fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
6524                                 return fe.(*fieldError).Error()
6525                         }
6526
6527                         return t
6528                 })
6529
6530         Equal(t, err, nil)
6531
6532         type Test struct {
6533                 Value interface{} `validate:"required"`
6534         }
6535
6536         var test Test
6537
6538         err = validate.Struct(test)
6539         NotEqual(t, err, nil)
6540
6541         errs := err.(ValidationErrors)
6542         Equal(t, len(errs), 1)
6543
6544         fe := errs[0]
6545         Equal(t, fe.Tag(), "required")
6546         Equal(t, fe.Namespace(), "Test.Value")
6547         Equal(t, fe.Translate(trans), fmt.Sprintf("%s is a required field", fe.Field()))
6548         Equal(t, fe.Translate(fr), fmt.Sprintf("%s est un champ obligatoire", fe.Field()))
6549
6550         nl := nl.New()
6551         uni2 := ut.New(nl, nl)
6552         trans2, _ := uni2.GetTranslator("nl")
6553         Equal(t, fe.Translate(trans2), "Key: 'Test.Value' Error:Field validation for 'Value' failed on the 'required' tag")
6554
6555         terrs := errs.Translate(trans)
6556         Equal(t, len(terrs), 1)
6557
6558         v, ok := terrs["Test.Value"]
6559         Equal(t, ok, true)
6560         Equal(t, v, fmt.Sprintf("%s is a required field", fe.Field()))
6561
6562         terrs = errs.Translate(fr)
6563         Equal(t, len(terrs), 1)
6564
6565         v, ok = terrs["Test.Value"]
6566         Equal(t, ok, true)
6567         Equal(t, v, fmt.Sprintf("%s est un champ obligatoire", fe.Field()))
6568
6569         type Test2 struct {
6570                 Value string `validate:"gt=1"`
6571         }
6572
6573         var t2 Test2
6574
6575         err = validate.Struct(t2)
6576         NotEqual(t, err, nil)
6577
6578         errs = err.(ValidationErrors)
6579         Equal(t, len(errs), 1)
6580
6581         fe = errs[0]
6582         Equal(t, fe.Tag(), "gt")
6583         Equal(t, fe.Namespace(), "Test2.Value")
6584         Equal(t, fe.Translate(trans), "Key: 'Test2.Value' Error:Field validation for 'Value' failed on the 'gt' tag")
6585 }
6586
6587 func TestTranslationErrors(t *testing.T) {
6588
6589         en := en.New()
6590         uni := ut.New(en, en, fr.New())
6591
6592         trans, _ := uni.GetTranslator("en")
6593         trans.Add("required", "{0} is a required field", false) // using translator outside of validator also
6594
6595         validate := New()
6596         err := validate.RegisterTranslation("required", trans,
6597                 func(ut ut.Translator) (err error) {
6598
6599                         // using this stype because multiple translation may have to be added for the full translation
6600                         if err = ut.Add("required", "{0} is a required field", false); err != nil {
6601                                 return
6602                         }
6603
6604                         return
6605
6606                 }, func(ut ut.Translator, fe FieldError) string {
6607
6608                         t, err := ut.T(fe.Tag(), fe.Field())
6609                         if err != nil {
6610                                 fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
6611                                 return fe.(*fieldError).Error()
6612                         }
6613
6614                         return t
6615                 })
6616
6617         NotEqual(t, err, nil)
6618         Equal(t, err.Error(), "error: conflicting key 'required' rule 'Unknown' with text '{0} is a required field' for locale 'en', value being ignored")
6619 }
6620
6621 func TestStructFiltered(t *testing.T) {
6622
6623         p1 := func(ns []byte) bool {
6624                 if bytes.HasSuffix(ns, []byte("NoTag")) || bytes.HasSuffix(ns, []byte("Required")) {
6625                         return false
6626                 }
6627
6628                 return true
6629         }
6630
6631         p2 := func(ns []byte) bool {
6632                 if bytes.HasSuffix(ns, []byte("SubSlice[0].Test")) ||
6633                         bytes.HasSuffix(ns, []byte("SubSlice[0]")) ||
6634                         bytes.HasSuffix(ns, []byte("SubSlice")) ||
6635                         bytes.HasSuffix(ns, []byte("Sub")) ||
6636                         bytes.HasSuffix(ns, []byte("SubIgnore")) ||
6637                         bytes.HasSuffix(ns, []byte("Anonymous")) ||
6638                         bytes.HasSuffix(ns, []byte("Anonymous.A")) {
6639                         return false
6640                 }
6641
6642                 return true
6643         }
6644
6645         p3 := func(ns []byte) bool {
6646                 return !bytes.HasSuffix(ns, []byte("SubTest.Test"))
6647         }
6648
6649         // p4 := []string{
6650         //      "A",
6651         // }
6652
6653         tPartial := &TestPartial{
6654                 NoTag:    "NoTag",
6655                 Required: "Required",
6656
6657                 SubSlice: []*SubTest{
6658                         {
6659
6660                                 Test: "Required",
6661                         },
6662                         {
6663
6664                                 Test: "Required",
6665                         },
6666                 },
6667
6668                 Sub: &SubTest{
6669                         Test: "1",
6670                 },
6671                 SubIgnore: &SubTest{
6672                         Test: "",
6673                 },
6674                 Anonymous: struct {
6675                         A             string     `validate:"required"`
6676                         ASubSlice     []*SubTest `validate:"required,dive"`
6677                         SubAnonStruct []struct {
6678                                 Test      string `validate:"required"`
6679                                 OtherTest string `validate:"required"`
6680                         } `validate:"required,dive"`
6681                 }{
6682                         A: "1",
6683                         ASubSlice: []*SubTest{
6684                                 {
6685                                         Test: "Required",
6686                                 },
6687                                 {
6688                                         Test: "Required",
6689                                 },
6690                         },
6691
6692                         SubAnonStruct: []struct {
6693                                 Test      string `validate:"required"`
6694                                 OtherTest string `validate:"required"`
6695                         }{
6696                                 {"Required", "RequiredOther"},
6697                                 {"Required", "RequiredOther"},
6698                         },
6699                 },
6700         }
6701
6702         validate := New()
6703
6704         // the following should all return no errors as everything is valid in
6705         // the default state
6706         errs := validate.StructFilteredCtx(context.Background(), tPartial, p1)
6707         Equal(t, errs, nil)
6708
6709         errs = validate.StructFiltered(tPartial, p2)
6710         Equal(t, errs, nil)
6711
6712         // this isn't really a robust test, but is ment to illustrate the ANON CASE below
6713         errs = validate.StructFiltered(tPartial.SubSlice[0], p3)
6714         Equal(t, errs, nil)
6715
6716         // mod tParial for required feild and re-test making sure invalid fields are NOT required:
6717         tPartial.Required = ""
6718
6719         // inversion and retesting Partial to generate failures:
6720         errs = validate.StructFiltered(tPartial, p1)
6721         NotEqual(t, errs, nil)
6722         AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required")
6723
6724         // reset Required field, and set nested struct
6725         tPartial.Required = "Required"
6726         tPartial.Anonymous.A = ""
6727
6728         // will pass as unset feilds is not going to be tested
6729         errs = validate.StructFiltered(tPartial, p1)
6730         Equal(t, errs, nil)
6731
6732         // will fail as unset feild is tested
6733         errs = validate.StructFiltered(tPartial, p2)
6734         NotEqual(t, errs, nil)
6735         AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required")
6736
6737         // reset nested struct and unset struct in slice
6738         tPartial.Anonymous.A = "Required"
6739         tPartial.SubSlice[0].Test = ""
6740
6741         // these will pass as unset item is NOT tested
6742         errs = validate.StructFiltered(tPartial, p1)
6743         Equal(t, errs, nil)
6744
6745         errs = validate.StructFiltered(tPartial, p2)
6746         NotEqual(t, errs, nil)
6747         AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
6748         Equal(t, len(errs.(ValidationErrors)), 1)
6749
6750         // Unset second slice member concurrently to test dive behavior:
6751         tPartial.SubSlice[1].Test = ""
6752
6753         errs = validate.StructFiltered(tPartial, p1)
6754         Equal(t, errs, nil)
6755
6756         errs = validate.StructFiltered(tPartial, p2)
6757         NotEqual(t, errs, nil)
6758         Equal(t, len(errs.(ValidationErrors)), 1)
6759         AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required")
6760
6761         // reset struct in slice, and unset struct in slice in unset posistion
6762         tPartial.SubSlice[0].Test = "Required"
6763
6764         // these will pass as the unset item is NOT tested
6765         errs = validate.StructFiltered(tPartial, p1)
6766         Equal(t, errs, nil)
6767
6768         errs = validate.StructFiltered(tPartial, p2)
6769         Equal(t, errs, nil)
6770
6771         tPartial.SubSlice[1].Test = "Required"
6772         tPartial.Anonymous.SubAnonStruct[0].Test = ""
6773
6774         // these will pass as the unset item is NOT tested
6775         errs = validate.StructFiltered(tPartial, p1)
6776         Equal(t, errs, nil)
6777
6778         errs = validate.StructFiltered(tPartial, p2)
6779         Equal(t, errs, nil)
6780
6781         dt := time.Now()
6782         err := validate.StructFiltered(&dt, func(ns []byte) bool { return true })
6783         NotEqual(t, err, nil)
6784         Equal(t, err.Error(), "validator: (nil *time.Time)")
6785 }
6786
6787 func TestRequiredPtr(t *testing.T) {
6788
6789         type Test struct {
6790                 Bool *bool `validate:"required"`
6791         }
6792
6793         validate := New()
6794
6795         f := false
6796
6797         test := Test{
6798                 Bool: &f,
6799         }
6800
6801         err := validate.Struct(test)
6802         Equal(t, err, nil)
6803
6804         tr := true
6805
6806         test.Bool = &tr
6807
6808         err = validate.Struct(test)
6809         Equal(t, err, nil)
6810
6811         test.Bool = nil
6812
6813         err = validate.Struct(test)
6814         NotEqual(t, err, nil)
6815
6816         errs, ok := err.(ValidationErrors)
6817         Equal(t, ok, true)
6818         Equal(t, len(errs), 1)
6819         AssertError(t, errs, "Test.Bool", "Test.Bool", "Bool", "Bool", "required")
6820
6821         type Test2 struct {
6822                 Bool bool `validate:"required"`
6823         }
6824
6825         var test2 Test2
6826
6827         err = validate.Struct(test2)
6828         NotEqual(t, err, nil)
6829
6830         errs, ok = err.(ValidationErrors)
6831         Equal(t, ok, true)
6832         Equal(t, len(errs), 1)
6833         AssertError(t, errs, "Test2.Bool", "Test2.Bool", "Bool", "Bool", "required")
6834
6835         test2.Bool = true
6836
6837         err = validate.Struct(test2)
6838         Equal(t, err, nil)
6839
6840         type Test3 struct {
6841                 Arr []string `validate:"required"`
6842         }
6843
6844         var test3 Test3
6845
6846         err = validate.Struct(test3)
6847         NotEqual(t, err, nil)
6848
6849         errs, ok = err.(ValidationErrors)
6850         Equal(t, ok, true)
6851         Equal(t, len(errs), 1)
6852         AssertError(t, errs, "Test3.Arr", "Test3.Arr", "Arr", "Arr", "required")
6853
6854         test3.Arr = make([]string, 0)
6855
6856         err = validate.Struct(test3)
6857         Equal(t, err, nil)
6858
6859         type Test4 struct {
6860                 Arr *[]string `validate:"required"` // I know I know pointer to array, just making sure validation works as expected...
6861         }
6862
6863         var test4 Test4
6864
6865         err = validate.Struct(test4)
6866         NotEqual(t, err, nil)
6867
6868         errs, ok = err.(ValidationErrors)
6869         Equal(t, ok, true)
6870         Equal(t, len(errs), 1)
6871         AssertError(t, errs, "Test4.Arr", "Test4.Arr", "Arr", "Arr", "required")
6872
6873         arr := make([]string, 0)
6874         test4.Arr = &arr
6875
6876         err = validate.Struct(test4)
6877         Equal(t, err, nil)
6878 }
6879
6880 func TestAlphaUnicodeValidation(t *testing.T) {
6881         tests := []struct {
6882                 param    string
6883                 expected bool
6884         }{
6885                 {"", false},
6886                 {"abc", true},
6887                 {"this is a test string", false},
6888                 {"这是一个测试字符串", true},
6889                 {"123", false},
6890                 {"<>@;.-=", false},
6891                 {"ひらがな・カタカナ、.漢字", false},
6892                 {"あいうえおfoobar", true},
6893                 {"test@example.com", false},
6894                 {"1234abcDE", false},
6895                 {"カタカナ", true},
6896         }
6897
6898         validate := New()
6899
6900         for i, test := range tests {
6901
6902                 errs := validate.Var(test.param, "alphaunicode")
6903
6904                 if test.expected {
6905                         if !IsEqual(errs, nil) {
6906                                 t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs)
6907                         }
6908                 } else {
6909                         if IsEqual(errs, nil) {
6910                                 t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs)
6911                         } else {
6912                                 val := getError(errs, "", "")
6913                                 if val.Tag() != "alphaunicode" {
6914                                         t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs)
6915                                 }
6916                         }
6917                 }
6918         }
6919 }
6920
6921 func TestAlphanumericUnicodeValidation(t *testing.T) {
6922
6923         tests := []struct {
6924                 param    string
6925                 expected bool
6926         }{
6927                 {"", false},
6928                 {"abc", true},
6929                 {"this is a test string", false},
6930                 {"这是一个测试字符串", true},
6931                 {"\u0031\u0032\u0033", true}, // unicode 5
6932                 {"123", true},
6933                 {"<>@;.-=", false},
6934                 {"ひらがな・カタカナ、.漢字", false},
6935                 {"あいうえおfoobar", true},
6936                 {"test@example.com", false},
6937                 {"1234abcDE", true},
6938                 {"カタカナ", true},
6939         }
6940
6941         validate := New()
6942
6943         for i, test := range tests {
6944
6945                 errs := validate.Var(test.param, "alphanumunicode")
6946
6947                 if test.expected {
6948                         if !IsEqual(errs, nil) {
6949                                 t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs)
6950                         }
6951                 } else {
6952                         if IsEqual(errs, nil) {
6953                                 t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs)
6954                         } else {
6955                                 val := getError(errs, "", "")
6956                                 if val.Tag() != "alphanumunicode" {
6957                                         t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs)
6958                                 }
6959                         }
6960                 }
6961         }
6962 }
6963
6964 func TestArrayStructNamespace(t *testing.T) {
6965
6966         validate := New()
6967         validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
6968                 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
6969
6970                 if name == "-" {
6971                         return ""
6972                 }
6973
6974                 return name
6975         })
6976
6977         type child struct {
6978                 Name string `json:"name" validate:"required"`
6979         }
6980         var input struct {
6981                 Children []child `json:"children" validate:"required,gt=0,dive"`
6982         }
6983         input.Children = []child{{"ok"}, {""}}
6984
6985         errs := validate.Struct(input)
6986         NotEqual(t, errs, nil)
6987
6988         ve := errs.(ValidationErrors)
6989         Equal(t, len(ve), 1)
6990         AssertError(t, errs, "children[1].name", "Children[1].Name", "name", "Name", "required")
6991 }
6992
6993 func TestMapStructNamespace(t *testing.T) {
6994
6995         validate := New()
6996         validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
6997                 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
6998
6999                 if name == "-" {
7000                         return ""
7001                 }
7002
7003                 return name
7004         })
7005
7006         type child struct {
7007                 Name string `json:"name" validate:"required"`
7008         }
7009         var input struct {
7010                 Children map[int]child `json:"children" validate:"required,gt=0,dive"`
7011         }
7012         input.Children = map[int]child{
7013                 0: {Name: "ok"},
7014                 1: {Name: ""},
7015         }
7016
7017         errs := validate.Struct(input)
7018         NotEqual(t, errs, nil)
7019
7020         ve := errs.(ValidationErrors)
7021         Equal(t, len(ve), 1)
7022         AssertError(t, errs, "children[1].name", "Children[1].Name", "name", "Name", "required")
7023 }
7024
7025 func TestFieldLevelName(t *testing.T) {
7026         type Test struct {
7027                 String string            `validate:"custom1"      json:"json1"`
7028                 Array  []string          `validate:"dive,custom2" json:"json2"`
7029                 Map    map[string]string `validate:"dive,custom3" json:"json3"`
7030                 Array2 []string          `validate:"custom4"      json:"json4"`
7031                 Map2   map[string]string `validate:"custom5"      json:"json5"`
7032         }
7033
7034         var res1, res2, res3, res4, res5, alt1, alt2, alt3, alt4, alt5 string
7035         validate := New()
7036         validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
7037                 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
7038
7039                 if name == "-" {
7040                         return ""
7041                 }
7042
7043                 return name
7044         })
7045         validate.RegisterValidation("custom1", func(fl FieldLevel) bool {
7046                 res1 = fl.FieldName()
7047                 alt1 = fl.StructFieldName()
7048                 return true
7049         })
7050         validate.RegisterValidation("custom2", func(fl FieldLevel) bool {
7051                 res2 = fl.FieldName()
7052                 alt2 = fl.StructFieldName()
7053                 return true
7054         })
7055         validate.RegisterValidation("custom3", func(fl FieldLevel) bool {
7056                 res3 = fl.FieldName()
7057                 alt3 = fl.StructFieldName()
7058                 return true
7059         })
7060         validate.RegisterValidation("custom4", func(fl FieldLevel) bool {
7061                 res4 = fl.FieldName()
7062                 alt4 = fl.StructFieldName()
7063                 return true
7064         })
7065         validate.RegisterValidation("custom5", func(fl FieldLevel) bool {
7066                 res5 = fl.FieldName()
7067                 alt5 = fl.StructFieldName()
7068                 return true
7069         })
7070
7071         test := Test{
7072                 String: "test",
7073                 Array:  []string{"1"},
7074                 Map:    map[string]string{"test": "test"},
7075         }
7076
7077         errs := validate.Struct(test)
7078         Equal(t, errs, nil)
7079         Equal(t, res1, "json1")
7080         Equal(t, alt1, "String")
7081         Equal(t, res2, "json2[0]")
7082         Equal(t, alt2, "Array[0]")
7083         Equal(t, res3, "json3[test]")
7084         Equal(t, alt3, "Map[test]")
7085         Equal(t, res4, "json4")
7086         Equal(t, alt4, "Array2")
7087         Equal(t, res5, "json5")
7088         Equal(t, alt5, "Map2")
7089 }
7090
7091 func TestValidateStructRegisterCtx(t *testing.T) {
7092
7093         var ctxVal string
7094
7095         fnCtx := func(ctx context.Context, fl FieldLevel) bool {
7096                 ctxVal = ctx.Value(&ctxVal).(string)
7097                 return true
7098         }
7099
7100         var ctxSlVal string
7101         slFn := func(ctx context.Context, sl StructLevel) {
7102                 ctxSlVal = ctx.Value(&ctxSlVal).(string)
7103         }
7104
7105         type Test struct {
7106                 Field string `validate:"val"`
7107         }
7108
7109         var tst Test
7110
7111         validate := New()
7112         validate.RegisterValidationCtx("val", fnCtx)
7113         validate.RegisterStructValidationCtx(slFn, Test{})
7114
7115         ctx := context.WithValue(context.Background(), &ctxVal, "testval")
7116         ctx = context.WithValue(ctx, &ctxSlVal, "slVal")
7117         errs := validate.StructCtx(ctx, tst)
7118         Equal(t, errs, nil)
7119         Equal(t, ctxVal, "testval")
7120         Equal(t, ctxSlVal, "slVal")
7121 }
7122
7123 func TestHostnameValidation(t *testing.T) {
7124         tests := []struct {
7125                 param    string
7126                 expected bool
7127         }{
7128                 {"test.example.com", true},
7129                 {"example.com", true},
7130                 {"example24.com", true},
7131                 {"test.example24.com", true},
7132                 {"test24.example24.com", true},
7133                 {"example", true},
7134                 {"test.example.com.", false},
7135                 {"example.com.", false},
7136                 {"example24.com.", false},
7137                 {"test.example24.com.", false},
7138                 {"test24.example24.com.", false},
7139                 {"example.", false},
7140                 {"192.168.0.1", false},
7141                 {"email@example.com", false},
7142                 {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
7143                 {"2001:cdba:0:0:0:0:3257:9652", false},
7144                 {"2001:cdba::3257:9652", false},
7145         }
7146
7147         validate := New()
7148
7149         for i, test := range tests {
7150
7151                 errs := validate.Var(test.param, "hostname")
7152
7153                 if test.expected {
7154                         if !IsEqual(errs, nil) {
7155                                 t.Fatalf("Index: %d hostname failed Error: %s", i, errs)
7156                         }
7157                 } else {
7158                         if IsEqual(errs, nil) {
7159                                 t.Fatalf("Index: %d hostname failed Error: %s", i, errs)
7160                         } else {
7161                                 val := getError(errs, "", "")
7162                                 if val.Tag() != "hostname" {
7163                                         t.Fatalf("Index: %d hostname failed Error: %s", i, errs)
7164                                 }
7165                         }
7166                 }
7167         }
7168 }
7169
7170 func TestFQDNValidation(t *testing.T) {
7171         tests := []struct {
7172                 param    string
7173                 expected bool
7174         }{
7175                 {"test.example.com", true},
7176                 {"example.com", true},
7177                 {"example24.com", true},
7178                 {"test.example24.com", true},
7179                 {"test24.example24.com", true},
7180                 {"test.example.com.", true},
7181                 {"example.com.", true},
7182                 {"example24.com.", true},
7183                 {"test.example24.com.", true},
7184                 {"test24.example24.com.", true},
7185                 {"test24.example24.com..", false},
7186                 {"example", false},
7187                 {"192.168.0.1", false},
7188                 {"email@example.com", false},
7189                 {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
7190                 {"2001:cdba:0:0:0:0:3257:9652", false},
7191                 {"2001:cdba::3257:9652", false},
7192                 {"", false},
7193         }
7194
7195         validate := New()
7196
7197         for i, test := range tests {
7198
7199                 errs := validate.Var(test.param, "fqdn")
7200
7201                 if test.expected {
7202                         if !IsEqual(errs, nil) {
7203                                 t.Fatalf("Index: %d fqdn failed Error: %s", i, errs)
7204                         }
7205                 } else {
7206                         if IsEqual(errs, nil) {
7207                                 t.Fatalf("Index: %d fqdn failed Error: %s", i, errs)
7208                         } else {
7209                                 val := getError(errs, "", "")
7210                                 if val.Tag() != "fqdn" {
7211                                         t.Fatalf("Index: %d fqdn failed Error: %s", i, errs)
7212                                 }
7213                         }
7214                 }
7215         }
7216 }
7217
7218 func TestIsDefault(t *testing.T) {
7219
7220         validate := New()
7221
7222         type Inner struct {
7223                 String string `validate:"isdefault"`
7224         }
7225         type Test struct {
7226                 String string `validate:"isdefault"`
7227                 Inner  *Inner `validate:"isdefault"`
7228         }
7229
7230         var tt Test
7231
7232         errs := validate.Struct(tt)
7233         Equal(t, errs, nil)
7234
7235         tt.Inner = &Inner{String: ""}
7236         errs = validate.Struct(tt)
7237         NotEqual(t, errs, nil)
7238
7239         fe := errs.(ValidationErrors)[0]
7240         Equal(t, fe.Field(), "Inner")
7241         Equal(t, fe.Namespace(), "Test.Inner")
7242         Equal(t, fe.Tag(), "isdefault")
7243
7244         validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
7245                 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
7246
7247                 if name == "-" {
7248                         return ""
7249                 }
7250
7251                 return name
7252         })
7253
7254         type Inner2 struct {
7255                 String string `validate:"isdefault"`
7256         }
7257
7258         type Test2 struct {
7259                 Inner Inner2 `validate:"isdefault" json:"inner"`
7260         }
7261
7262         var t2 Test2
7263         errs = validate.Struct(t2)
7264         Equal(t, errs, nil)
7265
7266         t2.Inner.String = "Changed"
7267         errs = validate.Struct(t2)
7268         NotEqual(t, errs, nil)
7269
7270         fe = errs.(ValidationErrors)[0]
7271         Equal(t, fe.Field(), "inner")
7272         Equal(t, fe.Namespace(), "Test2.inner")
7273         Equal(t, fe.Tag(), "isdefault")
7274 }
7275
7276 func TestUniqueValidation(t *testing.T) {
7277         tests := []struct {
7278                 param    interface{}
7279                 expected bool
7280         }{
7281                 {[]string{"a", "b"}, true},
7282                 {[]int{1, 2}, true},
7283                 {[]float64{1, 2}, true},
7284                 {[]interface{}{"a", "b"}, true},
7285                 {[]interface{}{"a", 1}, true},
7286                 {[]float64{1, 1}, false},
7287                 {[]int{1, 1}, false},
7288                 {[]string{"a", "a"}, false},
7289                 {[]interface{}{"a", "a"}, false},
7290                 {[]interface{}{"a", 1, "b", 1}, false},
7291         }
7292
7293         validate := New()
7294
7295         for i, test := range tests {
7296
7297                 errs := validate.Var(test.param, "unique")
7298
7299                 if test.expected {
7300                         if !IsEqual(errs, nil) {
7301                                 t.Fatalf("Index: %d unique failed Error: %v", i, errs)
7302                         }
7303                 } else {
7304                         if IsEqual(errs, nil) {
7305                                 t.Fatalf("Index: %d unique failed Error: %v", i, errs)
7306                         } else {
7307                                 val := getError(errs, "", "")
7308                                 if val.Tag() != "unique" {
7309                                         t.Fatalf("Index: %d unique failed Error: %v", i, errs)
7310                                 }
7311                         }
7312                 }
7313         }
7314         PanicMatches(t, func() { validate.Var(1.0, "unique") }, "Bad field type float64")
7315 }