OSDN Git Service

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