12 . "gopkg.in/go-playground/assert.v1"
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
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
26 // go test -cpuprofile cpu.out
27 // ./validator.test -test.bench=. -test.cpuprofile=cpu.prof
28 // go tool pprof validator.test cpu.prof
31 // go test -memprofile mem.out
38 F string `validate:"len=3"`
41 func (i *Impl) Foo() string {
46 Test string `validate:"required"`
49 type TestInterface struct {
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"`
66 SubIgnore *SubTest `validate:"-"`
68 A string `validate:"required"`
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"`
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"`
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"`
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"`
114 var validate = New(&Config{TagName: "validate"})
116 func AssertError(t *testing.T, err error, key, field, expectedTag string) {
118 errs := err.(ValidationErrors)
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)
131 func (v valuer) Value() (driver.Value, error) {
133 if v.Name == "errorme" {
134 panic("SQL Driver Valuer error: some kind of error")
135 // return nil, errors.New("some kind of error")
138 if len(v.Name) == 0 {
145 type MadeUpCustomType struct {
150 func ValidateCustomType(field reflect.Value) interface{} {
151 if cust, ok := field.Interface().(MadeUpCustomType); ok {
153 if len(cust.FirstName) == 0 || len(cust.LastName) == 0 {
157 return cust.FirstName + " " + cust.LastName
163 func OverrideIntTypeForSomeReason(field reflect.Value) interface{} {
165 if i, ok := field.Interface().(int); ok {
178 type CustomMadeUpStruct struct {
179 MadeUp MadeUpCustomType `validate:"required"`
180 OverriddenInt int `validate:"gt=1"`
183 func ValidateValuerType(field reflect.Value) interface{} {
185 if valuer, ok := field.Interface().(driver.Valuer); ok {
187 val, err := valuer.Value()
189 // handle the error how you want
199 type TestPartial struct {
201 BlankTag string `validate:""`
202 Required string `validate:"required"`
203 SubSlice []*SubTest `validate:"required,dive"`
205 SubIgnore *SubTest `validate:"-"`
207 A string `validate:"required"`
208 ASubSlice []*SubTest `validate:"required,dive"`
210 SubAnonStruct []struct {
211 Test string `validate:"required"`
212 OtherTest string `validate:"required"`
213 } `validate:"required,dive"`
217 type TestStruct struct {
218 String string `validate:"required" json:"StringVal"`
221 func StructValidationTestStructSuccess(v *Validate, structLevel *StructLevel) {
223 st := structLevel.CurrentStruct.Interface().(TestStruct)
225 if st.String != "good value" {
226 structLevel.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "badvalueteststruct")
230 func StructValidationTestStruct(v *Validate, structLevel *StructLevel) {
232 st := structLevel.CurrentStruct.Interface().(TestStruct)
234 if st.String != "bad value" {
235 structLevel.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "badvalueteststruct")
239 func StructValidationBadTestStructFieldName(v *Validate, structLevel *StructLevel) {
241 st := structLevel.CurrentStruct.Interface().(TestStruct)
243 if st.String != "bad value" {
244 structLevel.ReportError(reflect.ValueOf(st.String), "", "StringVal", "badvalueteststruct")
248 func StructValidationBadTestStructTag(v *Validate, structLevel *StructLevel) {
250 st := structLevel.CurrentStruct.Interface().(TestStruct)
252 if st.String != "bad value" {
253 structLevel.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "")
257 func StructValidationNoTestStructCustomName(v *Validate, structLevel *StructLevel) {
259 st := structLevel.CurrentStruct.Interface().(TestStruct)
261 if st.String != "bad value" {
262 structLevel.ReportError(reflect.ValueOf(st.String), "String", "", "badvalueteststruct")
266 func StructValidationTestStructInvalid(v *Validate, structLevel *StructLevel) {
268 st := structLevel.CurrentStruct.Interface().(TestStruct)
270 if st.String != "bad value" {
271 structLevel.ReportError(reflect.ValueOf(nil), "String", "StringVal", "badvalueteststruct")
275 func StructValidationTestStructReturnValidationErrors(v *Validate, structLevel *StructLevel) {
277 s := structLevel.CurrentStruct.Interface().(TestStructReturnValidationErrors)
279 errs := v.Struct(s.Inner1.Inner2)
284 structLevel.ReportValidationErrors("Inner1.", errs.(ValidationErrors))
287 func StructValidationTestStructReturnValidationErrors2(v *Validate, structLevel *StructLevel) {
289 s := structLevel.CurrentStruct.Interface().(TestStructReturnValidationErrors)
291 errs := v.Struct(s.Inner1.Inner2)
296 structLevel.ReportValidationErrors("Inner1.|Inner1JSON.", errs.(ValidationErrors))
299 type TestStructReturnValidationErrorsInner2 struct {
300 String string `validate:"required" json:"JSONString"`
303 type TestStructReturnValidationErrorsInner1 struct {
304 Inner2 *TestStructReturnValidationErrorsInner2
307 type TestStructReturnValidationErrors struct {
308 Inner1 *TestStructReturnValidationErrorsInner1 `json:"Inner1JSON"`
311 type Inner2Namespace struct {
312 String []string `validate:"dive,required" json:"JSONString"`
315 type Inner1Namespace struct {
316 Inner2 *Inner2Namespace `json:"Inner2JSON"`
319 type Namespace struct {
320 Inner1 *Inner1Namespace `json:"Inner1JSON"`
323 func TestNameNamespace(t *testing.T) {
327 FieldNameTag: "json",
331 i2 := &Inner2Namespace{String: []string{"ok", "ok", "ok"}}
332 i1 := &Inner1Namespace{Inner2: i2}
333 ns := &Namespace{Inner1: i1}
335 errs := v1.Struct(ns)
341 NotEqual(t, errs, nil)
343 ve := errs.(ValidationErrors)
345 AssertError(t, errs, "Namespace.Inner1.Inner2.String[1]", "String[1]", "required")
347 fe, ok := ve["Namespace.Inner1.Inner2.String[1]"]
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]")
356 func TestAnonymous(t *testing.T) {
358 v2 := New(&Config{TagName: "validate", FieldNameTag: "json"})
362 A string `validate:"required" json:"EH"`
365 B string `validate:"required" json:"BEE"`
368 c string `validate:"required"`
374 A string `validate:"required" json:"EH"`
379 B string `validate:"required" json:"BEE"`
384 c string `validate:"required"`
390 err := v2.Struct(tst)
391 NotEqual(t, err, nil)
393 errs := err.(ValidationErrors)
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")
401 c string `validate:"required"`
410 func TestAnonymousSameStructDifferentTags(t *testing.T) {
412 v2 := New(&Config{TagName: "validate", FieldNameTag: "json"})
420 A string `validate:"required"`
426 err := v2.Struct(tst)
427 NotEqual(t, err, nil)
429 errs := err.(ValidationErrors)
431 Equal(t, len(errs), 1)
432 AssertError(t, errs, "Test.A.A", "A", "required")
436 A string `validate:"omitempty,required"`
446 func TestStructLevelReturnValidationErrors(t *testing.T) {
452 v1.RegisterStructValidation(StructValidationTestStructReturnValidationErrors, TestStructReturnValidationErrors{})
454 inner2 := &TestStructReturnValidationErrorsInner2{
458 inner1 := &TestStructReturnValidationErrorsInner1{
462 val := &TestStructReturnValidationErrors{
466 errs := v1.Struct(val)
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")
479 func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) {
482 FieldNameTag: "json",
486 v1.RegisterStructValidation(StructValidationTestStructReturnValidationErrors2, TestStructReturnValidationErrors{})
488 inner2 := &TestStructReturnValidationErrorsInner2{
492 inner1 := &TestStructReturnValidationErrorsInner1{
496 val := &TestStructReturnValidationErrors{
500 errs := v1.Struct(val)
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")
512 fe, ok := errs.(ValidationErrors)["TestStructReturnValidationErrors.Inner1.Inner2.String"]
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")
521 fe, ok = errs.(ValidationErrors)["TestStructReturnValidationErrors.Inner1.String"]
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")
531 func TestStructLevelValidations(t *testing.T) {
538 v1.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
541 String: "good value",
544 errs := v1.Struct(tst)
545 NotEqual(t, errs, nil)
546 AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
549 v2.RegisterStructValidation(StructValidationBadTestStructFieldName, TestStruct{})
551 PanicMatches(t, func() { v2.Struct(tst) }, fieldNameRequired)
554 v3.RegisterStructValidation(StructValidationBadTestStructTag, TestStruct{})
556 PanicMatches(t, func() { v3.Struct(tst) }, tagRequired)
559 v4.RegisterStructValidation(StructValidationNoTestStructCustomName, TestStruct{})
561 errs = v4.Struct(tst)
562 NotEqual(t, errs, nil)
563 AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
566 v5.RegisterStructValidation(StructValidationTestStructInvalid, TestStruct{})
568 errs = v5.Struct(tst)
569 NotEqual(t, errs, nil)
570 AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
573 v6.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{})
575 errs = v6.Struct(tst)
579 func TestAliasTags(t *testing.T) {
581 validate.RegisterAliasValidation("iscolor", "hexcolor|rgb|rgba|hsl|hsla")
583 s := "rgb(255,255,255)"
584 errs := validate.Field(s, "iscolor")
588 errs = validate.Field(s, "omitempty,iscolor")
592 errs = validate.Field(s, "iscolor,len=5")
593 NotEqual(t, errs, nil)
594 AssertError(t, errs, "", "", "len")
597 Color string `validate:"iscolor"`
604 errs = validate.Struct(tst)
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")
613 validate.RegisterAliasValidation("req", "required,dive,iscolor")
614 arr := []string{"val1", "#fff", "#000"}
616 errs = validate.Field(arr, "req")
617 NotEqual(t, errs, nil)
618 AssertError(t, errs, "[0]", "[0]", "iscolor")
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")
623 func TestNilValidator(t *testing.T) {
625 type TestStruct struct {
626 Test string `validate:"required"`
633 fn := func(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
635 return current.String() == field.String()
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)
647 func TestStructPartial(t *testing.T) {
669 tPartial := &TestPartial{
671 Required: "Required",
673 SubSlice: []*SubTest{
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"`
699 ASubSlice: []*SubTest{
708 SubAnonStruct: []struct {
709 Test string `validate:"required"`
710 OtherTest string `validate:"required"`
712 {"Required", "RequiredOther"},
713 {"Required", "RequiredOther"},
718 // the following should all return no errors as everything is valid in
720 errs := validate.StructPartial(tPartial, p1...)
723 errs = validate.StructPartial(tPartial, p2...)
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...)
730 errs = validate.StructExcept(tPartial, p1...)
733 errs = validate.StructExcept(tPartial, p2...)
736 // mod tParial for required feild and re-test making sure invalid fields are NOT required:
737 tPartial.Required = ""
739 errs = validate.StructExcept(tPartial, p1...)
742 errs = validate.StructPartial(tPartial, p2...)
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")
750 errs = validate.StructExcept(tPartial, p2...)
751 AssertError(t, errs, "TestPartial.Required", "Required", "required")
753 // reset Required field, and set nested struct
754 tPartial.Required = "Required"
755 tPartial.Anonymous.A = ""
757 // will pass as unset feilds is not going to be tested
758 errs = validate.StructPartial(tPartial, p1...)
761 errs = validate.StructExcept(tPartial, p2...)
764 // ANON CASE the response here is strange, it clearly does what it is being told to
765 errs = validate.StructExcept(tPartial.Anonymous, p4...)
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")
773 errs = validate.StructExcept(tPartial, p1...)
774 NotEqual(t, errs, nil)
775 AssertError(t, errs, "TestPartial.Anonymous.A", "A", "required")
777 // reset nested struct and unset struct in slice
778 tPartial.Anonymous.A = "Required"
779 tPartial.SubSlice[0].Test = ""
781 // these will pass as unset item is NOT tested
782 errs = validate.StructPartial(tPartial, p1...)
785 errs = validate.StructExcept(tPartial, p2...)
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)
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)
798 // Unset second slice member concurrently to test dive behavior:
799 tPartial.SubSlice[1].Test = ""
801 errs = validate.StructPartial(tPartial, p1...)
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")
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")
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")
820 // reset struct in slice, and unset struct in slice in unset posistion
821 tPartial.SubSlice[0].Test = "Required"
823 // these will pass as the unset item is NOT tested
824 errs = validate.StructPartial(tPartial, p1...)
827 errs = validate.StructPartial(tPartial, p2...)
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")
836 errs = validate.StructExcept(tPartial, p2...)
837 NotEqual(t, errs, nil)
838 AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
840 tPartial.SubSlice[1].Test = "Required"
842 tPartial.Anonymous.SubAnonStruct[0].Test = ""
843 // these will pass as the unset item is NOT tested
844 errs = validate.StructPartial(tPartial, p1...)
847 errs = validate.StructPartial(tPartial, p2...)
850 errs = validate.StructExcept(tPartial, p1...)
851 NotEqual(t, errs, nil)
852 AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "required")
854 errs = validate.StructExcept(tPartial, p2...)
855 NotEqual(t, errs, nil)
856 AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "required")
860 func TestCrossStructLteFieldValidation(t *testing.T) {
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"`
881 now := time.Now().UTC()
882 then := now.Add(time.Hour * 5)
890 Array: []string{"val1", "val2"},
900 Array: []string{"val1"},
903 errs := validate.Struct(test)
906 test.CreatedAt = &then
911 test.Array = []string{"val1", "val2"}
913 errs = validate.Struct(test)
916 after := now.Add(time.Hour * 10)
918 test.CreatedAt = &after
923 test.Array = []string{"val1", "val2", "val3"}
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")
934 errs = validate.FieldWithValue(1, "", "ltecsfield")
935 NotEqual(t, errs, nil)
936 AssertError(t, errs, "", "", "ltecsfield")
938 errs = validate.FieldWithValue(test, now, "ltecsfield")
939 NotEqual(t, errs, nil)
940 AssertError(t, errs, "", "", "ltecsfield")
943 func TestCrossStructLtFieldValidation(t *testing.T) {
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"`
964 now := time.Now().UTC()
965 then := now.Add(time.Hour * 5)
973 Array: []string{"val1", "val2"},
983 Array: []string{"val1"},
986 errs := validate.Struct(test)
989 test.CreatedAt = &then
994 test.Array = []string{"val1", "val2"}
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")
1005 errs = validate.FieldWithValue(1, "", "ltcsfield")
1006 NotEqual(t, errs, nil)
1007 AssertError(t, errs, "", "", "ltcsfield")
1009 errs = validate.FieldWithValue(test, now, "ltcsfield")
1010 NotEqual(t, errs, nil)
1011 AssertError(t, errs, "", "", "ltcsfield")
1014 func TestCrossStructGteFieldValidation(t *testing.T) {
1017 CreatedAt *time.Time
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"`
1035 now := time.Now().UTC()
1036 then := now.Add(time.Hour * -5)
1044 Array: []string{"val1", "val2"},
1054 Array: []string{"val1", "val2", "val3"},
1057 errs := validate.Struct(test)
1060 test.CreatedAt = &then
1061 test.String = "abcd"
1065 test.Array = []string{"val1", "val2"}
1067 errs = validate.Struct(test)
1070 before := now.Add(time.Hour * -10)
1072 test.CreatedAt = &before
1077 test.Array = []string{"val1"}
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")
1088 errs = validate.FieldWithValue(1, "", "gtecsfield")
1089 NotEqual(t, errs, nil)
1090 AssertError(t, errs, "", "", "gtecsfield")
1092 errs = validate.FieldWithValue(test, now, "gtecsfield")
1093 NotEqual(t, errs, nil)
1094 AssertError(t, errs, "", "", "gtecsfield")
1097 func TestCrossStructGtFieldValidation(t *testing.T) {
1100 CreatedAt *time.Time
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"`
1118 now := time.Now().UTC()
1119 then := now.Add(time.Hour * -5)
1127 Array: []string{"val1", "val2"},
1137 Array: []string{"val1", "val2", "val3"},
1140 errs := validate.Struct(test)
1143 test.CreatedAt = &then
1144 test.String = "abcd"
1148 test.Array = []string{"val1", "val2"}
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")
1159 errs = validate.FieldWithValue(1, "", "gtcsfield")
1160 NotEqual(t, errs, nil)
1161 AssertError(t, errs, "", "", "gtcsfield")
1163 errs = validate.FieldWithValue(test, now, "gtcsfield")
1164 NotEqual(t, errs, nil)
1165 AssertError(t, errs, "", "", "gtcsfield")
1168 func TestCrossStructNeFieldValidation(t *testing.T) {
1171 CreatedAt *time.Time
1176 CreatedAt *time.Time `validate:"necsfield=Inner.CreatedAt"`
1179 now := time.Now().UTC()
1180 then := now.Add(time.Hour * 5)
1191 errs := validate.Struct(test)
1194 test.CreatedAt = &then
1196 errs = validate.Struct(test)
1197 NotEqual(t, errs, nil)
1198 AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "necsfield")
1208 arr := []string{"test"}
1214 arr2 := []string{"test"}
1215 arr3 := []string{"test", "test2"}
1218 errs = validate.FieldWithValue(s, s2, "necsfield")
1219 NotEqual(t, errs, nil)
1220 AssertError(t, errs, "", "", "necsfield")
1222 errs = validate.FieldWithValue(i2, i, "necsfield")
1223 NotEqual(t, errs, nil)
1224 AssertError(t, errs, "", "", "necsfield")
1226 errs = validate.FieldWithValue(j2, j, "necsfield")
1227 NotEqual(t, errs, nil)
1228 AssertError(t, errs, "", "", "necsfield")
1230 errs = validate.FieldWithValue(k2, k, "necsfield")
1231 NotEqual(t, errs, nil)
1232 AssertError(t, errs, "", "", "necsfield")
1234 errs = validate.FieldWithValue(arr2, arr, "necsfield")
1235 NotEqual(t, errs, nil)
1236 AssertError(t, errs, "", "", "necsfield")
1238 errs = validate.FieldWithValue(now2, now, "necsfield")
1239 NotEqual(t, errs, nil)
1240 AssertError(t, errs, "", "", "necsfield")
1242 errs = validate.FieldWithValue(arr3, arr, "necsfield")
1245 type SInner struct {
1249 type TStruct struct {
1251 CreatedAt *time.Time `validate:"necsfield=Inner"`
1263 errs = validate.Struct(test2)
1267 errs = validate.Struct(test2)
1270 errs = validate.FieldWithValue(nil, 1, "necsfield")
1274 func TestCrossStructEqFieldValidation(t *testing.T) {
1277 CreatedAt *time.Time
1282 CreatedAt *time.Time `validate:"eqcsfield=Inner.CreatedAt"`
1285 now := time.Now().UTC()
1296 errs := validate.Struct(test)
1299 newTime := time.Now().UTC()
1300 test.CreatedAt = &newTime
1302 errs = validate.Struct(test)
1303 NotEqual(t, errs, nil)
1304 AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "eqcsfield")
1312 arr := []string{"test"}
1320 arr2 := []string{"test"}
1321 arr3 := []string{"test", "test2"}
1324 errs = validate.FieldWithValue(s, s2, "eqcsfield")
1327 errs = validate.FieldWithValue(i2, i, "eqcsfield")
1330 errs = validate.FieldWithValue(j2, j, "eqcsfield")
1333 errs = validate.FieldWithValue(k2, k, "eqcsfield")
1336 errs = validate.FieldWithValue(arr2, arr, "eqcsfield")
1339 errs = validate.FieldWithValue(now2, now, "eqcsfield")
1342 errs = validate.FieldWithValue(arr3, arr, "eqcsfield")
1343 NotEqual(t, errs, nil)
1344 AssertError(t, errs, "", "", "eqcsfield")
1346 type SInner struct {
1350 type TStruct struct {
1352 CreatedAt *time.Time `validate:"eqcsfield=Inner"`
1364 errs = validate.Struct(test2)
1365 NotEqual(t, errs, nil)
1366 AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqcsfield")
1369 errs = validate.Struct(test2)
1370 NotEqual(t, errs, nil)
1371 AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqcsfield")
1373 errs = validate.FieldWithValue(nil, 1, "eqcsfield")
1374 NotEqual(t, errs, nil)
1375 AssertError(t, errs, "", "", "eqcsfield")
1378 func TestCrossNamespaceFieldValidation(t *testing.T) {
1380 type SliceStruct struct {
1384 type MapStruct struct {
1389 CreatedAt *time.Time
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
1417 CreatedAt *time.Time
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"},
1454 val := reflect.ValueOf(test)
1456 current, kind, ok := validate.GetStructFieldOK(val, "Inner.CreatedAt")
1458 Equal(t, kind, reflect.Struct)
1459 tm, ok := current.Interface().(time.Time)
1463 current, kind, ok = validate.GetStructFieldOK(val, "Inner.Slice[1]")
1465 Equal(t, kind, reflect.String)
1466 Equal(t, current.String(), "val2")
1468 current, kind, ok = validate.GetStructFieldOK(val, "Inner.CrazyNonExistantField")
1471 current, kind, ok = validate.GetStructFieldOK(val, "Inner.Slice[101]")
1474 current, kind, ok = validate.GetStructFieldOK(val, "Inner.Map[key3]")
1476 Equal(t, kind, reflect.String)
1477 Equal(t, current.String(), "val3")
1479 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapMap[key2][key2-1]")
1481 Equal(t, kind, reflect.String)
1482 Equal(t, current.String(), "val2")
1484 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapStructs[key2].Name")
1486 Equal(t, kind, reflect.String)
1487 Equal(t, current.String(), "name2")
1489 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapMapStruct[key3][key3-1].Name")
1491 Equal(t, kind, reflect.String)
1492 Equal(t, current.String(), "name3")
1494 current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceSlice[2][0]")
1496 Equal(t, kind, reflect.String)
1497 Equal(t, current.String(), "7")
1499 current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceSliceStruct[2][1].Name")
1501 Equal(t, kind, reflect.String)
1502 Equal(t, current.String(), "name8")
1504 current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceMap[1][key5]")
1506 Equal(t, kind, reflect.String)
1507 Equal(t, current.String(), "val5")
1509 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapSlice[key3][2]")
1511 Equal(t, kind, reflect.String)
1512 Equal(t, current.String(), "9")
1514 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt[2]")
1516 Equal(t, kind, reflect.String)
1517 Equal(t, current.String(), "val2")
1519 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt8[2]")
1521 Equal(t, kind, reflect.String)
1522 Equal(t, current.String(), "val2")
1524 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt16[2]")
1526 Equal(t, kind, reflect.String)
1527 Equal(t, current.String(), "val2")
1529 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt32[2]")
1531 Equal(t, kind, reflect.String)
1532 Equal(t, current.String(), "val2")
1534 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt64[2]")
1536 Equal(t, kind, reflect.String)
1537 Equal(t, current.String(), "val2")
1539 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint[2]")
1541 Equal(t, kind, reflect.String)
1542 Equal(t, current.String(), "val2")
1544 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint8[2]")
1546 Equal(t, kind, reflect.String)
1547 Equal(t, current.String(), "val2")
1549 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint16[2]")
1551 Equal(t, kind, reflect.String)
1552 Equal(t, current.String(), "val2")
1554 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint32[2]")
1556 Equal(t, kind, reflect.String)
1557 Equal(t, current.String(), "val2")
1559 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint64[2]")
1561 Equal(t, kind, reflect.String)
1562 Equal(t, current.String(), "val2")
1564 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapFloat32[3.03]")
1566 Equal(t, kind, reflect.String)
1567 Equal(t, current.String(), "val3")
1569 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapFloat64[2.02]")
1571 Equal(t, kind, reflect.String)
1572 Equal(t, current.String(), "val2")
1574 current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapBool[true]")
1576 Equal(t, kind, reflect.String)
1577 Equal(t, current.String(), "val1")
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"}},
1598 val = reflect.ValueOf(test)
1600 current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceStructs[2]")
1602 Equal(t, kind, reflect.Ptr)
1603 Equal(t, current.String(), "<*validator.SliceStruct Value>")
1604 Equal(t, current.IsNil(), true)
1606 current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceStructs[2].Name")
1608 Equal(t, kind, reflect.Ptr)
1609 Equal(t, current.String(), "<*validator.SliceStruct Value>")
1610 Equal(t, current.IsNil(), true)
1612 PanicMatches(t, func() { validate.GetStructFieldOK(reflect.ValueOf(1), "crazyinput") }, "Invalid field namespace")
1615 func TestExistsValidation(t *testing.T) {
1617 jsonText := "{ \"truthiness2\": true }"
1620 Truthiness *bool `json:"truthiness" validate:"exists,required"`
1625 err := json.Unmarshal([]byte(jsonText), &ting)
1627 NotEqual(t, ting, nil)
1628 Equal(t, ting.Truthiness, nil)
1630 errs := validate.Struct(ting)
1631 NotEqual(t, errs, nil)
1632 AssertError(t, errs, "Thing.Truthiness", "Truthiness", "exists")
1634 jsonText = "{ \"truthiness\": true }"
1636 err = json.Unmarshal([]byte(jsonText), &ting)
1638 NotEqual(t, ting, nil)
1639 Equal(t, ting.Truthiness, true)
1641 errs = validate.Struct(ting)
1645 func TestSQLValue2Validation(t *testing.T) {
1648 TagName: "validate",
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)
1660 errs := validate.Field(val, "required")
1661 NotEqual(t, errs, nil)
1662 AssertError(t, errs, "", "", "required")
1664 val.Name = "Valid Name"
1665 errs = validate.Field(val, "required")
1668 val.Name = "errorme"
1670 PanicMatches(t, func() { validate.Field(val, "required") }, "SQL Driver Valuer error: some kind of error")
1672 type myValuer valuer
1678 errs = validate.Field(myVal, "required")
1679 NotEqual(t, errs, nil)
1680 AssertError(t, errs, "", "", "required")
1682 cust := MadeUpCustomType{
1687 c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
1689 errs = validate.Struct(c)
1692 c.MadeUp.FirstName = ""
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")
1702 func TestSQLValueValidation(t *testing.T) {
1704 validate := New(&Config{TagName: "validate"})
1705 validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{})
1706 validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
1707 validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1)
1713 errs := validate.Field(val, "required")
1714 NotEqual(t, errs, nil)
1715 AssertError(t, errs, "", "", "required")
1717 val.Name = "Valid Name"
1718 errs = validate.Field(val, "required")
1721 val.Name = "errorme"
1723 PanicMatches(t, func() { errs = validate.Field(val, "required") }, "SQL Driver Valuer error: some kind of error")
1725 type myValuer valuer
1731 errs = validate.Field(myVal, "required")
1732 NotEqual(t, errs, nil)
1733 AssertError(t, errs, "", "", "required")
1735 cust := MadeUpCustomType{
1740 c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
1742 errs = validate.Struct(c)
1745 c.MadeUp.FirstName = ""
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")
1755 func TestMACValidation(t *testing.T) {
1760 {"3D:F2:C9:A6:B3:4F", true},
1761 {"3D-F2-C9-A6-B3:4F", false},
1765 {"00:25:96:FF:FE:12:34:56", true},
1766 {"0025:96FF:FE12:3456", false},
1769 for i, test := range tests {
1771 errs := validate.Field(test.param, "mac")
1774 if !IsEqual(errs, nil) {
1775 t.Fatalf("Index: %d mac failed Error: %s", i, errs)
1778 if IsEqual(errs, nil) {
1779 t.Fatalf("Index: %d mac failed Error: %s", i, errs)
1781 val := errs.(ValidationErrors)[""]
1782 if val.Tag != "mac" {
1783 t.Fatalf("Index: %d mac failed Error: %s", i, errs)
1790 func TestIPValidation(t *testing.T) {
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},
1808 for i, test := range tests {
1810 errs := validate.Field(test.param, "ip")
1813 if !IsEqual(errs, nil) {
1814 t.Fatalf("Index: %d ip failed Error: %s", i, errs)
1817 if IsEqual(errs, nil) {
1818 t.Fatalf("Index: %d ip failed Error: %s", i, errs)
1820 val := errs.(ValidationErrors)[""]
1821 if val.Tag != "ip" {
1822 t.Fatalf("Index: %d ip failed Error: %s", i, errs)
1829 func TestIPv6Validation(t *testing.T) {
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},
1846 for i, test := range tests {
1848 errs := validate.Field(test.param, "ipv6")
1851 if !IsEqual(errs, nil) {
1852 t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
1855 if IsEqual(errs, nil) {
1856 t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
1858 val := errs.(ValidationErrors)[""]
1859 if val.Tag != "ipv6" {
1860 t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
1867 func TestIPv4Validation(t *testing.T) {
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},
1884 for i, test := range tests {
1886 errs := validate.Field(test.param, "ipv4")
1889 if !IsEqual(errs, nil) {
1890 t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
1893 if IsEqual(errs, nil) {
1894 t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
1896 val := errs.(ValidationErrors)[""]
1897 if val.Tag != "ipv4" {
1898 t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
1905 func TestCIDRValidation(t *testing.T) {
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},
1925 for i, test := range tests {
1927 errs := validate.Field(test.param, "cidr")
1930 if !IsEqual(errs, nil) {
1931 t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
1934 if IsEqual(errs, nil) {
1935 t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
1937 val := errs.(ValidationErrors)[""]
1938 if val.Tag != "cidr" {
1939 t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
1946 func TestCIDRv6Validation(t *testing.T) {
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},
1966 for i, test := range tests {
1968 errs := validate.Field(test.param, "cidrv6")
1971 if !IsEqual(errs, nil) {
1972 t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
1975 if IsEqual(errs, nil) {
1976 t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
1978 val := errs.(ValidationErrors)[""]
1979 if val.Tag != "cidrv6" {
1980 t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
1987 func TestCIDRv4Validation(t *testing.T) {
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},
2007 for i, test := range tests {
2009 errs := validate.Field(test.param, "cidrv4")
2012 if !IsEqual(errs, nil) {
2013 t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
2016 if IsEqual(errs, nil) {
2017 t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
2019 val := errs.(ValidationErrors)[""]
2020 if val.Tag != "cidrv4" {
2021 t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
2028 func TestTCPAddrValidation(t *testing.T) {
2035 {"127.0.0.1:80", true},
2037 {"256.0.0.0:1", false},
2041 for i, test := range tests {
2042 errs := validate.Field(test.param, "tcp_addr")
2044 if !IsEqual(errs, nil) {
2045 t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
2048 if IsEqual(errs, nil) {
2049 t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
2051 val := errs.(ValidationErrors)[""]
2052 if val.Tag != "tcp_addr" {
2053 t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
2060 func TestTCP6AddrValidation(t *testing.T) {
2067 {"127.0.0.1:80", false},
2069 {"256.0.0.0:1", false},
2073 for i, test := range tests {
2074 errs := validate.Field(test.param, "tcp6_addr")
2076 if !IsEqual(errs, nil) {
2077 t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
2080 if IsEqual(errs, nil) {
2081 t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
2083 val := errs.(ValidationErrors)[""]
2084 if val.Tag != "tcp6_addr" {
2085 t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
2092 func TestTCP4AddrValidation(t *testing.T) {
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},
2105 for i, test := range tests {
2106 errs := validate.Field(test.param, "tcp4_addr")
2108 if !IsEqual(errs, nil) {
2109 t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
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)
2116 val := errs.(ValidationErrors)[""]
2117 if val.Tag != "tcp4_addr" {
2118 t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
2125 func TestUDPAddrValidation(t *testing.T) {
2132 {"127.0.0.1:80", true},
2134 {"256.0.0.0:1", false},
2138 for i, test := range tests {
2139 errs := validate.Field(test.param, "udp_addr")
2141 if !IsEqual(errs, nil) {
2142 t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
2145 if IsEqual(errs, nil) {
2146 t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
2148 val := errs.(ValidationErrors)[""]
2149 if val.Tag != "udp_addr" {
2150 t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
2157 func TestUDP6AddrValidation(t *testing.T) {
2164 {"127.0.0.1:80", false},
2166 {"256.0.0.0:1", false},
2170 for i, test := range tests {
2171 errs := validate.Field(test.param, "udp6_addr")
2173 if !IsEqual(errs, nil) {
2174 t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
2177 if IsEqual(errs, nil) {
2178 t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
2180 val := errs.(ValidationErrors)[""]
2181 if val.Tag != "udp6_addr" {
2182 t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
2189 func TestUDP4AddrValidation(t *testing.T) {
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},
2202 for i, test := range tests {
2203 errs := validate.Field(test.param, "udp4_addr")
2205 if !IsEqual(errs, nil) {
2206 t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
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)
2213 val := errs.(ValidationErrors)[""]
2214 if val.Tag != "udp4_addr" {
2215 t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
2222 func TestIPAddrValidation(t *testing.T) {
2228 {"127.0.0.1", true},
2229 {"127.0.0.1:80", false},
2231 {"256.0.0.0", false},
2232 {"localhost", false},
2235 for i, test := range tests {
2236 errs := validate.Field(test.param, "ip_addr")
2238 if !IsEqual(errs, nil) {
2239 t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
2242 if IsEqual(errs, nil) {
2243 t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
2245 val := errs.(ValidationErrors)[""]
2246 if val.Tag != "ip_addr" {
2247 t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
2254 func TestIP6AddrValidation(t *testing.T) {
2260 {"127.0.0.1", false}, // https://github.com/golang/go/issues/14037
2261 {"127.0.0.1:80", false},
2263 {"0:0:0:0:0:0:0:1", true},
2264 {"256.0.0.0", false},
2267 for i, test := range tests {
2268 errs := validate.Field(test.param, "ip6_addr")
2270 if !IsEqual(errs, nil) {
2271 t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
2274 if IsEqual(errs, nil) {
2275 t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
2277 val := errs.(ValidationErrors)[""]
2278 if val.Tag != "ip6_addr" {
2279 t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
2286 func TestIP4AddrValidation(t *testing.T) {
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},
2299 for i, test := range tests {
2300 errs := validate.Field(test.param, "ip4_addr")
2302 if !IsEqual(errs, nil) {
2303 t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
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)
2310 val := errs.(ValidationErrors)[""]
2311 if val.Tag != "ip4_addr" {
2312 t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
2319 func TestUnixAddrValidation(t *testing.T) {
2328 for i, test := range tests {
2329 errs := validate.Field(test.param, "unix_addr")
2331 if !IsEqual(errs, nil) {
2332 t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
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)
2339 val := errs.(ValidationErrors)[""]
2340 if val.Tag != "unix_addr" {
2341 t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
2348 func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {
2350 var m map[string]string
2352 errs := validate.Field(m, "required")
2353 NotEqual(t, errs, nil)
2354 AssertError(t, errs, "", "", "required")
2356 m = map[string]string{}
2357 errs = validate.Field(m, "required")
2361 errs = validate.Field(arr, "required")
2362 NotEqual(t, errs, nil)
2363 AssertError(t, errs, "", "", "required")
2366 errs = validate.Field(arr, "required")
2370 errs = validate.Field(s, "required")
2371 NotEqual(t, errs, nil)
2372 AssertError(t, errs, "", "", "required")
2375 errs = validate.Field(s, "required")
2379 errs = validate.Field(c, "required")
2380 NotEqual(t, errs, nil)
2381 AssertError(t, errs, "", "", "required")
2383 c = make(chan string)
2384 errs = validate.Field(c, "required")
2388 errs = validate.Field(tst, "required")
2389 NotEqual(t, errs, nil)
2390 AssertError(t, errs, "", "", "required")
2394 errs = validate.Field(tst, "required")
2397 var iface interface{}
2399 errs = validate.Field(iface, "required")
2400 NotEqual(t, errs, nil)
2401 AssertError(t, errs, "", "", "required")
2403 errs = validate.Field(iface, "omitempty,required")
2406 errs = validate.Field(iface, "")
2409 errs = validate.FieldWithValue(nil, iface, "")
2414 errs = validate.Field(f, "required")
2415 NotEqual(t, errs, nil)
2416 AssertError(t, errs, "", "", "required")
2418 f = func(name string) {}
2420 errs = validate.Field(f, "required")
2424 func TestDatePtrValidationIssueValidation(t *testing.T) {
2427 LastViewed *time.Time
2433 errs := validate.Struct(test)
2437 func TestCommaAndPipeObfuscationValidation(t *testing.T) {
2438 s := "My Name Is, |joeybloggs|"
2440 errs := validate.Field(s, "excludesall=0x2C")
2441 NotEqual(t, errs, nil)
2442 AssertError(t, errs, "", "", "excludesall")
2444 errs = validate.Field(s, "excludesall=0x7C")
2445 NotEqual(t, errs, nil)
2446 AssertError(t, errs, "", "", "excludesall")
2449 func TestBadKeyValidation(t *testing.T) {
2451 Name string `validate:"required, "`
2458 PanicMatches(t, func() { validate.Struct(tst) }, "Undefined validation function on field Name")
2461 Name string `validate:"required,,len=2"`
2468 PanicMatches(t, func() { validate.Struct(tst2) }, "Invalid validation tag on field Name")
2471 func TestInterfaceErrValidation(t *testing.T) {
2479 errs := validate.Field(v1, "len=1")
2482 errs = validate.Field(v2, "len=1")
2485 type ExternalCMD struct {
2486 Userid string `json:"userid"`
2487 Action uint32 `json:"action"`
2488 Data interface{} `json:"data,omitempty" validate:"required"`
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")
2502 type ExternalCMD2 struct {
2503 Userid string `json:"userid"`
2504 Action uint32 `json:"action"`
2505 Data interface{} `json:"data,omitempty" validate:"len=1"`
2508 s2 := &ExternalCMD2{
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")
2519 s3 := &ExternalCMD2{
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")
2531 Name string `validate:"required"`
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")
2549 type TestMapStructPtr struct {
2550 Errs map[int]interface{} `validate:"gt=0,dive,len=2"`
2553 mip := map[int]interface{}{0: &Inner{"ok"}, 3: nil, 4: &Inner{"ok"}}
2555 msp := &TestMapStructPtr{
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")
2564 type TestMultiDimensionalStructs struct {
2565 Errs [][]interface{} `validate:"gt=0,dive,dive"`
2568 var errStructArray [][]interface{}
2570 errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
2571 errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
2573 tms := &TestMultiDimensionalStructs{
2574 Errs: errStructArray,
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")
2585 type TestMultiDimensionalStructsPtr2 struct {
2586 Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
2589 var errStructPtr2Array [][]*Inner
2591 errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
2592 errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
2593 errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
2595 tmsp2 := &TestMultiDimensionalStructsPtr2{
2596 Errs: errStructPtr2Array,
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")
2609 m := map[int]interface{}{0: "ok", 3: "", 4: "ok"}
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")
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")
2621 arr := []interface{}{"ok", "", "ok"}
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")
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")
2633 type MyStruct struct {
2643 errs = validate.Struct(a)
2647 func TestMapDiveValidation(t *testing.T) {
2649 n := map[int]interface{}{0: nil}
2650 errs := validate.Field(n, "omitempty,required")
2653 m := map[int]string{0: "ok", 3: "", 4: "ok"}
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")
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")
2666 Name string `validate:"required"`
2669 type TestMapStruct struct {
2670 Errs map[int]Inner `validate:"gt=0,dive"`
2673 mi := map[int]Inner{0: {"ok"}, 3: {""}, 4: {"ok"}}
2675 ms := &TestMapStruct{
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")
2684 // for full test coverage
2685 s := fmt.Sprint(errs.Error())
2688 type TestMapTimeStruct struct {
2689 Errs map[int]*time.Time `validate:"gt=0,dive,required"`
2692 t1 := time.Now().UTC()
2694 mta := map[int]*time.Time{0: &t1, 3: nil, 4: nil}
2696 mt := &TestMapTimeStruct{
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")
2706 type TestMapStructPtr struct {
2707 Errs map[int]*Inner `validate:"gt=0,dive,required"`
2710 mip := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
2712 msp := &TestMapStructPtr{
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")
2721 type TestMapStructPtr2 struct {
2722 Errs map[int]*Inner `validate:"gt=0,dive,omitempty,required"`
2725 mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
2727 msp2 := &TestMapStructPtr2{
2731 errs = validate.Struct(msp2)
2735 func TestArrayDiveValidation(t *testing.T) {
2737 arr := []string{"ok", "", "ok"}
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")
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")
2749 type BadDive struct {
2750 Name string `validate:"dive"`
2757 PanicMatches(t, func() { validate.Struct(bd) }, "dive error! can't dive on a non slice or map")
2760 Errs []string `validate:"gt=0,dive,required"`
2764 Errs: []string{"ok", "", "ok"},
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")
2773 Errs: []string{"ok", "ok", ""},
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")
2781 type TestMultiDimensional struct {
2782 Errs [][]string `validate:"gt=0,dive,dive,required"`
2785 var errArray [][]string
2787 errArray = append(errArray, []string{"ok", "", ""})
2788 errArray = append(errArray, []string{"ok", "", ""})
2790 tm := &TestMultiDimensional{
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")
2803 Name string `validate:"required"`
2806 type TestMultiDimensionalStructs struct {
2807 Errs [][]Inner `validate:"gt=0,dive,dive"`
2810 var errStructArray [][]Inner
2812 errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
2813 errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
2815 tms := &TestMultiDimensionalStructs{
2816 Errs: errStructArray,
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")
2827 type TestMultiDimensionalStructsPtr struct {
2828 Errs [][]*Inner `validate:"gt=0,dive,dive"`
2831 var errStructPtrArray [][]*Inner
2833 errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
2834 errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
2835 errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, nil})
2837 tmsp := &TestMultiDimensionalStructsPtr{
2838 Errs: errStructPtrArray,
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")
2850 // for full test coverage
2851 s := fmt.Sprint(errs.Error())
2854 type TestMultiDimensionalStructsPtr2 struct {
2855 Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
2858 var errStructPtr2Array [][]*Inner
2860 errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
2861 errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
2862 errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
2864 tmsp2 := &TestMultiDimensionalStructsPtr2{
2865 Errs: errStructPtr2Array,
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")
2878 type TestMultiDimensionalStructsPtr3 struct {
2879 Errs [][]*Inner `validate:"gt=0,dive,dive,omitempty"`
2882 var errStructPtr3Array [][]*Inner
2884 errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
2885 errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
2886 errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, nil})
2888 tmsp3 := &TestMultiDimensionalStructsPtr3{
2889 Errs: errStructPtr3Array,
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")
2901 type TestMultiDimensionalTimeTime struct {
2902 Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
2905 var errTimePtr3Array [][]*time.Time
2907 t1 := time.Now().UTC()
2908 t2 := time.Now().UTC()
2909 t3 := time.Now().UTC().Add(time.Hour * 24)
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})
2915 tmtp3 := &TestMultiDimensionalTimeTime{
2916 Errs: errTimePtr3Array,
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")
2926 type TestMultiDimensionalTimeTime2 struct {
2927 Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
2930 var errTimeArray [][]*time.Time
2932 t1 = time.Now().UTC()
2933 t2 = time.Now().UTC()
2934 t3 = time.Now().UTC().Add(time.Hour * 24)
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})
2940 tmtp := &TestMultiDimensionalTimeTime2{
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")
2952 func TestNilStructPointerValidation(t *testing.T) {
2958 Inner *Inner `validate:"omitempty"`
2969 errs := validate.Struct(outer)
2976 errs = validate.Struct(outer)
2979 type Inner2 struct {
2983 type Outer2 struct {
2984 Inner2 *Inner2 `validate:"required"`
2995 errs = validate.Struct(outer2)
3002 errs = validate.Struct(outer2)
3003 NotEqual(t, errs, nil)
3004 AssertError(t, errs, "Outer2.Inner2", "Inner2", "required")
3006 type Inner3 struct {
3010 type Outer3 struct {
3022 errs = validate.Struct(outer3)
3025 type Inner4 struct {
3029 type Outer4 struct {
3030 Inner4 *Inner4 `validate:"-"`
3041 errs = validate.Struct(outer4)
3045 func TestSSNValidation(t *testing.T) {
3051 {"00-90-8787", false},
3052 {"66690-76", false},
3053 {"191 60 2869", true},
3054 {"191-60-2869", true},
3057 for i, test := range tests {
3059 errs := validate.Field(test.param, "ssn")
3062 if !IsEqual(errs, nil) {
3063 t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
3066 if IsEqual(errs, nil) {
3067 t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
3069 val := errs.(ValidationErrors)[""]
3070 if val.Tag != "ssn" {
3071 t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
3078 func TestLongitudeValidation(t *testing.T) {
3087 {"+382.3811", false},
3088 {"23.11111111", true},
3091 for i, test := range tests {
3093 errs := validate.Field(test.param, "longitude")
3096 if !IsEqual(errs, nil) {
3097 t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
3100 if IsEqual(errs, nil) {
3101 t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
3103 val := errs.(ValidationErrors)[""]
3104 if val.Tag != "longitude" {
3105 t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
3112 func TestLatitudeValidation(t *testing.T) {
3120 {"47.1231231", true},
3125 for i, test := range tests {
3127 errs := validate.Field(test.param, "latitude")
3130 if !IsEqual(errs, nil) {
3131 t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
3134 if IsEqual(errs, nil) {
3135 t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
3137 val := errs.(ValidationErrors)[""]
3138 if val.Tag != "latitude" {
3139 t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
3146 func TestDataURIValidation(t *testing.T) {
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},
3162 {"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
3165 for i, test := range tests {
3167 errs := validate.Field(test.param, "datauri")
3170 if !IsEqual(errs, nil) {
3171 t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
3174 if IsEqual(errs, nil) {
3175 t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
3177 val := errs.(ValidationErrors)[""]
3178 if val.Tag != "datauri" {
3179 t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
3186 func TestMultibyteValidation(t *testing.T) {
3195 {"ひらがな・カタカナ、.漢字", true},
3196 {"あいうえお foobar", true},
3197 {"test@example.com", true},
3198 {"test@example.com", true},
3199 {"1234abcDExyz", true},
3203 for i, test := range tests {
3205 errs := validate.Field(test.param, "multibyte")
3208 if !IsEqual(errs, nil) {
3209 t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
3212 if IsEqual(errs, nil) {
3213 t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
3215 val := errs.(ValidationErrors)[""]
3216 if val.Tag != "multibyte" {
3217 t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
3224 func TestPrintableASCIIValidation(t *testing.T) {
3235 {"0987654321", true},
3236 {"test@example.com", true},
3237 {"1234abcDEF", true},
3238 {"newline\n", false},
3239 {"\x19test\x7F", false},
3242 for i, test := range tests {
3244 errs := validate.Field(test.param, "printascii")
3247 if !IsEqual(errs, nil) {
3248 t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
3251 if IsEqual(errs, nil) {
3252 t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
3254 val := errs.(ValidationErrors)[""]
3255 if val.Tag != "printascii" {
3256 t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
3263 func TestASCIIValidation(t *testing.T) {
3274 {"0987654321", true},
3275 {"test@example.com", true},
3276 {"1234abcDEF", true},
3280 for i, test := range tests {
3282 errs := validate.Field(test.param, "ascii")
3285 if !IsEqual(errs, nil) {
3286 t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
3289 if IsEqual(errs, nil) {
3290 t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
3292 val := errs.(ValidationErrors)[""]
3293 if val.Tag != "ascii" {
3294 t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
3301 func TestUUID5Validation(t *testing.T) {
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},
3315 for i, test := range tests {
3317 errs := validate.Field(test.param, "uuid5")
3320 if !IsEqual(errs, nil) {
3321 t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
3324 if IsEqual(errs, nil) {
3325 t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
3327 val := errs.(ValidationErrors)[""]
3328 if val.Tag != "uuid5" {
3329 t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
3336 func TestUUID4Validation(t *testing.T) {
3342 {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
3343 {"a987fbc9-4bed-5078-af07-9141ba07c9f3", false},
3345 {"57b73598-8764-4ad0-a76a-679bb6640eb1", true},
3346 {"625e63f3-58f5-40b7-83a1-a72ad31acffb", true},
3349 for i, test := range tests {
3351 errs := validate.Field(test.param, "uuid4")
3354 if !IsEqual(errs, nil) {
3355 t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
3358 if IsEqual(errs, nil) {
3359 t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
3361 val := errs.(ValidationErrors)[""]
3362 if val.Tag != "uuid4" {
3363 t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
3370 func TestUUID3Validation(t *testing.T) {
3376 {"412452646", false},
3377 {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
3378 {"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false},
3379 {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
3382 for i, test := range tests {
3384 errs := validate.Field(test.param, "uuid3")
3387 if !IsEqual(errs, nil) {
3388 t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
3391 if IsEqual(errs, nil) {
3392 t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
3394 val := errs.(ValidationErrors)[""]
3395 if val.Tag != "uuid3" {
3396 t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
3403 func TestUUIDValidation(t *testing.T) {
3409 {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
3410 {"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false},
3411 {"a987fbc94bed3078cf079141ba07c9f3", false},
3413 {"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false},
3414 {"aaaaaaaa-1111-1111-aaag-111111111111", false},
3415 {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
3418 for i, test := range tests {
3420 errs := validate.Field(test.param, "uuid")
3423 if !IsEqual(errs, nil) {
3424 t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
3427 if IsEqual(errs, nil) {
3428 t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
3430 val := errs.(ValidationErrors)[""]
3431 if val.Tag != "uuid" {
3432 t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
3439 func TestISBNValidation(t *testing.T) {
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},
3456 for i, test := range tests {
3458 errs := validate.Field(test.param, "isbn")
3461 if !IsEqual(errs, nil) {
3462 t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
3465 if IsEqual(errs, nil) {
3466 t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
3468 val := errs.(ValidationErrors)[""]
3469 if val.Tag != "isbn" {
3470 t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
3477 func TestISBN13Validation(t *testing.T) {
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},
3493 for i, test := range tests {
3495 errs := validate.Field(test.param, "isbn13")
3498 if !IsEqual(errs, nil) {
3499 t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
3502 if IsEqual(errs, nil) {
3503 t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
3505 val := errs.(ValidationErrors)[""]
3506 if val.Tag != "isbn13" {
3507 t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
3514 func TestISBN10Validation(t *testing.T) {
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},
3531 for i, test := range tests {
3533 errs := validate.Field(test.param, "isbn10")
3536 if !IsEqual(errs, nil) {
3537 t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
3540 if IsEqual(errs, nil) {
3541 t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
3543 val := errs.(ValidationErrors)[""]
3544 if val.Tag != "isbn10" {
3545 t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
3552 func TestExcludesRuneValidation(t *testing.T) {
3555 Value string `validate:"excludesrune=☻"`
3559 {Value: "a☺b☻c☹d", Tag: "excludesrune=☻", ExpectedNil: false},
3560 {Value: "abcd", Tag: "excludesrune=☻", ExpectedNil: true},
3563 for i, s := range tests {
3564 errs := validate.Field(s.Value, s.Tag)
3566 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3567 t.Fatalf("Index: %d failed Error: %s", i, errs)
3570 errs = validate.Struct(s)
3572 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3573 t.Fatalf("Index: %d failed Error: %s", i, errs)
3578 func TestExcludesAllValidation(t *testing.T) {
3581 Value string `validate:"excludesall=@!{}[]"`
3585 {Value: "abcd@!jfk", Tag: "excludesall=@!{}[]", ExpectedNil: false},
3586 {Value: "abcdefg", Tag: "excludesall=@!{}[]", ExpectedNil: true},
3589 for i, s := range tests {
3590 errs := validate.Field(s.Value, s.Tag)
3592 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3593 t.Fatalf("Index: %d failed Error: %s", i, errs)
3596 errs = validate.Struct(s)
3598 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3599 t.Fatalf("Index: %d failed Error: %s", i, errs)
3603 username := "joeybloggs "
3605 errs := validate.Field(username, "excludesall=@ ")
3606 NotEqual(t, errs, nil)
3607 AssertError(t, errs, "", "", "excludesall")
3611 errs = validate.Field(excluded, "excludesall=!@#$%^&*()_+.0x2C?")
3612 NotEqual(t, errs, nil)
3613 AssertError(t, errs, "", "", "excludesall")
3617 errs = validate.Field(excluded, "excludesall=!@#$%^&*()_+.0x2C=?")
3618 NotEqual(t, errs, nil)
3619 AssertError(t, errs, "", "", "excludesall")
3622 func TestExcludesValidation(t *testing.T) {
3625 Value string `validate:"excludes=@"`
3629 {Value: "abcd@!jfk", Tag: "excludes=@", ExpectedNil: false},
3630 {Value: "abcdq!jfk", Tag: "excludes=@", ExpectedNil: true},
3633 for i, s := range tests {
3634 errs := validate.Field(s.Value, s.Tag)
3636 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3637 t.Fatalf("Index: %d failed Error: %s", i, errs)
3640 errs = validate.Struct(s)
3642 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3643 t.Fatalf("Index: %d failed Error: %s", i, errs)
3648 func TestContainsRuneValidation(t *testing.T) {
3651 Value string `validate:"containsrune=☻"`
3655 {Value: "a☺b☻c☹d", Tag: "containsrune=☻", ExpectedNil: true},
3656 {Value: "abcd", Tag: "containsrune=☻", ExpectedNil: false},
3659 for i, s := range tests {
3660 errs := validate.Field(s.Value, s.Tag)
3662 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3663 t.Fatalf("Index: %d failed Error: %s", i, errs)
3666 errs = validate.Struct(s)
3668 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3669 t.Fatalf("Index: %d failed Error: %s", i, errs)
3674 func TestContainsAnyValidation(t *testing.T) {
3677 Value string `validate:"containsany=@!{}[]"`
3681 {Value: "abcd@!jfk", Tag: "containsany=@!{}[]", ExpectedNil: true},
3682 {Value: "abcdefg", Tag: "containsany=@!{}[]", ExpectedNil: false},
3685 for i, s := range tests {
3686 errs := validate.Field(s.Value, s.Tag)
3688 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3689 t.Fatalf("Index: %d failed Error: %s", i, errs)
3692 errs = validate.Struct(s)
3694 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3695 t.Fatalf("Index: %d failed Error: %s", i, errs)
3700 func TestContainsValidation(t *testing.T) {
3703 Value string `validate:"contains=@"`
3707 {Value: "abcd@!jfk", Tag: "contains=@", ExpectedNil: true},
3708 {Value: "abcdq!jfk", Tag: "contains=@", ExpectedNil: false},
3711 for i, s := range tests {
3712 errs := validate.Field(s.Value, s.Tag)
3714 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3715 t.Fatalf("Index: %d failed Error: %s", i, errs)
3718 errs = validate.Struct(s)
3720 if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
3721 t.Fatalf("Index: %d failed Error: %s", i, errs)
3726 func TestIsNeFieldValidation(t *testing.T) {
3734 arr := []string{"test"}
3735 now := time.Now().UTC()
3743 arr2 := []string{"test", "test2"}
3744 arr3 := []string{"test"}
3747 errs := validate.FieldWithValue(s, s2, "nefield")
3750 errs = validate.FieldWithValue(i2, i, "nefield")
3753 errs = validate.FieldWithValue(j2, j, "nefield")
3756 errs = validate.FieldWithValue(k2, k, "nefield")
3759 errs = validate.FieldWithValue(arr2, arr, "nefield")
3762 errs = validate.FieldWithValue(now2, now, "nefield")
3763 NotEqual(t, errs, nil)
3764 AssertError(t, errs, "", "", "nefield")
3766 errs = validate.FieldWithValue(arr3, arr, "nefield")
3767 NotEqual(t, errs, nil)
3768 AssertError(t, errs, "", "", "nefield")
3771 Start *time.Time `validate:"nefield=End"`
3780 errs = validate.Struct(sv)
3781 NotEqual(t, errs, nil)
3782 AssertError(t, errs, "Test.Start", "Start", "nefield")
3784 now3 := time.Now().UTC()
3791 errs = validate.Struct(sv)
3794 errs = validate.FieldWithValue(nil, 1, "nefield")
3797 errs = validate.FieldWithValue(sv, now, "nefield")
3801 Start *time.Time `validate:"nefield=NonExistantField"`
3810 errs = validate.Struct(sv2)
3814 func TestIsNeValidation(t *testing.T) {
3822 arr := []string{"test"}
3823 now := time.Now().UTC()
3825 errs := validate.Field(s, "ne=abcd")
3828 errs = validate.Field(i, "ne=1")
3831 errs = validate.Field(j, "ne=1")
3834 errs = validate.Field(k, "ne=1.543")
3837 errs = validate.Field(arr, "ne=2")
3840 errs = validate.Field(arr, "ne=1")
3841 NotEqual(t, errs, nil)
3842 AssertError(t, errs, "", "", "ne")
3844 PanicMatches(t, func() { validate.Field(now, "ne=now") }, "Bad field type time.Time")
3847 func TestIsEqFieldValidation(t *testing.T) {
3855 arr := []string{"test"}
3856 now := time.Now().UTC()
3864 arr2 := []string{"test"}
3865 arr3 := []string{"test", "test2"}
3868 errs := validate.FieldWithValue(s, s2, "eqfield")
3871 errs = validate.FieldWithValue(i2, i, "eqfield")
3874 errs = validate.FieldWithValue(j2, j, "eqfield")
3877 errs = validate.FieldWithValue(k2, k, "eqfield")
3880 errs = validate.FieldWithValue(arr2, arr, "eqfield")
3883 errs = validate.FieldWithValue(now2, now, "eqfield")
3886 errs = validate.FieldWithValue(arr3, arr, "eqfield")
3887 NotEqual(t, errs, nil)
3888 AssertError(t, errs, "", "", "eqfield")
3891 Start *time.Time `validate:"eqfield=End"`
3900 errs = validate.Struct(sv)
3903 now3 := time.Now().UTC()
3910 errs = validate.Struct(sv)
3911 NotEqual(t, errs, nil)
3912 AssertError(t, errs, "Test.Start", "Start", "eqfield")
3914 errs = validate.FieldWithValue(nil, 1, "eqfield")
3915 NotEqual(t, errs, nil)
3916 AssertError(t, errs, "", "", "eqfield")
3918 channel := make(chan string)
3919 errs = validate.FieldWithValue(5, channel, "eqfield")
3920 NotEqual(t, errs, nil)
3921 AssertError(t, errs, "", "", "eqfield")
3923 errs = validate.FieldWithValue(5, now, "eqfield")
3924 NotEqual(t, errs, nil)
3925 AssertError(t, errs, "", "", "eqfield")
3928 Start *time.Time `validate:"eqfield=NonExistantField"`
3937 errs = validate.Struct(sv2)
3938 NotEqual(t, errs, nil)
3939 AssertError(t, errs, "Test2.Start", "Start", "eqfield")
3945 type TStruct struct {
3947 CreatedAt *time.Time `validate:"eqfield=Inner"`
3959 errs = validate.Struct(test)
3960 NotEqual(t, errs, nil)
3961 AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqfield")
3964 func TestIsEqValidation(t *testing.T) {
3972 arr := []string{"test"}
3973 now := time.Now().UTC()
3975 errs := validate.Field(s, "eq=abcd")
3978 errs = validate.Field(i, "eq=1")
3981 errs = validate.Field(j, "eq=1")
3984 errs = validate.Field(k, "eq=1.543")
3987 errs = validate.Field(arr, "eq=1")
3990 errs = validate.Field(arr, "eq=2")
3991 NotEqual(t, errs, nil)
3992 AssertError(t, errs, "", "", "eq")
3994 PanicMatches(t, func() { validate.Field(now, "eq=now") }, "Bad field type time.Time")
3997 func TestBase64Validation(t *testing.T) {
4001 errs := validate.Field(s, "base64")
4004 s = "dGhpIGlzIGEgdGVzdCBiYXNlNjQ="
4005 errs = validate.Field(s, "base64")
4009 errs = validate.Field(s, "base64")
4010 NotEqual(t, errs, nil)
4011 AssertError(t, errs, "", "", "base64")
4013 s = "dW5pY29ybg== foo bar"
4014 errs = validate.Field(s, "base64")
4015 NotEqual(t, errs, nil)
4016 AssertError(t, errs, "", "", "base64")
4019 func TestNoStructLevelValidation(t *testing.T) {
4022 Test string `validate:"len=5"`
4026 InnerStruct *Inner `validate:"required,nostructlevel"`
4033 errs := validate.Struct(outer)
4034 NotEqual(t, errs, nil)
4035 AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required")
4045 errs = validate.Struct(outer)
4049 func TestStructOnlyValidation(t *testing.T) {
4052 Test string `validate:"len=5"`
4056 InnerStruct *Inner `validate:"required,structonly"`
4063 errs := validate.Struct(outer)
4064 NotEqual(t, errs, nil)
4065 AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required")
4075 errs = validate.Struct(outer)
4079 func TestGtField(t *testing.T) {
4081 type TimeTest struct {
4082 Start *time.Time `validate:"required,gt"`
4083 End *time.Time `validate:"required,gt,gtfield=Start"`
4087 start := now.Add(time.Hour * 24)
4088 end := start.Add(time.Hour * 24)
4090 timeTest := &TimeTest{
4095 errs := validate.Struct(timeTest)
4098 timeTest = &TimeTest{
4103 errs = validate.Struct(timeTest)
4104 NotEqual(t, errs, nil)
4105 AssertError(t, errs, "TimeTest.End", "End", "gtfield")
4107 errs = validate.FieldWithValue(&start, &end, "gtfield")
4110 errs = validate.FieldWithValue(&end, &start, "gtfield")
4111 NotEqual(t, errs, nil)
4112 AssertError(t, errs, "", "", "gtfield")
4114 errs = validate.FieldWithValue(&timeTest, &end, "gtfield")
4115 NotEqual(t, errs, nil)
4117 errs = validate.FieldWithValue("test", "test bigger", "gtfield")
4120 type IntTest struct {
4121 Val1 int `validate:"required"`
4122 Val2 int `validate:"required,gtfield=Val1"`
4125 intTest := &IntTest{
4130 errs = validate.Struct(intTest)
4138 errs = validate.Struct(intTest)
4139 NotEqual(t, errs, nil)
4140 AssertError(t, errs, "IntTest.Val2", "Val2", "gtfield")
4142 errs = validate.FieldWithValue(int(1), int(5), "gtfield")
4145 errs = validate.FieldWithValue(int(5), int(1), "gtfield")
4146 NotEqual(t, errs, nil)
4147 AssertError(t, errs, "", "", "gtfield")
4149 type UIntTest struct {
4150 Val1 uint `validate:"required"`
4151 Val2 uint `validate:"required,gtfield=Val1"`
4154 uIntTest := &UIntTest{
4159 errs = validate.Struct(uIntTest)
4162 uIntTest = &UIntTest{
4167 errs = validate.Struct(uIntTest)
4168 NotEqual(t, errs, nil)
4169 AssertError(t, errs, "UIntTest.Val2", "Val2", "gtfield")
4171 errs = validate.FieldWithValue(uint(1), uint(5), "gtfield")
4174 errs = validate.FieldWithValue(uint(5), uint(1), "gtfield")
4175 NotEqual(t, errs, nil)
4176 AssertError(t, errs, "", "", "gtfield")
4178 type FloatTest struct {
4179 Val1 float64 `validate:"required"`
4180 Val2 float64 `validate:"required,gtfield=Val1"`
4183 floatTest := &FloatTest{
4188 errs = validate.Struct(floatTest)
4191 floatTest = &FloatTest{
4196 errs = validate.Struct(floatTest)
4197 NotEqual(t, errs, nil)
4198 AssertError(t, errs, "FloatTest.Val2", "Val2", "gtfield")
4200 errs = validate.FieldWithValue(float32(1), float32(5), "gtfield")
4203 errs = validate.FieldWithValue(float32(5), float32(1), "gtfield")
4204 NotEqual(t, errs, nil)
4205 AssertError(t, errs, "", "", "gtfield")
4207 errs = validate.FieldWithValue(nil, 1, "gtfield")
4208 NotEqual(t, errs, nil)
4209 AssertError(t, errs, "", "", "gtfield")
4211 errs = validate.FieldWithValue(5, "T", "gtfield")
4212 NotEqual(t, errs, nil)
4213 AssertError(t, errs, "", "", "gtfield")
4215 errs = validate.FieldWithValue(5, start, "gtfield")
4216 NotEqual(t, errs, nil)
4217 AssertError(t, errs, "", "", "gtfield")
4219 type TimeTest2 struct {
4220 Start *time.Time `validate:"required"`
4221 End *time.Time `validate:"required,gtfield=NonExistantField"`
4224 timeTest2 := &TimeTest2{
4229 errs = validate.Struct(timeTest2)
4230 NotEqual(t, errs, nil)
4231 AssertError(t, errs, "TimeTest2.End", "End", "gtfield")
4234 func TestLtField(t *testing.T) {
4236 type TimeTest struct {
4237 Start *time.Time `validate:"required,lt,ltfield=End"`
4238 End *time.Time `validate:"required,lt"`
4242 start := now.Add(time.Hour * 24 * -1 * 2)
4243 end := start.Add(time.Hour * 24)
4245 timeTest := &TimeTest{
4250 errs := validate.Struct(timeTest)
4253 timeTest = &TimeTest{
4258 errs = validate.Struct(timeTest)
4259 NotEqual(t, errs, nil)
4260 AssertError(t, errs, "TimeTest.Start", "Start", "ltfield")
4262 errs = validate.FieldWithValue(&end, &start, "ltfield")
4265 errs = validate.FieldWithValue(&start, &end, "ltfield")
4266 NotEqual(t, errs, nil)
4267 AssertError(t, errs, "", "", "ltfield")
4269 errs = validate.FieldWithValue(timeTest, &end, "ltfield")
4270 NotEqual(t, errs, nil)
4271 AssertError(t, errs, "", "", "ltfield")
4273 errs = validate.FieldWithValue("test", "tes", "ltfield")
4276 type IntTest struct {
4277 Val1 int `validate:"required"`
4278 Val2 int `validate:"required,ltfield=Val1"`
4281 intTest := &IntTest{
4286 errs = validate.Struct(intTest)
4294 errs = validate.Struct(intTest)
4295 NotEqual(t, errs, nil)
4296 AssertError(t, errs, "IntTest.Val2", "Val2", "ltfield")
4298 errs = validate.FieldWithValue(int(5), int(1), "ltfield")
4301 errs = validate.FieldWithValue(int(1), int(5), "ltfield")
4302 NotEqual(t, errs, nil)
4303 AssertError(t, errs, "", "", "ltfield")
4305 type UIntTest struct {
4306 Val1 uint `validate:"required"`
4307 Val2 uint `validate:"required,ltfield=Val1"`
4310 uIntTest := &UIntTest{
4315 errs = validate.Struct(uIntTest)
4318 uIntTest = &UIntTest{
4323 errs = validate.Struct(uIntTest)
4324 NotEqual(t, errs, nil)
4325 AssertError(t, errs, "UIntTest.Val2", "Val2", "ltfield")
4327 errs = validate.FieldWithValue(uint(5), uint(1), "ltfield")
4330 errs = validate.FieldWithValue(uint(1), uint(5), "ltfield")
4331 NotEqual(t, errs, nil)
4332 AssertError(t, errs, "", "", "ltfield")
4334 type FloatTest struct {
4335 Val1 float64 `validate:"required"`
4336 Val2 float64 `validate:"required,ltfield=Val1"`
4339 floatTest := &FloatTest{
4344 errs = validate.Struct(floatTest)
4347 floatTest = &FloatTest{
4352 errs = validate.Struct(floatTest)
4353 NotEqual(t, errs, nil)
4354 AssertError(t, errs, "FloatTest.Val2", "Val2", "ltfield")
4356 errs = validate.FieldWithValue(float32(5), float32(1), "ltfield")
4359 errs = validate.FieldWithValue(float32(1), float32(5), "ltfield")
4360 NotEqual(t, errs, nil)
4361 AssertError(t, errs, "", "", "ltfield")
4363 errs = validate.FieldWithValue(nil, 5, "ltfield")
4364 NotEqual(t, errs, nil)
4365 AssertError(t, errs, "", "", "ltfield")
4367 errs = validate.FieldWithValue(1, "T", "ltfield")
4368 NotEqual(t, errs, nil)
4369 AssertError(t, errs, "", "", "ltfield")
4371 errs = validate.FieldWithValue(1, end, "ltfield")
4372 NotEqual(t, errs, nil)
4373 AssertError(t, errs, "", "", "ltfield")
4375 type TimeTest2 struct {
4376 Start *time.Time `validate:"required"`
4377 End *time.Time `validate:"required,ltfield=NonExistantField"`
4380 timeTest2 := &TimeTest2{
4385 errs = validate.Struct(timeTest2)
4386 NotEqual(t, errs, nil)
4387 AssertError(t, errs, "TimeTest2.End", "End", "ltfield")
4390 func TestLteField(t *testing.T) {
4392 type TimeTest struct {
4393 Start *time.Time `validate:"required,lte,ltefield=End"`
4394 End *time.Time `validate:"required,lte"`
4398 start := now.Add(time.Hour * 24 * -1 * 2)
4399 end := start.Add(time.Hour * 24)
4401 timeTest := &TimeTest{
4406 errs := validate.Struct(timeTest)
4409 timeTest = &TimeTest{
4414 errs = validate.Struct(timeTest)
4415 NotEqual(t, errs, nil)
4416 AssertError(t, errs, "TimeTest.Start", "Start", "ltefield")
4418 errs = validate.FieldWithValue(&end, &start, "ltefield")
4421 errs = validate.FieldWithValue(&start, &end, "ltefield")
4422 NotEqual(t, errs, nil)
4423 AssertError(t, errs, "", "", "ltefield")
4425 errs = validate.FieldWithValue(timeTest, &end, "ltefield")
4426 NotEqual(t, errs, nil)
4427 AssertError(t, errs, "", "", "ltefield")
4429 errs = validate.FieldWithValue("test", "tes", "ltefield")
4432 errs = validate.FieldWithValue("test", "test", "ltefield")
4435 type IntTest struct {
4436 Val1 int `validate:"required"`
4437 Val2 int `validate:"required,ltefield=Val1"`
4440 intTest := &IntTest{
4445 errs = validate.Struct(intTest)
4453 errs = validate.Struct(intTest)
4454 NotEqual(t, errs, nil)
4455 AssertError(t, errs, "IntTest.Val2", "Val2", "ltefield")
4457 errs = validate.FieldWithValue(int(5), int(1), "ltefield")
4460 errs = validate.FieldWithValue(int(1), int(5), "ltefield")
4461 NotEqual(t, errs, nil)
4462 AssertError(t, errs, "", "", "ltefield")
4464 type UIntTest struct {
4465 Val1 uint `validate:"required"`
4466 Val2 uint `validate:"required,ltefield=Val1"`
4469 uIntTest := &UIntTest{
4474 errs = validate.Struct(uIntTest)
4477 uIntTest = &UIntTest{
4482 errs = validate.Struct(uIntTest)
4483 NotEqual(t, errs, nil)
4484 AssertError(t, errs, "UIntTest.Val2", "Val2", "ltefield")
4486 errs = validate.FieldWithValue(uint(5), uint(1), "ltefield")
4489 errs = validate.FieldWithValue(uint(1), uint(5), "ltefield")
4490 NotEqual(t, errs, nil)
4491 AssertError(t, errs, "", "", "ltefield")
4493 type FloatTest struct {
4494 Val1 float64 `validate:"required"`
4495 Val2 float64 `validate:"required,ltefield=Val1"`
4498 floatTest := &FloatTest{
4503 errs = validate.Struct(floatTest)
4506 floatTest = &FloatTest{
4511 errs = validate.Struct(floatTest)
4512 NotEqual(t, errs, nil)
4513 AssertError(t, errs, "FloatTest.Val2", "Val2", "ltefield")
4515 errs = validate.FieldWithValue(float32(5), float32(1), "ltefield")
4518 errs = validate.FieldWithValue(float32(1), float32(5), "ltefield")
4519 NotEqual(t, errs, nil)
4520 AssertError(t, errs, "", "", "ltefield")
4522 errs = validate.FieldWithValue(nil, 5, "ltefield")
4523 NotEqual(t, errs, nil)
4524 AssertError(t, errs, "", "", "ltefield")
4526 errs = validate.FieldWithValue(1, "T", "ltefield")
4527 NotEqual(t, errs, nil)
4528 AssertError(t, errs, "", "", "ltefield")
4530 errs = validate.FieldWithValue(1, end, "ltefield")
4531 NotEqual(t, errs, nil)
4532 AssertError(t, errs, "", "", "ltefield")
4534 type TimeTest2 struct {
4535 Start *time.Time `validate:"required"`
4536 End *time.Time `validate:"required,ltefield=NonExistantField"`
4539 timeTest2 := &TimeTest2{
4544 errs = validate.Struct(timeTest2)
4545 NotEqual(t, errs, nil)
4546 AssertError(t, errs, "TimeTest2.End", "End", "ltefield")
4549 func TestGteField(t *testing.T) {
4551 type TimeTest struct {
4552 Start *time.Time `validate:"required,gte"`
4553 End *time.Time `validate:"required,gte,gtefield=Start"`
4557 start := now.Add(time.Hour * 24)
4558 end := start.Add(time.Hour * 24)
4560 timeTest := &TimeTest{
4565 errs := validate.Struct(timeTest)
4568 timeTest = &TimeTest{
4573 errs = validate.Struct(timeTest)
4574 NotEqual(t, errs, nil)
4575 AssertError(t, errs, "TimeTest.End", "End", "gtefield")
4577 errs = validate.FieldWithValue(&start, &end, "gtefield")
4580 errs = validate.FieldWithValue(&end, &start, "gtefield")
4581 NotEqual(t, errs, nil)
4582 AssertError(t, errs, "", "", "gtefield")
4584 errs = validate.FieldWithValue(timeTest, &start, "gtefield")
4585 NotEqual(t, errs, nil)
4586 AssertError(t, errs, "", "", "gtefield")
4588 errs = validate.FieldWithValue("test", "test", "gtefield")
4591 errs = validate.FieldWithValue("test", "test bigger", "gtefield")
4594 type IntTest struct {
4595 Val1 int `validate:"required"`
4596 Val2 int `validate:"required,gtefield=Val1"`
4599 intTest := &IntTest{
4604 errs = validate.Struct(intTest)
4612 errs = validate.Struct(intTest)
4613 NotEqual(t, errs, nil)
4614 AssertError(t, errs, "IntTest.Val2", "Val2", "gtefield")
4616 errs = validate.FieldWithValue(int(1), int(5), "gtefield")
4619 errs = validate.FieldWithValue(int(5), int(1), "gtefield")
4620 NotEqual(t, errs, nil)
4621 AssertError(t, errs, "", "", "gtefield")
4623 type UIntTest struct {
4624 Val1 uint `validate:"required"`
4625 Val2 uint `validate:"required,gtefield=Val1"`
4628 uIntTest := &UIntTest{
4633 errs = validate.Struct(uIntTest)
4636 uIntTest = &UIntTest{
4641 errs = validate.Struct(uIntTest)
4642 NotEqual(t, errs, nil)
4643 AssertError(t, errs, "UIntTest.Val2", "Val2", "gtefield")
4645 errs = validate.FieldWithValue(uint(1), uint(5), "gtefield")
4648 errs = validate.FieldWithValue(uint(5), uint(1), "gtefield")
4649 NotEqual(t, errs, nil)
4650 AssertError(t, errs, "", "", "gtefield")
4652 type FloatTest struct {
4653 Val1 float64 `validate:"required"`
4654 Val2 float64 `validate:"required,gtefield=Val1"`
4657 floatTest := &FloatTest{
4662 errs = validate.Struct(floatTest)
4665 floatTest = &FloatTest{
4670 errs = validate.Struct(floatTest)
4671 NotEqual(t, errs, nil)
4672 AssertError(t, errs, "FloatTest.Val2", "Val2", "gtefield")
4674 errs = validate.FieldWithValue(float32(1), float32(5), "gtefield")
4677 errs = validate.FieldWithValue(float32(5), float32(1), "gtefield")
4678 NotEqual(t, errs, nil)
4679 AssertError(t, errs, "", "", "gtefield")
4681 errs = validate.FieldWithValue(nil, 1, "gtefield")
4682 NotEqual(t, errs, nil)
4683 AssertError(t, errs, "", "", "gtefield")
4685 errs = validate.FieldWithValue(5, "T", "gtefield")
4686 NotEqual(t, errs, nil)
4687 AssertError(t, errs, "", "", "gtefield")
4689 errs = validate.FieldWithValue(5, start, "gtefield")
4690 NotEqual(t, errs, nil)
4691 AssertError(t, errs, "", "", "gtefield")
4693 type TimeTest2 struct {
4694 Start *time.Time `validate:"required"`
4695 End *time.Time `validate:"required,gtefield=NonExistantField"`
4698 timeTest2 := &TimeTest2{
4703 errs = validate.Struct(timeTest2)
4704 NotEqual(t, errs, nil)
4705 AssertError(t, errs, "TimeTest2.End", "End", "gtefield")
4708 func TestValidateByTagAndValue(t *testing.T) {
4712 errs := validate.FieldWithValue(val, field, "required")
4715 fn := func(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
4717 return current.String() == field.String()
4720 validate.RegisterValidation("isequaltestfunc", fn)
4722 errs = validate.FieldWithValue(val, field, "isequaltestfunc")
4727 errs = validate.FieldWithValue(val, field, "isequaltestfunc")
4728 NotEqual(t, errs, nil)
4729 AssertError(t, errs, "", "", "isequaltestfunc")
4732 func TestAddFunctions(t *testing.T) {
4734 fn := func(v *Validate, topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
4740 TagName: "validateme",
4743 validate := New(config)
4745 errs := validate.RegisterValidation("new", fn)
4748 errs = validate.RegisterValidation("", fn)
4749 NotEqual(t, errs, nil)
4751 validate.RegisterValidation("new", nil)
4752 NotEqual(t, errs, nil)
4754 errs = validate.RegisterValidation("new", fn)
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")
4760 func TestChangeTag(t *testing.T) {
4765 validate := New(config)
4768 Name string `val:"len=4"`
4774 errs := validate.Struct(s)
4778 func TestUnexposedStruct(t *testing.T) {
4783 A string `validate:"required"`
4791 errs := validate.Struct(s)
4795 func TestBadParams(t *testing.T) {
4798 errs := validate.Field(i, "-")
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")
4805 PanicMatches(t, func() { validate.Field(ui, "len=a") }, "strconv.ParseUint: parsing \"a\": invalid syntax")
4808 PanicMatches(t, func() { validate.Field(f, "len=a") }, "strconv.ParseFloat: parsing \"a\": invalid syntax")
4811 func TestLength(t *testing.T) {
4814 PanicMatches(t, func() { validate.Field(i, "len") }, "Bad field type bool")
4817 func TestIsGt(t *testing.T) {
4819 myMap := map[string]string{}
4820 errs := validate.Field(myMap, "gt=0")
4821 NotEqual(t, errs, nil)
4824 errs = validate.Field(f, "gt=5")
4825 NotEqual(t, errs, nil)
4826 AssertError(t, errs, "", "", "gt")
4829 errs = validate.Field(ui, "gt=10")
4830 NotEqual(t, errs, nil)
4831 AssertError(t, errs, "", "", "gt")
4834 PanicMatches(t, func() { validate.Field(i, "gt") }, "Bad field type bool")
4836 tm := time.Now().UTC()
4837 tm = tm.Add(time.Hour * 24)
4839 errs = validate.Field(tm, "gt")
4842 t2 := time.Now().UTC().Add(-time.Hour)
4844 errs = validate.Field(t2, "gt")
4845 NotEqual(t, errs, nil)
4846 AssertError(t, errs, "", "", "gt")
4849 Now *time.Time `validate:"gt"`
4855 errs = validate.Struct(s)
4862 errs = validate.Struct(s)
4863 NotEqual(t, errs, nil)
4864 AssertError(t, errs, "Test.Now", "Now", "gt")
4867 func TestIsGte(t *testing.T) {
4870 PanicMatches(t, func() { validate.Field(i, "gte") }, "Bad field type bool")
4872 t1 := time.Now().UTC()
4873 t1 = t1.Add(time.Hour * 24)
4875 errs := validate.Field(t1, "gte")
4878 t2 := time.Now().UTC().Add(-time.Hour)
4880 errs = validate.Field(t2, "gte")
4881 NotEqual(t, errs, nil)
4882 AssertError(t, errs, "", "", "gte")
4885 Now *time.Time `validate:"gte"`
4891 errs = validate.Struct(s)
4898 errs = validate.Struct(s)
4899 NotEqual(t, errs, nil)
4900 AssertError(t, errs, "Test.Now", "Now", "gte")
4903 func TestIsLt(t *testing.T) {
4905 myMap := map[string]string{}
4906 errs := validate.Field(myMap, "lt=0")
4907 NotEqual(t, errs, nil)
4908 AssertError(t, errs, "", "", "lt")
4911 errs = validate.Field(f, "lt=0")
4912 NotEqual(t, errs, nil)
4913 AssertError(t, errs, "", "", "lt")
4916 errs = validate.Field(ui, "lt=0")
4917 NotEqual(t, errs, nil)
4918 AssertError(t, errs, "", "", "lt")
4921 PanicMatches(t, func() { validate.Field(i, "lt") }, "Bad field type bool")
4923 t1 := time.Now().UTC().Add(-time.Hour)
4925 errs = validate.Field(t1, "lt")
4928 t2 := time.Now().UTC()
4929 t2 = t2.Add(time.Hour * 24)
4931 errs = validate.Field(t2, "lt")
4932 NotEqual(t, errs, nil)
4933 AssertError(t, errs, "", "", "lt")
4936 Now *time.Time `validate:"lt"`
4943 errs = validate.Struct(s)
4950 errs = validate.Struct(s)
4951 NotEqual(t, errs, nil)
4952 AssertError(t, errs, "Test.Now", "Now", "lt")
4955 func TestIsLte(t *testing.T) {
4958 PanicMatches(t, func() { validate.Field(i, "lte") }, "Bad field type bool")
4960 t1 := time.Now().UTC().Add(-time.Hour)
4962 errs := validate.Field(t1, "lte")
4965 t2 := time.Now().UTC()
4966 t2 = t2.Add(time.Hour * 24)
4968 errs = validate.Field(t2, "lte")
4969 NotEqual(t, errs, nil)
4970 AssertError(t, errs, "", "", "lte")
4973 Now *time.Time `validate:"lte"`
4980 errs = validate.Struct(s)
4987 errs = validate.Struct(s)
4988 NotEqual(t, errs, nil)
4991 func TestUrl(t *testing.T) {
4993 var tests = []struct {
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},
5014 {"xyz://foobar.com", true},
5015 {"invalid.", 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},
5032 for i, test := range tests {
5034 errs := validate.Field(test.param, "url")
5037 if !IsEqual(errs, nil) {
5038 t.Fatalf("Index: %d URL failed Error: %s", i, errs)
5041 if IsEqual(errs, nil) {
5042 t.Fatalf("Index: %d URL failed Error: %s", i, errs)
5044 val := errs.(ValidationErrors)[""]
5045 if val.Tag != "url" {
5046 t.Fatalf("Index: %d URL failed Error: %s", i, errs)
5053 PanicMatches(t, func() { validate.Field(i, "url") }, "Bad field type int")
5056 func TestUri(t *testing.T) {
5058 var tests = []struct {
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},
5079 {"xyz://foobar.com", true},
5080 {"invalid.", 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},
5096 for i, test := range tests {
5098 errs := validate.Field(test.param, "uri")
5101 if !IsEqual(errs, nil) {
5102 t.Fatalf("Index: %d URI failed Error: %s", i, errs)
5105 if IsEqual(errs, nil) {
5106 t.Fatalf("Index: %d URI failed Error: %s", i, errs)
5108 val := errs.(ValidationErrors)[""]
5109 if val.Tag != "uri" {
5110 t.Fatalf("Index: %d URI failed Error: %s", i, errs)
5117 PanicMatches(t, func() { validate.Field(i, "uri") }, "Bad field type int")
5120 func TestOrTag(t *testing.T) {
5121 s := "rgba(0,31,255,0.5)"
5122 errs := validate.Field(s, "rgb|rgba")
5125 s = "rgba(0,31,255,0.5)"
5126 errs = validate.Field(s, "rgb|rgba|len=18")
5129 s = "this ain't right"
5130 errs = validate.Field(s, "rgb|rgba")
5131 NotEqual(t, errs, nil)
5132 AssertError(t, errs, "", "", "rgb|rgba")
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")
5140 errs = validate.Field(s, "rgb|rgba|len=13")
5144 errs = validate.Field(s, "omitempty,rgb|rgba")
5147 s = "this is right, but a blank or isn't"
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")
5153 func TestHsla(t *testing.T) {
5155 s := "hsla(360,100%,100%,1)"
5156 errs := validate.Field(s, "hsla")
5159 s = "hsla(360,100%,100%,0.5)"
5160 errs = validate.Field(s, "hsla")
5163 s = "hsla(0,0%,0%, 0)"
5164 errs = validate.Field(s, "hsla")
5167 s = "hsl(361,100%,50%,1)"
5168 errs = validate.Field(s, "hsla")
5169 NotEqual(t, errs, nil)
5170 AssertError(t, errs, "", "", "hsla")
5172 s = "hsl(361,100%,50%)"
5173 errs = validate.Field(s, "hsla")
5174 NotEqual(t, errs, nil)
5175 AssertError(t, errs, "", "", "hsla")
5177 s = "hsla(361,100%,50%)"
5178 errs = validate.Field(s, "hsla")
5179 NotEqual(t, errs, nil)
5180 AssertError(t, errs, "", "", "hsla")
5182 s = "hsla(360,101%,50%)"
5183 errs = validate.Field(s, "hsla")
5184 NotEqual(t, errs, nil)
5185 AssertError(t, errs, "", "", "hsla")
5187 s = "hsla(360,100%,101%)"
5188 errs = validate.Field(s, "hsla")
5189 NotEqual(t, errs, nil)
5190 AssertError(t, errs, "", "", "hsla")
5193 validate.Field(i, "hsla")
5194 NotEqual(t, errs, nil)
5195 AssertError(t, errs, "", "", "hsla")
5198 func TestHsl(t *testing.T) {
5200 s := "hsl(360,100%,50%)"
5201 errs := validate.Field(s, "hsl")
5205 errs = validate.Field(s, "hsl")
5208 s = "hsl(361,100%,50%)"
5209 errs = validate.Field(s, "hsl")
5210 NotEqual(t, errs, nil)
5211 AssertError(t, errs, "", "", "hsl")
5213 s = "hsl(361,101%,50%)"
5214 errs = validate.Field(s, "hsl")
5215 NotEqual(t, errs, nil)
5216 AssertError(t, errs, "", "", "hsl")
5218 s = "hsl(361,100%,101%)"
5219 errs = validate.Field(s, "hsl")
5220 NotEqual(t, errs, nil)
5221 AssertError(t, errs, "", "", "hsl")
5223 s = "hsl(-10,100%,100%)"
5224 errs = validate.Field(s, "hsl")
5225 NotEqual(t, errs, nil)
5226 AssertError(t, errs, "", "", "hsl")
5229 errs = validate.Field(i, "hsl")
5230 NotEqual(t, errs, nil)
5231 AssertError(t, errs, "", "", "hsl")
5234 func TestRgba(t *testing.T) {
5236 s := "rgba(0,31,255,0.5)"
5237 errs := validate.Field(s, "rgba")
5240 s = "rgba(0,31,255,0.12)"
5241 errs = validate.Field(s, "rgba")
5244 s = "rgba(12%,55%,100%,0.12)"
5245 errs = validate.Field(s, "rgba")
5248 s = "rgba( 0, 31, 255, 0.5)"
5249 errs = validate.Field(s, "rgba")
5252 s = "rgba(12%,55,100%,0.12)"
5253 errs = validate.Field(s, "rgba")
5254 NotEqual(t, errs, nil)
5255 AssertError(t, errs, "", "", "rgba")
5257 s = "rgb(0, 31, 255)"
5258 errs = validate.Field(s, "rgba")
5259 NotEqual(t, errs, nil)
5260 AssertError(t, errs, "", "", "rgba")
5262 s = "rgb(1,349,275,0.5)"
5263 errs = validate.Field(s, "rgba")
5264 NotEqual(t, errs, nil)
5265 AssertError(t, errs, "", "", "rgba")
5267 s = "rgb(01,31,255,0.5)"
5268 errs = validate.Field(s, "rgba")
5269 NotEqual(t, errs, nil)
5270 AssertError(t, errs, "", "", "rgba")
5273 errs = validate.Field(i, "rgba")
5274 NotEqual(t, errs, nil)
5275 AssertError(t, errs, "", "", "rgba")
5278 func TestRgb(t *testing.T) {
5280 s := "rgb(0,31,255)"
5281 errs := validate.Field(s, "rgb")
5284 s = "rgb(0, 31, 255)"
5285 errs = validate.Field(s, "rgb")
5288 s = "rgb(10%, 50%, 100%)"
5289 errs = validate.Field(s, "rgb")
5292 s = "rgb(10%, 50%, 55)"
5293 errs = validate.Field(s, "rgb")
5294 NotEqual(t, errs, nil)
5295 AssertError(t, errs, "", "", "rgb")
5297 s = "rgb(1,349,275)"
5298 errs = validate.Field(s, "rgb")
5299 NotEqual(t, errs, nil)
5300 AssertError(t, errs, "", "", "rgb")
5302 s = "rgb(01,31,255)"
5303 errs = validate.Field(s, "rgb")
5304 NotEqual(t, errs, nil)
5305 AssertError(t, errs, "", "", "rgb")
5307 s = "rgba(0,31,255)"
5308 errs = validate.Field(s, "rgb")
5309 NotEqual(t, errs, nil)
5310 AssertError(t, errs, "", "", "rgb")
5313 errs = validate.Field(i, "rgb")
5314 NotEqual(t, errs, nil)
5315 AssertError(t, errs, "", "", "rgb")
5318 func TestEmail(t *testing.T) {
5320 s := "test@mail.com"
5321 errs := validate.Field(s, "email")
5324 s = "Dörte@Sörensen.example.com"
5325 errs = validate.Field(s, "email")
5328 s = "θσερ@εχαμπλε.ψομ"
5329 errs = validate.Field(s, "email")
5332 s = "юзер@екзампл.ком"
5333 errs = validate.Field(s, "email")
5336 s = "उपयोगकर्ता@उदाहरण.कॉम"
5337 errs = validate.Field(s, "email")
5341 errs = validate.Field(s, "email")
5345 errs = validate.Field(s, "email")
5346 NotEqual(t, errs, nil)
5347 AssertError(t, errs, "", "", "email")
5350 errs = validate.Field(s, "email")
5351 NotEqual(t, errs, nil)
5352 AssertError(t, errs, "", "", "email")
5355 errs = validate.Field(s, "email")
5356 NotEqual(t, errs, nil)
5357 AssertError(t, errs, "", "", "email")
5360 errs = validate.Field(s, "email")
5361 NotEqual(t, errs, nil)
5362 AssertError(t, errs, "", "", "email")
5365 errs = validate.Field(i, "email")
5366 NotEqual(t, errs, nil)
5367 AssertError(t, errs, "", "", "email")
5370 func TestHexColor(t *testing.T) {
5373 errs := validate.Field(s, "hexcolor")
5377 errs = validate.Field(s, "hexcolor")
5381 errs = validate.Field(s, "hexcolor")
5382 NotEqual(t, errs, nil)
5383 AssertError(t, errs, "", "", "hexcolor")
5386 errs = validate.Field(s, "hexcolor")
5387 NotEqual(t, errs, nil)
5388 AssertError(t, errs, "", "", "hexcolor")
5391 errs = validate.Field(i, "hexcolor")
5392 NotEqual(t, errs, nil)
5393 AssertError(t, errs, "", "", "hexcolor")
5396 func TestHexadecimal(t *testing.T) {
5399 errs := validate.Field(s, "hexadecimal")
5403 errs = validate.Field(s, "hexadecimal")
5404 NotEqual(t, errs, nil)
5405 AssertError(t, errs, "", "", "hexadecimal")
5408 errs = validate.Field(i, "hexadecimal")
5409 NotEqual(t, errs, nil)
5410 AssertError(t, errs, "", "", "hexadecimal")
5413 func TestNumber(t *testing.T) {
5416 errs := validate.Field(s, "number")
5420 errs = validate.Field(s, "number")
5421 NotEqual(t, errs, nil)
5422 AssertError(t, errs, "", "", "number")
5425 errs = validate.Field(s, "number")
5426 NotEqual(t, errs, nil)
5427 AssertError(t, errs, "", "", "number")
5430 errs = validate.Field(s, "number")
5431 NotEqual(t, errs, nil)
5432 AssertError(t, errs, "", "", "number")
5435 errs = validate.Field(s, "number")
5436 NotEqual(t, errs, nil)
5437 AssertError(t, errs, "", "", "number")
5440 errs = validate.Field(s, "number")
5441 NotEqual(t, errs, nil)
5442 AssertError(t, errs, "", "", "number")
5445 errs = validate.Field(s, "number")
5446 NotEqual(t, errs, nil)
5447 AssertError(t, errs, "", "", "number")
5450 errs = validate.Field(s, "number")
5451 NotEqual(t, errs, nil)
5452 AssertError(t, errs, "", "", "number")
5455 errs = validate.Field(i, "number")
5456 NotEqual(t, errs, nil)
5457 AssertError(t, errs, "", "", "number")
5460 func TestNumeric(t *testing.T) {
5463 errs := validate.Field(s, "numeric")
5467 errs = validate.Field(s, "numeric")
5471 errs = validate.Field(s, "numeric")
5475 errs = validate.Field(s, "numeric")
5479 errs = validate.Field(s, "numeric")
5483 errs = validate.Field(s, "numeric")
5487 errs = validate.Field(s, "numeric")
5488 NotEqual(t, errs, nil)
5489 AssertError(t, errs, "", "", "numeric")
5492 errs = validate.Field(s, "numeric")
5493 NotEqual(t, errs, nil)
5494 AssertError(t, errs, "", "", "numeric")
5497 errs = validate.Field(i, "numeric")
5498 NotEqual(t, errs, nil)
5499 AssertError(t, errs, "", "", "numeric")
5502 func TestAlphaNumeric(t *testing.T) {
5505 errs := validate.Field(s, "alphanum")
5509 errs = validate.Field(s, "alphanum")
5510 NotEqual(t, errs, nil)
5511 AssertError(t, errs, "", "", "alphanum")
5513 errs = validate.Field(1, "alphanum")
5514 NotEqual(t, errs, nil)
5515 AssertError(t, errs, "", "", "alphanum")
5518 func TestAlpha(t *testing.T) {
5521 errs := validate.Field(s, "alpha")
5525 errs = validate.Field(s, "alpha")
5526 NotEqual(t, errs, nil)
5527 AssertError(t, errs, "", "", "alpha")
5530 errs = validate.Field(s, "alpha")
5531 NotEqual(t, errs, nil)
5532 AssertError(t, errs, "", "", "alpha")
5535 errs = validate.Field(s, "alpha")
5536 NotEqual(t, errs, nil)
5537 AssertError(t, errs, "", "", "alpha")
5539 errs = validate.Field(1, "alpha")
5540 NotEqual(t, errs, nil)
5541 AssertError(t, errs, "", "", "alpha")
5545 func TestStructStringValidation(t *testing.T) {
5547 tSuccess := &TestString{
5548 Required: "Required",
5561 SubIgnore: &SubTest{
5565 A string `validate:"required"`
5574 errs := validate.Struct(tSuccess)
5577 tFail := &TestString{
5587 OmitEmpty: "12345678901",
5592 A string `validate:"required"`
5601 errs = validate.Struct(tFail)
5604 NotEqual(t, errs, nil)
5605 Equal(t, len(errs.(ValidationErrors)), 13)
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")
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")
5625 func TestStructInt32Validation(t *testing.T) {
5627 tSuccess := &TestInt32{
5640 errs := validate.Struct(tSuccess)
5643 tFail := &TestInt32{
5656 errs = validate.Struct(tFail)
5659 NotEqual(t, errs, nil)
5660 Equal(t, len(errs.(ValidationErrors)), 10)
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")
5675 func TestStructUint64Validation(t *testing.T) {
5677 tSuccess := &TestUint64{
5686 errs := validate.Struct(tSuccess)
5689 tFail := &TestUint64{
5698 errs = validate.Struct(tFail)
5701 NotEqual(t, errs, nil)
5702 Equal(t, len(errs.(ValidationErrors)), 6)
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")
5713 func TestStructFloat64Validation(t *testing.T) {
5715 tSuccess := &TestFloat64{
5724 errs := validate.Struct(tSuccess)
5727 tFail := &TestFloat64{
5736 errs = validate.Struct(tFail)
5739 NotEqual(t, errs, nil)
5740 Equal(t, len(errs.(ValidationErrors)), 6)
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")
5751 func TestStructSliceValidation(t *testing.T) {
5753 tSuccess := &TestSlice{
5755 Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
5757 Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
5758 MinMax: []int{1, 2, 3, 4, 5},
5762 errs := validate.Struct(tSuccess)
5765 tFail := &TestSlice{
5767 Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
5769 Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
5771 OmitEmpty: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
5774 errs = validate.Struct(tFail)
5775 NotEqual(t, errs, nil)
5776 Equal(t, len(errs.(ValidationErrors)), 6)
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")
5787 func TestInvalidStruct(t *testing.T) {
5792 PanicMatches(t, func() { validate.Struct(s.Test) }, "value passed for validation is not a struct")
5795 func TestInvalidValidatorFunction(t *testing.T) {
5800 PanicMatches(t, func() { validate.Field(s.Test, "zzxxBadFunction") }, "Undefined validation function on field")
5803 func TestCustomFieldName(t *testing.T) {
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"`
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")
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")
5830 func TestMutipleRecursiveExtractStructCache(t *testing.T) {
5832 type Recursive struct {
5833 Field *string `validate:"exists,required,len=5,ne=string"`
5838 current := reflect.ValueOf(test)
5840 proceed := make(chan struct{})
5842 sc := validate.extractStructCache(current, name)
5843 ptr := fmt.Sprintf("%p", sc)
5845 for i := 0; i < 100; i++ {
5849 sc := validate.extractStructCache(current, name)
5850 Equal(t, ptr, fmt.Sprintf("%p", sc))
5857 // Thanks @robbrockbank, see https://github.com/go-playground/validator/issues/249
5858 func TestPointerAndOmitEmpty(t *testing.T) {
5861 MyInt *int `validate:"omitempty,gte=2,lte=255"`
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
5871 errs := validate.Struct(t1)
5872 NotEqual(t, errs, nil)
5873 AssertError(t, errs, "Test.MyInt", "MyInt", "gte")
5875 errs = validate.Struct(t2)
5876 NotEqual(t, errs, nil)
5877 AssertError(t, errs, "Test.MyInt", "MyInt", "lte")
5879 errs = validate.Struct(t3)
5882 type TestIface struct {
5883 MyInt interface{} `validate:"omitempty,gte=2,lte=255"`
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
5890 errs = validate.Struct(ti1)
5891 NotEqual(t, errs, nil)
5892 AssertError(t, errs, "TestIface.MyInt", "MyInt", "gte")
5894 errs = validate.Struct(ti2)
5895 NotEqual(t, errs, nil)
5896 AssertError(t, errs, "TestIface.MyInt", "MyInt", "lte")
5898 errs = validate.Struct(ti3)