From 3d78e8a9bbee419efb71186e42d5d18332187ff2 Mon Sep 17 00:00:00 2001 From: gamife Date: Sat, 28 Nov 2020 15:07:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8C=85=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go-playground/locales/go.sum | 3 - go-playground/validator/v10/validator_test.go | 11035 ------------------------ 2 files changed, 11038 deletions(-) delete mode 100644 go-playground/locales/go.sum delete mode 100644 go-playground/validator/v10/validator_test.go diff --git a/go-playground/locales/go.sum b/go-playground/locales/go.sum deleted file mode 100644 index 63c9200..0000000 --- a/go-playground/locales/go.sum +++ /dev/null @@ -1,3 +0,0 @@ -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/go-playground/validator/v10/validator_test.go b/go-playground/validator/v10/validator_test.go deleted file mode 100644 index b18b9e5..0000000 --- a/go-playground/validator/v10/validator_test.go +++ /dev/null @@ -1,11035 +0,0 @@ -package validator - -import ( - "bytes" - "context" - "database/sql" - "database/sql/driver" - "encoding/base64" - "encoding/json" - "fmt" - "path/filepath" - "reflect" - "strings" - "testing" - "time" - - . "git.ningdatech.com/ningda/gin_valid/go-playground/assert/v2" - "git.ningdatech.com/ningda/gin_valid/go-playground/locales/en" - "git.ningdatech.com/ningda/gin_valid/go-playground/locales/fr" - "git.ningdatech.com/ningda/gin_valid/go-playground/locales/nl" - ut "git.ningdatech.com/ningda/gin_valid/go-playground/universal-translator" -) - -// NOTES: -// - Run "go test" to run tests -// - Run "gocov test | gocov report" to report on test converage by file -// - Run "gocov test | gocov annotate -" to report on all code and functions, those ,marked with "MISS" were never called -// -// or -// -// -- may be a good idea to change to output path to somewherelike /tmp -// go test -coverprofile cover.out && go tool cover -html=cover.out -o cover.html -// -// -// go test -cpuprofile cpu.out -// ./validator.test -test.bench=. -test.cpuprofile=cpu.prof -// go tool pprof validator.test cpu.prof -// -// -// go test -memprofile mem.out - -type I interface { - Foo() string -} - -type Impl struct { - F string `validate:"len=3"` -} - -func (i *Impl) Foo() string { - return i.F -} - -type SubTest struct { - Test string `validate:"required"` -} - -type TestInterface struct { - Iface I -} - -type TestString struct { - BlankTag string `validate:""` - Required string `validate:"required"` - Len string `validate:"len=10"` - Min string `validate:"min=1"` - Max string `validate:"max=10"` - MinMax string `validate:"min=1,max=10"` - Lt string `validate:"lt=10"` - Lte string `validate:"lte=10"` - Gt string `validate:"gt=10"` - Gte string `validate:"gte=10"` - OmitEmpty string `validate:"omitempty,min=1,max=10"` - Sub *SubTest - SubIgnore *SubTest `validate:"-"` - Anonymous struct { - A string `validate:"required"` - } - Iface I -} - -type TestUint64 struct { - Required uint64 `validate:"required"` - Len uint64 `validate:"len=10"` - Min uint64 `validate:"min=1"` - Max uint64 `validate:"max=10"` - MinMax uint64 `validate:"min=1,max=10"` - OmitEmpty uint64 `validate:"omitempty,min=1,max=10"` -} - -type TestFloat64 struct { - Required float64 `validate:"required"` - Len float64 `validate:"len=10"` - Min float64 `validate:"min=1"` - Max float64 `validate:"max=10"` - MinMax float64 `validate:"min=1,max=10"` - Lte float64 `validate:"lte=10"` - OmitEmpty float64 `validate:"omitempty,min=1,max=10"` -} - -type TestSlice struct { - Required []int `validate:"required"` - Len []int `validate:"len=10"` - Min []int `validate:"min=1"` - Max []int `validate:"max=10"` - MinMax []int `validate:"min=1,max=10"` - OmitEmpty []int `validate:"omitempty,min=1,max=10"` -} - -func AssertError(t *testing.T, err error, nsKey, structNsKey, field, structField, expectedTag string) { - - errs := err.(ValidationErrors) - - found := false - var fe FieldError - - for i := 0; i < len(errs); i++ { - if errs[i].Namespace() == nsKey && errs[i].StructNamespace() == structNsKey { - found = true - fe = errs[i] - break - } - } - - EqualSkip(t, 2, found, true) - NotEqualSkip(t, 2, fe, nil) - EqualSkip(t, 2, fe.Field(), field) - EqualSkip(t, 2, fe.StructField(), structField) - EqualSkip(t, 2, fe.Tag(), expectedTag) -} - -func AssertDeepError(t *testing.T, err error, nsKey, structNsKey, field, structField, expectedTag, actualTag string) { - errs := err.(ValidationErrors) - - found := false - var fe FieldError - - for i := 0; i < len(errs); i++ { - if errs[i].Namespace() == nsKey && errs[i].StructNamespace() == structNsKey && errs[i].Tag() == expectedTag && errs[i].ActualTag() == actualTag { - found = true - fe = errs[i] - break - } - } - - EqualSkip(t, 2, found, true) - NotEqualSkip(t, 2, fe, nil) - EqualSkip(t, 2, fe.Field(), field) - EqualSkip(t, 2, fe.StructField(), structField) -} - -func getError(err error, nsKey, structNsKey string) FieldError { - - errs := err.(ValidationErrors) - - var fe FieldError - - for i := 0; i < len(errs); i++ { - if errs[i].Namespace() == nsKey && errs[i].StructNamespace() == structNsKey { - fe = errs[i] - break - } - } - - return fe -} - -type valuer struct { - Name string -} - -func (v valuer) Value() (driver.Value, error) { - - if v.Name == "errorme" { - panic("SQL Driver Valuer error: some kind of error") - // return nil, errors.New("some kind of error") - } - - if len(v.Name) == 0 { - return nil, nil - } - - return v.Name, nil -} - -type MadeUpCustomType struct { - FirstName string - LastName string -} - -func ValidateCustomType(field reflect.Value) interface{} { - - if cust, ok := field.Interface().(MadeUpCustomType); ok { - - if len(cust.FirstName) == 0 || len(cust.LastName) == 0 { - return "" - } - - return cust.FirstName + " " + cust.LastName - } - - return "" -} - -func OverrideIntTypeForSomeReason(field reflect.Value) interface{} { - - if i, ok := field.Interface().(int); ok { - if i == 1 { - return "1" - } - - if i == 2 { - return "12" - } - } - - return "" -} - -type CustomMadeUpStruct struct { - MadeUp MadeUpCustomType `validate:"required"` - OverriddenInt int `validate:"gt=1"` -} - -func ValidateValuerType(field reflect.Value) interface{} { - - if valuer, ok := field.Interface().(driver.Valuer); ok { - - val, err := valuer.Value() - if err != nil { - // handle the error how you want - return nil - } - - return val - } - - return nil -} - -type TestPartial struct { - NoTag string - BlankTag string `validate:""` - Required string `validate:"required"` - SubSlice []*SubTest `validate:"required,dive"` - Sub *SubTest - SubIgnore *SubTest `validate:"-"` - Anonymous struct { - A string `validate:"required"` - ASubSlice []*SubTest `validate:"required,dive"` - - SubAnonStruct []struct { - Test string `validate:"required"` - OtherTest string `validate:"required"` - } `validate:"required,dive"` - } -} - -type TestStruct struct { - String string `validate:"required" json:"StringVal"` -} - -func StructValidationTestStructSuccess(sl StructLevel) { - - st := sl.Current().Interface().(TestStruct) - - if st.String != "good value" { - sl.ReportError(st.String, "StringVal", "String", "badvalueteststruct", "good value") - } -} - -func StructValidationTestStruct(sl StructLevel) { - - st := sl.Current().Interface().(TestStruct) - - if st.String != "bad value" { - sl.ReportError(st.String, "StringVal", "String", "badvalueteststruct", "bad value") - } -} - -func StructValidationNoTestStructCustomName(sl StructLevel) { - - st := sl.Current().Interface().(TestStruct) - - if st.String != "bad value" { - sl.ReportError(st.String, "String", "", "badvalueteststruct", "bad value") - } -} - -func StructValidationTestStructInvalid(sl StructLevel) { - - st := sl.Current().Interface().(TestStruct) - - if st.String != "bad value" { - sl.ReportError(nil, "StringVal", "String", "badvalueteststruct", "bad value") - } -} - -func StructValidationTestStructReturnValidationErrors(sl StructLevel) { - - s := sl.Current().Interface().(TestStructReturnValidationErrors) - - errs := sl.Validator().Struct(s.Inner1.Inner2) - if errs == nil { - return - } - - sl.ReportValidationErrors("Inner1.", "Inner1.", errs.(ValidationErrors)) -} - -func StructValidationTestStructReturnValidationErrors2(sl StructLevel) { - - s := sl.Current().Interface().(TestStructReturnValidationErrors) - - errs := sl.Validator().Struct(s.Inner1.Inner2) - if errs == nil { - return - } - - sl.ReportValidationErrors("Inner1JSON.", "Inner1.", errs.(ValidationErrors)) -} - -type TestStructReturnValidationErrorsInner2 struct { - String string `validate:"required" json:"JSONString"` -} - -type TestStructReturnValidationErrorsInner1 struct { - Inner2 *TestStructReturnValidationErrorsInner2 -} - -type TestStructReturnValidationErrors struct { - Inner1 *TestStructReturnValidationErrorsInner1 `json:"Inner1JSON"` -} - -type StructLevelInvalidErr struct { - Value string -} - -func StructLevelInvalidError(sl StructLevel) { - - top := sl.Top().Interface().(StructLevelInvalidErr) - s := sl.Current().Interface().(StructLevelInvalidErr) - - if top.Value == s.Value { - sl.ReportError(nil, "Value", "Value", "required", "") - } -} - -func stringPtr(v string) *string { - return &v -} - -func intPtr(v int) *int { - return &v -} - -func float64Ptr(v float64) *float64 { - return &v -} - -func TestStructLevelInvalidError(t *testing.T) { - - validate := New() - validate.RegisterStructValidation(StructLevelInvalidError, StructLevelInvalidErr{}) - - var test StructLevelInvalidErr - - err := validate.Struct(test) - NotEqual(t, err, nil) - - errs, ok := err.(ValidationErrors) - Equal(t, ok, true) - - fe := errs[0] - Equal(t, fe.Field(), "Value") - Equal(t, fe.StructField(), "Value") - Equal(t, fe.Namespace(), "StructLevelInvalidErr.Value") - Equal(t, fe.StructNamespace(), "StructLevelInvalidErr.Value") - Equal(t, fe.Tag(), "required") - Equal(t, fe.ActualTag(), "required") - Equal(t, fe.Kind(), reflect.Invalid) - Equal(t, fe.Type(), reflect.TypeOf(nil)) -} - -func TestNameNamespace(t *testing.T) { - - type Inner2Namespace struct { - String []string `validate:"dive,required" json:"JSONString"` - } - - type Inner1Namespace struct { - Inner2 *Inner2Namespace `json:"Inner2JSON"` - } - - type Namespace struct { - Inner1 *Inner1Namespace `json:"Inner1JSON"` - } - - validate := New() - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - - if name == "-" { - return "" - } - - return name - }) - - i2 := &Inner2Namespace{String: []string{"ok", "ok", "ok"}} - i1 := &Inner1Namespace{Inner2: i2} - ns := &Namespace{Inner1: i1} - - errs := validate.Struct(ns) - Equal(t, errs, nil) - - i2.String[1] = "" - - errs = validate.Struct(ns) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 1) - AssertError(t, errs, "Namespace.Inner1JSON.Inner2JSON.JSONString[1]", "Namespace.Inner1.Inner2.String[1]", "JSONString[1]", "String[1]", "required") - - fe := getError(ve, "Namespace.Inner1JSON.Inner2JSON.JSONString[1]", "Namespace.Inner1.Inner2.String[1]") - NotEqual(t, fe, nil) - Equal(t, fe.Field(), "JSONString[1]") - Equal(t, fe.StructField(), "String[1]") - Equal(t, fe.Namespace(), "Namespace.Inner1JSON.Inner2JSON.JSONString[1]") - Equal(t, fe.StructNamespace(), "Namespace.Inner1.Inner2.String[1]") -} - -func TestAnonymous(t *testing.T) { - - validate := New() - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - - if name == "-" { - return "" - } - - return name - }) - - type Test struct { - Anonymous struct { - A string `validate:"required" json:"EH"` - } - AnonymousB struct { - B string `validate:"required" json:"BEE"` - } - anonymousC struct { - c string `validate:"required"` - } - } - - tst := &Test{ - Anonymous: struct { - A string `validate:"required" json:"EH"` - }{ - A: "1", - }, - AnonymousB: struct { - B string `validate:"required" json:"BEE"` - }{ - B: "", - }, - anonymousC: struct { - c string `validate:"required"` - }{ - c: "", - }, - } - - Equal(t, tst.anonymousC.c, "") - - err := validate.Struct(tst) - NotEqual(t, err, nil) - - errs := err.(ValidationErrors) - - Equal(t, len(errs), 1) - AssertError(t, errs, "Test.AnonymousB.BEE", "Test.AnonymousB.B", "BEE", "B", "required") - - fe := getError(errs, "Test.AnonymousB.BEE", "Test.AnonymousB.B") - NotEqual(t, fe, nil) - Equal(t, fe.Field(), "BEE") - Equal(t, fe.StructField(), "B") - - s := struct { - c string `validate:"required"` - }{ - c: "", - } - - err = validate.Struct(s) - Equal(t, err, nil) -} - -func TestAnonymousSameStructDifferentTags(t *testing.T) { - - validate := New() - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - - if name == "-" { - return "" - } - - return name - }) - - type Test struct { - A interface{} - } - - tst := &Test{ - A: struct { - A string `validate:"required"` - }{ - A: "", - }, - } - - err := validate.Struct(tst) - NotEqual(t, err, nil) - - errs := err.(ValidationErrors) - - Equal(t, len(errs), 1) - AssertError(t, errs, "Test.A.A", "Test.A.A", "A", "A", "required") - - tst = &Test{ - A: struct { - A string `validate:"omitempty,required"` - }{ - A: "", - }, - } - - err = validate.Struct(tst) - Equal(t, err, nil) -} - -func TestStructLevelReturnValidationErrors(t *testing.T) { - - validate := New() - validate.RegisterStructValidation(StructValidationTestStructReturnValidationErrors, TestStructReturnValidationErrors{}) - - inner2 := &TestStructReturnValidationErrorsInner2{ - String: "I'm HERE", - } - - inner1 := &TestStructReturnValidationErrorsInner1{ - Inner2: inner2, - } - - val := &TestStructReturnValidationErrors{ - Inner1: inner1, - } - - errs := validate.Struct(val) - Equal(t, errs, nil) - - inner2.String = "" - - errs = validate.Struct(val) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 2) - AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.Inner2.String", "TestStructReturnValidationErrors.Inner1.Inner2.String", "String", "String", "required") - // this is an extra error reported from struct validation - AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "String", "String", "required") -} - -func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) { - - validate := New() - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - - if name == "-" { - return "" - } - - return name - }) - validate.RegisterStructValidation(StructValidationTestStructReturnValidationErrors2, TestStructReturnValidationErrors{}) - - inner2 := &TestStructReturnValidationErrorsInner2{ - String: "I'm HERE", - } - - inner1 := &TestStructReturnValidationErrorsInner1{ - Inner2: inner2, - } - - val := &TestStructReturnValidationErrors{ - Inner1: inner1, - } - - errs := validate.Struct(val) - Equal(t, errs, nil) - - inner2.String = "" - - errs = validate.Struct(val) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 2) - AssertError(t, errs, "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString", "TestStructReturnValidationErrors.Inner1.Inner2.String", "JSONString", "String", "required") - // this is an extra error reported from struct validation, it's a badly formatted one, but on purpose - AssertError(t, errs, "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "JSONString", "String", "required") - - fe := getError(errs, "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString", "TestStructReturnValidationErrors.Inner1.Inner2.String") - NotEqual(t, fe, nil) - - // check for proper JSON namespace - Equal(t, fe.Field(), "JSONString") - Equal(t, fe.StructField(), "String") - Equal(t, fe.Namespace(), "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString") - Equal(t, fe.StructNamespace(), "TestStructReturnValidationErrors.Inner1.Inner2.String") - - fe = getError(errs, "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String") - NotEqual(t, fe, nil) - - // check for proper JSON namespace - Equal(t, fe.Field(), "JSONString") - Equal(t, fe.StructField(), "String") - Equal(t, fe.Namespace(), "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString") - Equal(t, fe.StructNamespace(), "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String") -} - -func TestStructLevelValidations(t *testing.T) { - - v1 := New() - v1.RegisterStructValidation(StructValidationTestStruct, TestStruct{}) - - tst := &TestStruct{ - String: "good value", - } - - errs := v1.Struct(tst) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct") - - v2 := New() - v2.RegisterStructValidation(StructValidationNoTestStructCustomName, TestStruct{}) - - errs = v2.Struct(tst) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestStruct.String", "TestStruct.String", "String", "String", "badvalueteststruct") - - v3 := New() - v3.RegisterStructValidation(StructValidationTestStructInvalid, TestStruct{}) - - errs = v3.Struct(tst) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct") - - v4 := New() - v4.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{}) - - errs = v4.Struct(tst) - Equal(t, errs, nil) -} - -func TestAliasTags(t *testing.T) { - - validate := New() - validate.RegisterAlias("iscoloralias", "hexcolor|rgb|rgba|hsl|hsla") - - s := "rgb(255,255,255)" - errs := validate.Var(s, "iscoloralias") - Equal(t, errs, nil) - - s = "" - errs = validate.Var(s, "omitempty,iscoloralias") - Equal(t, errs, nil) - - s = "rgb(255,255,0)" - errs = validate.Var(s, "iscoloralias,len=5") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "len") - - type Test struct { - Color string `validate:"iscoloralias"` - } - - tst := &Test{ - Color: "#000", - } - - errs = validate.Struct(tst) - Equal(t, errs, nil) - - tst.Color = "cfvre" - errs = validate.Struct(tst) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.Color", "Test.Color", "Color", "Color", "iscoloralias") - - fe := getError(errs, "Test.Color", "Test.Color") - NotEqual(t, fe, nil) - Equal(t, fe.ActualTag(), "hexcolor|rgb|rgba|hsl|hsla") - - validate.RegisterAlias("req", "required,dive,iscoloralias") - arr := []string{"val1", "#fff", "#000"} - - errs = validate.Var(arr, "req") - NotEqual(t, errs, nil) - AssertError(t, errs, "[0]", "[0]", "[0]", "[0]", "iscoloralias") - - PanicMatches(t, func() { validate.RegisterAlias("exists!", "gt=5,lt=10") }, "Alias 'exists!' either contains restricted characters or is the same as a restricted tag needed for normal operation") -} - -func TestNilValidator(t *testing.T) { - - type TestStruct struct { - Test string `validate:"required"` - } - - ts := TestStruct{} - - var val *Validate - - fn := func(fl FieldLevel) bool { - - return fl.Parent().String() == fl.Field().String() - } - - PanicMatches(t, func() { val.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) }, "runtime error: invalid memory address or nil pointer dereference") - PanicMatches(t, func() { _ = val.RegisterValidation("something", fn) }, "runtime error: invalid memory address or nil pointer dereference") - PanicMatches(t, func() { _ = val.Var(ts.Test, "required") }, "runtime error: invalid memory address or nil pointer dereference") - PanicMatches(t, func() { _ = val.VarWithValue("test", ts.Test, "required") }, "runtime error: invalid memory address or nil pointer dereference") - PanicMatches(t, func() { _ = val.Struct(ts) }, "runtime error: invalid memory address or nil pointer dereference") - PanicMatches(t, func() { _ = val.StructExcept(ts, "Test") }, "runtime error: invalid memory address or nil pointer dereference") - PanicMatches(t, func() { _ = val.StructPartial(ts, "Test") }, "runtime error: invalid memory address or nil pointer dereference") -} - -func TestStructPartial(t *testing.T) { - p1 := []string{ - "NoTag", - "Required", - } - - p2 := []string{ - "SubSlice[0].Test", - "Sub", - "SubIgnore", - "Anonymous.A", - } - - p3 := []string{ - "SubTest.Test", - } - - p4 := []string{ - "A", - } - - tPartial := &TestPartial{ - NoTag: "NoTag", - Required: "Required", - - SubSlice: []*SubTest{ - { - - Test: "Required", - }, - { - - Test: "Required", - }, - }, - - Sub: &SubTest{ - Test: "1", - }, - SubIgnore: &SubTest{ - Test: "", - }, - Anonymous: struct { - A string `validate:"required"` - ASubSlice []*SubTest `validate:"required,dive"` - SubAnonStruct []struct { - Test string `validate:"required"` - OtherTest string `validate:"required"` - } `validate:"required,dive"` - }{ - A: "1", - ASubSlice: []*SubTest{ - { - Test: "Required", - }, - { - Test: "Required", - }, - }, - - SubAnonStruct: []struct { - Test string `validate:"required"` - OtherTest string `validate:"required"` - }{ - {"Required", "RequiredOther"}, - {"Required", "RequiredOther"}, - }, - }, - } - - validate := New() - - // the following should all return no errors as everything is valid in - // the default state - errs := validate.StructPartialCtx(context.Background(), tPartial, p1...) - Equal(t, errs, nil) - - errs = validate.StructPartial(tPartial, p2...) - Equal(t, errs, nil) - - // this isn't really a robust test, but is ment to illustrate the ANON CASE below - errs = validate.StructPartial(tPartial.SubSlice[0], p3...) - Equal(t, errs, nil) - - errs = validate.StructExceptCtx(context.Background(), tPartial, p1...) - Equal(t, errs, nil) - - errs = validate.StructExcept(tPartial, p2...) - Equal(t, errs, nil) - - // mod tParial for required feild and re-test making sure invalid fields are NOT required: - tPartial.Required = "" - - errs = validate.StructExcept(tPartial, p1...) - Equal(t, errs, nil) - - errs = validate.StructPartial(tPartial, p2...) - Equal(t, errs, nil) - - // inversion and retesting Partial to generate failures: - errs = validate.StructPartial(tPartial, p1...) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required") - - errs = validate.StructExcept(tPartial, p2...) - AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required") - - // reset Required field, and set nested struct - tPartial.Required = "Required" - tPartial.Anonymous.A = "" - - // will pass as unset feilds is not going to be tested - errs = validate.StructPartial(tPartial, p1...) - Equal(t, errs, nil) - - errs = validate.StructExcept(tPartial, p2...) - Equal(t, errs, nil) - - // ANON CASE the response here is strange, it clearly does what it is being told to - errs = validate.StructExcept(tPartial.Anonymous, p4...) - Equal(t, errs, nil) - - // will fail as unset feild is tested - errs = validate.StructPartial(tPartial, p2...) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required") - - errs = validate.StructExcept(tPartial, p1...) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required") - - // reset nested struct and unset struct in slice - tPartial.Anonymous.A = "Required" - tPartial.SubSlice[0].Test = "" - - // these will pass as unset item is NOT tested - errs = validate.StructPartial(tPartial, p1...) - Equal(t, errs, nil) - - errs = validate.StructExcept(tPartial, p2...) - Equal(t, errs, nil) - - // these will fail as unset item IS tested - errs = validate.StructExcept(tPartial, p1...) - AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") - Equal(t, len(errs.(ValidationErrors)), 1) - - errs = validate.StructPartial(tPartial, p2...) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") - Equal(t, len(errs.(ValidationErrors)), 1) - - // Unset second slice member concurrently to test dive behavior: - tPartial.SubSlice[1].Test = "" - - errs = validate.StructPartial(tPartial, p1...) - Equal(t, errs, nil) - - // NOTE: When specifying nested items, it is still the users responsibility - // to specify the dive tag, the library does not override this. - errs = validate.StructExcept(tPartial, p2...) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required") - - errs = validate.StructExcept(tPartial, p1...) - Equal(t, len(errs.(ValidationErrors)), 2) - AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") - AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required") - - errs = validate.StructPartial(tPartial, p2...) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") - - // reset struct in slice, and unset struct in slice in unset posistion - tPartial.SubSlice[0].Test = "Required" - - // these will pass as the unset item is NOT tested - errs = validate.StructPartial(tPartial, p1...) - Equal(t, errs, nil) - - errs = validate.StructPartial(tPartial, p2...) - Equal(t, errs, nil) - - // testing for missing item by exception, yes it dives and fails - errs = validate.StructExcept(tPartial, p1...) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required") - - errs = validate.StructExcept(tPartial, p2...) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required") - - tPartial.SubSlice[1].Test = "Required" - - tPartial.Anonymous.SubAnonStruct[0].Test = "" - // these will pass as the unset item is NOT tested - errs = validate.StructPartial(tPartial, p1...) - Equal(t, errs, nil) - - errs = validate.StructPartial(tPartial, p2...) - Equal(t, errs, nil) - - errs = validate.StructExcept(tPartial, p1...) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "Test", "required") - - errs = validate.StructExcept(tPartial, p2...) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "Test", "required") - -} - -func TestCrossStructLteFieldValidation(t *testing.T) { - var errs error - validate := New() - - type Inner struct { - CreatedAt *time.Time - String string - Int int - Uint uint - Float float64 - Array []string - } - - type Test struct { - Inner *Inner - CreatedAt *time.Time `validate:"ltecsfield=Inner.CreatedAt"` - String string `validate:"ltecsfield=Inner.String"` - Int int `validate:"ltecsfield=Inner.Int"` - Uint uint `validate:"ltecsfield=Inner.Uint"` - Float float64 `validate:"ltecsfield=Inner.Float"` - Array []string `validate:"ltecsfield=Inner.Array"` - } - - now := time.Now().UTC() - then := now.Add(time.Hour * 5) - - inner := &Inner{ - CreatedAt: &then, - String: "abcd", - Int: 13, - Uint: 13, - Float: 1.13, - Array: []string{"val1", "val2"}, - } - - test := &Test{ - Inner: inner, - CreatedAt: &now, - String: "abc", - Int: 12, - Uint: 12, - Float: 1.12, - Array: []string{"val1"}, - } - - errs = validate.Struct(test) - Equal(t, errs, nil) - - test.CreatedAt = &then - test.String = "abcd" - test.Int = 13 - test.Uint = 13 - test.Float = 1.13 - test.Array = []string{"val1", "val2"} - - errs = validate.Struct(test) - Equal(t, errs, nil) - - after := now.Add(time.Hour * 10) - - test.CreatedAt = &after - test.String = "abce" - test.Int = 14 - test.Uint = 14 - test.Float = 1.14 - test.Array = []string{"val1", "val2", "val3"} - - errs = validate.Struct(test) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltecsfield") - AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltecsfield") - AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltecsfield") - AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltecsfield") - AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltecsfield") - AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltecsfield") - - errs = validate.VarWithValueCtx(context.Background(), 1, "", "ltecsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltecsfield") - - // this test is for the WARNING about unforeseen validation issues. - errs = validate.VarWithValue(test, now, "ltecsfield") - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 6) - AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltecsfield") - AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltecsfield") - AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltecsfield") - AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltecsfield") - AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltecsfield") - AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltecsfield") - - type Other struct { - Value string - } - - type Test2 struct { - Value Other - Time time.Time `validate:"ltecsfield=Value"` - } - - tst := Test2{ - Value: Other{Value: "StringVal"}, - Time: then, - } - - errs = validate.Struct(tst) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltecsfield") - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltecsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour, "ltecsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltecsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltecsfield") - - errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltecsfield") - Equal(t, errs, nil) - - // -- Validations for a struct and an inner struct with time.Duration type fields. - - type TimeDurationInner struct { - Duration time.Duration - } - var timeDurationInner *TimeDurationInner - - type TimeDurationTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"ltecsfield=Inner.Duration"` - } - var timeDurationTest *TimeDurationTest - - timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationInner = &TimeDurationInner{time.Hour} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltecsfield") - - type TimeDurationOmitemptyTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"omitempty,ltecsfield=Inner.Duration"` - } - var timeDurationOmitemptyTest *TimeDurationOmitemptyTest - - timeDurationInner = &TimeDurationInner{-time.Minute} - timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestCrossStructLtFieldValidation(t *testing.T) { - var errs error - validate := New() - - type Inner struct { - CreatedAt *time.Time - String string - Int int - Uint uint - Float float64 - Array []string - } - - type Test struct { - Inner *Inner - CreatedAt *time.Time `validate:"ltcsfield=Inner.CreatedAt"` - String string `validate:"ltcsfield=Inner.String"` - Int int `validate:"ltcsfield=Inner.Int"` - Uint uint `validate:"ltcsfield=Inner.Uint"` - Float float64 `validate:"ltcsfield=Inner.Float"` - Array []string `validate:"ltcsfield=Inner.Array"` - } - - now := time.Now().UTC() - then := now.Add(time.Hour * 5) - - inner := &Inner{ - CreatedAt: &then, - String: "abcd", - Int: 13, - Uint: 13, - Float: 1.13, - Array: []string{"val1", "val2"}, - } - - test := &Test{ - Inner: inner, - CreatedAt: &now, - String: "abc", - Int: 12, - Uint: 12, - Float: 1.12, - Array: []string{"val1"}, - } - - errs = validate.Struct(test) - Equal(t, errs, nil) - - test.CreatedAt = &then - test.String = "abcd" - test.Int = 13 - test.Uint = 13 - test.Float = 1.13 - test.Array = []string{"val1", "val2"} - - errs = validate.Struct(test) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltcsfield") - AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltcsfield") - AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltcsfield") - AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltcsfield") - AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltcsfield") - AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltcsfield") - - errs = validate.VarWithValue(1, "", "ltcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltcsfield") - - // this test is for the WARNING about unforeseen validation issues. - errs = validate.VarWithValue(test, now, "ltcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltcsfield") - AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltcsfield") - AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltcsfield") - AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltcsfield") - AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltcsfield") - AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltcsfield") - - type Other struct { - Value string - } - - type Test2 struct { - Value Other - Time time.Time `validate:"ltcsfield=Value"` - } - - tst := Test2{ - Value: Other{Value: "StringVal"}, - Time: then, - } - - errs = validate.Struct(tst) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltcsfield") - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltcsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour, "ltcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltcsfield") - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltcsfield") - - errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltcsfield") - Equal(t, errs, nil) - - // -- Validations for a struct and an inner struct with time.Duration type fields. - - type TimeDurationInner struct { - Duration time.Duration - } - var timeDurationInner *TimeDurationInner - - type TimeDurationTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"ltcsfield=Inner.Duration"` - } - var timeDurationTest *TimeDurationTest - - timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationInner = &TimeDurationInner{time.Hour} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltcsfield") - - timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltcsfield") - - type TimeDurationOmitemptyTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"omitempty,ltcsfield=Inner.Duration"` - } - var timeDurationOmitemptyTest *TimeDurationOmitemptyTest - - timeDurationInner = &TimeDurationInner{-time.Minute} - timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestCrossStructGteFieldValidation(t *testing.T) { - var errs error - validate := New() - - type Inner struct { - CreatedAt *time.Time - String string - Int int - Uint uint - Float float64 - Array []string - } - - type Test struct { - Inner *Inner - CreatedAt *time.Time `validate:"gtecsfield=Inner.CreatedAt"` - String string `validate:"gtecsfield=Inner.String"` - Int int `validate:"gtecsfield=Inner.Int"` - Uint uint `validate:"gtecsfield=Inner.Uint"` - Float float64 `validate:"gtecsfield=Inner.Float"` - Array []string `validate:"gtecsfield=Inner.Array"` - } - - now := time.Now().UTC() - then := now.Add(time.Hour * -5) - - inner := &Inner{ - CreatedAt: &then, - String: "abcd", - Int: 13, - Uint: 13, - Float: 1.13, - Array: []string{"val1", "val2"}, - } - - test := &Test{ - Inner: inner, - CreatedAt: &now, - String: "abcde", - Int: 14, - Uint: 14, - Float: 1.14, - Array: []string{"val1", "val2", "val3"}, - } - - errs = validate.Struct(test) - Equal(t, errs, nil) - - test.CreatedAt = &then - test.String = "abcd" - test.Int = 13 - test.Uint = 13 - test.Float = 1.13 - test.Array = []string{"val1", "val2"} - - errs = validate.Struct(test) - Equal(t, errs, nil) - - before := now.Add(time.Hour * -10) - - test.CreatedAt = &before - test.String = "abc" - test.Int = 12 - test.Uint = 12 - test.Float = 1.12 - test.Array = []string{"val1"} - - errs = validate.Struct(test) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtecsfield") - AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtecsfield") - AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtecsfield") - AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtecsfield") - AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtecsfield") - AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtecsfield") - - errs = validate.VarWithValue(1, "", "gtecsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtecsfield") - - // this test is for the WARNING about unforeseen validation issues. - errs = validate.VarWithValue(test, now, "gtecsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtecsfield") - AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtecsfield") - AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtecsfield") - AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtecsfield") - AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtecsfield") - AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtecsfield") - - type Other struct { - Value string - } - - type Test2 struct { - Value Other - Time time.Time `validate:"gtecsfield=Value"` - } - - tst := Test2{ - Value: Other{Value: "StringVal"}, - Time: then, - } - - errs = validate.Struct(tst) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtecsfield") - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtecsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour, "gtecsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtecsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtecsfield") - - errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtecsfield") - Equal(t, errs, nil) - - // -- Validations for a struct and an inner struct with time.Duration type fields. - - type TimeDurationInner struct { - Duration time.Duration - } - var timeDurationInner *TimeDurationInner - - type TimeDurationTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"gtecsfield=Inner.Duration"` - } - var timeDurationTest *TimeDurationTest - - timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationInner = &TimeDurationInner{time.Hour} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtecsfield") - - type TimeDurationOmitemptyTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"omitempty,gtecsfield=Inner.Duration"` - } - var timeDurationOmitemptyTest *TimeDurationOmitemptyTest - - timeDurationInner = &TimeDurationInner{time.Hour} - timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestCrossStructGtFieldValidation(t *testing.T) { - var errs error - validate := New() - - type Inner struct { - CreatedAt *time.Time - String string - Int int - Uint uint - Float float64 - Array []string - } - - type Test struct { - Inner *Inner - CreatedAt *time.Time `validate:"gtcsfield=Inner.CreatedAt"` - String string `validate:"gtcsfield=Inner.String"` - Int int `validate:"gtcsfield=Inner.Int"` - Uint uint `validate:"gtcsfield=Inner.Uint"` - Float float64 `validate:"gtcsfield=Inner.Float"` - Array []string `validate:"gtcsfield=Inner.Array"` - } - - now := time.Now().UTC() - then := now.Add(time.Hour * -5) - - inner := &Inner{ - CreatedAt: &then, - String: "abcd", - Int: 13, - Uint: 13, - Float: 1.13, - Array: []string{"val1", "val2"}, - } - - test := &Test{ - Inner: inner, - CreatedAt: &now, - String: "abcde", - Int: 14, - Uint: 14, - Float: 1.14, - Array: []string{"val1", "val2", "val3"}, - } - - errs = validate.Struct(test) - Equal(t, errs, nil) - - test.CreatedAt = &then - test.String = "abcd" - test.Int = 13 - test.Uint = 13 - test.Float = 1.13 - test.Array = []string{"val1", "val2"} - - errs = validate.Struct(test) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtcsfield") - AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtcsfield") - AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtcsfield") - AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtcsfield") - AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtcsfield") - AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtcsfield") - - errs = validate.VarWithValue(1, "", "gtcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtcsfield") - - // this test is for the WARNING about unforeseen validation issues. - errs = validate.VarWithValue(test, now, "gtcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtcsfield") - AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtcsfield") - AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtcsfield") - AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtcsfield") - AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtcsfield") - AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtcsfield") - - type Other struct { - Value string - } - - type Test2 struct { - Value Other - Time time.Time `validate:"gtcsfield=Value"` - } - - tst := Test2{ - Value: Other{Value: "StringVal"}, - Time: then, - } - - errs = validate.Struct(tst) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtcsfield") - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtcsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour, "gtcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtcsfield") - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtcsfield") - - errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtcsfield") - Equal(t, errs, nil) - - // -- Validations for a struct and an inner struct with time.Duration type fields. - - type TimeDurationInner struct { - Duration time.Duration - } - var timeDurationInner *TimeDurationInner - - type TimeDurationTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"gtcsfield=Inner.Duration"` - } - var timeDurationTest *TimeDurationTest - - timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationInner = &TimeDurationInner{time.Hour} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtcsfield") - - timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtcsfield") - - type TimeDurationOmitemptyTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"omitempty,gtcsfield=Inner.Duration"` - } - var timeDurationOmitemptyTest *TimeDurationOmitemptyTest - - timeDurationInner = &TimeDurationInner{time.Hour} - timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestCrossStructNeFieldValidation(t *testing.T) { - var errs error - validate := New() - - type Inner struct { - CreatedAt *time.Time - } - - type Test struct { - Inner *Inner - CreatedAt *time.Time `validate:"necsfield=Inner.CreatedAt"` - } - - now := time.Now().UTC() - then := now.Add(time.Hour * 5) - - inner := &Inner{ - CreatedAt: &then, - } - - test := &Test{ - Inner: inner, - CreatedAt: &now, - } - - errs = validate.Struct(test) - Equal(t, errs, nil) - - test.CreatedAt = &then - - errs = validate.Struct(test) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "necsfield") - - var j uint64 - var k float64 - var j2 uint64 - var k2 float64 - s := "abcd" - i := 1 - j = 1 - k = 1.543 - arr := []string{"test"} - - s2 := "abcd" - i2 := 1 - j2 = 1 - k2 = 1.543 - arr2 := []string{"test"} - arr3 := []string{"test", "test2"} - now2 := now - - errs = validate.VarWithValue(s, s2, "necsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "necsfield") - - errs = validate.VarWithValue(i2, i, "necsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "necsfield") - - errs = validate.VarWithValue(j2, j, "necsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "necsfield") - - errs = validate.VarWithValue(k2, k, "necsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "necsfield") - - errs = validate.VarWithValue(arr2, arr, "necsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "necsfield") - - errs = validate.VarWithValue(now2, now, "necsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "necsfield") - - errs = validate.VarWithValue(arr3, arr, "necsfield") - Equal(t, errs, nil) - - type SInner struct { - Name string - } - - type TStruct struct { - Inner *SInner - CreatedAt *time.Time `validate:"necsfield=Inner"` - } - - sinner := &SInner{ - Name: "NAME", - } - - test2 := &TStruct{ - Inner: sinner, - CreatedAt: &now, - } - - errs = validate.Struct(test2) - Equal(t, errs, nil) - - test2.Inner = nil - errs = validate.Struct(test2) - Equal(t, errs, nil) - - errs = validate.VarWithValue(nil, 1, "necsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "necsfield") - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "necsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "necsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour, "necsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "necsfield") - - errs = validate.VarWithValue(time.Duration(0), time.Duration(0), "omitempty,necsfield") - Equal(t, errs, nil) - - // -- Validations for a struct and an inner struct with time.Duration type fields. - - type TimeDurationInner struct { - Duration time.Duration - } - var timeDurationInner *TimeDurationInner - - type TimeDurationTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"necsfield=Inner.Duration"` - } - var timeDurationTest *TimeDurationTest - - timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationInner = &TimeDurationInner{time.Hour} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "necsfield") - - type TimeDurationOmitemptyTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"omitempty,necsfield=Inner.Duration"` - } - var timeDurationOmitemptyTest *TimeDurationOmitemptyTest - - timeDurationInner = &TimeDurationInner{time.Duration(0)} - timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestCrossStructEqFieldValidation(t *testing.T) { - var errs error - validate := New() - - type Inner struct { - CreatedAt *time.Time - } - - type Test struct { - Inner *Inner - CreatedAt *time.Time `validate:"eqcsfield=Inner.CreatedAt"` - } - - now := time.Now().UTC() - - inner := &Inner{ - CreatedAt: &now, - } - - test := &Test{ - Inner: inner, - CreatedAt: &now, - } - - errs = validate.Struct(test) - Equal(t, errs, nil) - - newTime := time.Now().UTC() - test.CreatedAt = &newTime - - errs = validate.Struct(test) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield") - - var j uint64 - var k float64 - s := "abcd" - i := 1 - j = 1 - k = 1.543 - arr := []string{"test"} - - var j2 uint64 - var k2 float64 - s2 := "abcd" - i2 := 1 - j2 = 1 - k2 = 1.543 - arr2 := []string{"test"} - arr3 := []string{"test", "test2"} - now2 := now - - errs = validate.VarWithValue(s, s2, "eqcsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(i2, i, "eqcsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(j2, j, "eqcsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(k2, k, "eqcsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(arr2, arr, "eqcsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(now2, now, "eqcsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(arr3, arr, "eqcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eqcsfield") - - type SInner struct { - Name string - } - - type TStruct struct { - Inner *SInner - CreatedAt *time.Time `validate:"eqcsfield=Inner"` - } - - sinner := &SInner{ - Name: "NAME", - } - - test2 := &TStruct{ - Inner: sinner, - CreatedAt: &now, - } - - errs = validate.Struct(test2) - NotEqual(t, errs, nil) - AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield") - - test2.Inner = nil - errs = validate.Struct(test2) - NotEqual(t, errs, nil) - AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield") - - errs = validate.VarWithValue(nil, 1, "eqcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eqcsfield") - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour, "eqcsfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "eqcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eqcsfield") - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "eqcsfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eqcsfield") - - errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,eqcsfield") - Equal(t, errs, nil) - - // -- Validations for a struct and an inner struct with time.Duration type fields. - - type TimeDurationInner struct { - Duration time.Duration - } - var timeDurationInner *TimeDurationInner - - type TimeDurationTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"eqcsfield=Inner.Duration"` - } - var timeDurationTest *TimeDurationTest - - timeDurationInner = &TimeDurationInner{time.Hour} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eqcsfield") - - timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} - timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eqcsfield") - - type TimeDurationOmitemptyTest struct { - Inner *TimeDurationInner - Duration time.Duration `validate:"omitempty,eqcsfield=Inner.Duration"` - } - var timeDurationOmitemptyTest *TimeDurationOmitemptyTest - - timeDurationInner = &TimeDurationInner{time.Hour} - timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestCrossNamespaceFieldValidation(t *testing.T) { - - type SliceStruct struct { - Name string - } - - type Inner struct { - CreatedAt *time.Time - Slice []string - SliceStructs []*SliceStruct - SliceSlice [][]string - SliceSliceStruct [][]*SliceStruct - SliceMap []map[string]string - Map map[string]string - MapMap map[string]map[string]string - MapStructs map[string]*SliceStruct - MapMapStruct map[string]map[string]*SliceStruct - MapSlice map[string][]string - MapInt map[int]string - MapInt8 map[int8]string - MapInt16 map[int16]string - MapInt32 map[int32]string - MapInt64 map[int64]string - MapUint map[uint]string - MapUint8 map[uint8]string - MapUint16 map[uint16]string - MapUint32 map[uint32]string - MapUint64 map[uint64]string - MapFloat32 map[float32]string - MapFloat64 map[float64]string - MapBool map[bool]string - } - - type Test struct { - Inner *Inner - CreatedAt *time.Time - } - - now := time.Now() - - inner := &Inner{ - CreatedAt: &now, - Slice: []string{"val1", "val2", "val3"}, - SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, - SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}}, - SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}}, - SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}}, - Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"}, - MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}}, - MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}}, - MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}}, - MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}}, - MapInt: map[int]string{1: "val1", 2: "val2", 3: "val3"}, - MapInt8: map[int8]string{1: "val1", 2: "val2", 3: "val3"}, - MapInt16: map[int16]string{1: "val1", 2: "val2", 3: "val3"}, - MapInt32: map[int32]string{1: "val1", 2: "val2", 3: "val3"}, - MapInt64: map[int64]string{1: "val1", 2: "val2", 3: "val3"}, - MapUint: map[uint]string{1: "val1", 2: "val2", 3: "val3"}, - MapUint8: map[uint8]string{1: "val1", 2: "val2", 3: "val3"}, - MapUint16: map[uint16]string{1: "val1", 2: "val2", 3: "val3"}, - MapUint32: map[uint32]string{1: "val1", 2: "val2", 3: "val3"}, - MapUint64: map[uint64]string{1: "val1", 2: "val2", 3: "val3"}, - MapFloat32: map[float32]string{1.01: "val1", 2.02: "val2", 3.03: "val3"}, - MapFloat64: map[float64]string{1.01: "val1", 2.02: "val2", 3.03: "val3"}, - MapBool: map[bool]string{true: "val1", false: "val2"}, - } - - test := &Test{ - Inner: inner, - CreatedAt: &now, - } - - val := reflect.ValueOf(test) - - vd := New() - v := &validate{ - v: vd, - } - - current, kind, _, ok := v.getStructFieldOKInternal(val, "Inner.CreatedAt") - Equal(t, ok, true) - Equal(t, kind, reflect.Struct) - tm, ok := current.Interface().(time.Time) - Equal(t, ok, true) - Equal(t, tm, now) - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.Slice[1]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, _, _, ok = v.getStructFieldOKInternal(val, "Inner.CrazyNonExistantField") - Equal(t, ok, false) - - current, _, _, ok = v.getStructFieldOKInternal(val, "Inner.Slice[101]") - Equal(t, ok, false) - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.Map[key3]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val3") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapMap[key2][key2-1]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapStructs[key2].Name") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "name2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapMapStruct[key3][key3-1].Name") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "name3") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.SliceSlice[2][0]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "7") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.SliceSliceStruct[2][1].Name") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "name8") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.SliceMap[1][key5]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val5") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapSlice[key3][2]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "9") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapInt[2]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapInt8[2]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapInt16[2]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapInt32[2]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapInt64[2]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapUint[2]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapUint8[2]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapUint16[2]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapUint32[2]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapUint64[2]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapFloat32[3.03]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val3") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapFloat64[2.02]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val2") - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapBool[true]") - Equal(t, ok, true) - Equal(t, kind, reflect.String) - Equal(t, current.String(), "val1") - - inner = &Inner{ - CreatedAt: &now, - Slice: []string{"val1", "val2", "val3"}, - SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, nil}, - SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}}, - SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}}, - SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}}, - Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"}, - MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}}, - MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}}, - MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}}, - MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}}, - } - - test = &Test{ - Inner: inner, - CreatedAt: nil, - } - - val = reflect.ValueOf(test) - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.SliceStructs[2]") - Equal(t, ok, true) - Equal(t, kind, reflect.Ptr) - Equal(t, current.String(), "<*validator.SliceStruct Value>") - Equal(t, current.IsNil(), true) - - current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.SliceStructs[2].Name") - Equal(t, ok, false) - Equal(t, kind, reflect.Ptr) - Equal(t, current.String(), "<*validator.SliceStruct Value>") - Equal(t, current.IsNil(), true) - - PanicMatches(t, func() { v.getStructFieldOKInternal(reflect.ValueOf(1), "crazyinput") }, "Invalid field namespace") -} - -func TestExistsValidation(t *testing.T) { - - jsonText := "{ \"truthiness2\": true }" - - type Thing struct { - Truthiness *bool `json:"truthiness" validate:"required"` - } - - var ting Thing - - err := json.Unmarshal([]byte(jsonText), &ting) - Equal(t, err, nil) - NotEqual(t, ting, nil) - Equal(t, ting.Truthiness, nil) - - validate := New() - errs := validate.Struct(ting) - NotEqual(t, errs, nil) - AssertError(t, errs, "Thing.Truthiness", "Thing.Truthiness", "Truthiness", "Truthiness", "required") - - jsonText = "{ \"truthiness\": true }" - - err = json.Unmarshal([]byte(jsonText), &ting) - Equal(t, err, nil) - NotEqual(t, ting, nil) - Equal(t, ting.Truthiness, true) - - errs = validate.Struct(ting) - Equal(t, errs, nil) -} - -func TestSQLValue2Validation(t *testing.T) { - - validate := New() - validate.RegisterCustomTypeFunc(ValidateValuerType, valuer{}, (*driver.Valuer)(nil), sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{}) - validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) - validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1) - - val := valuer{ - Name: "", - } - - errs := validate.Var(val, "required") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "required") - - val.Name = "Valid Name" - errs = validate.VarCtx(context.Background(), val, "required") - Equal(t, errs, nil) - - val.Name = "errorme" - - PanicMatches(t, func() { _ = validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error") - - myVal := valuer{ - Name: "", - } - - errs = validate.Var(myVal, "required") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "required") - - cust := MadeUpCustomType{ - FirstName: "Joey", - LastName: "Bloggs", - } - - c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2} - - errs = validate.Struct(c) - Equal(t, errs, nil) - - c.MadeUp.FirstName = "" - c.OverriddenInt = 1 - - errs = validate.Struct(c) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 2) - AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "CustomMadeUpStruct.MadeUp", "MadeUp", "MadeUp", "required") - AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "OverriddenInt", "gt") -} - -func TestSQLValueValidation(t *testing.T) { - - validate := New() - validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{}) - validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) - validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1) - - val := valuer{ - Name: "", - } - - errs := validate.Var(val, "required") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "required") - - val.Name = "Valid Name" - errs = validate.Var(val, "required") - Equal(t, errs, nil) - - val.Name = "errorme" - - PanicMatches(t, func() { errs = validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error") - - myVal := valuer{ - Name: "", - } - - errs = validate.Var(myVal, "required") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "required") - - cust := MadeUpCustomType{ - FirstName: "Joey", - LastName: "Bloggs", - } - - c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2} - - errs = validate.Struct(c) - Equal(t, errs, nil) - - c.MadeUp.FirstName = "" - c.OverriddenInt = 1 - - errs = validate.Struct(c) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 2) - AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "CustomMadeUpStruct.MadeUp", "MadeUp", "MadeUp", "required") - AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "OverriddenInt", "gt") -} - -func TestMACValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"3D:F2:C9:A6:B3:4F", true}, - {"3D-F2-C9-A6-B3:4F", false}, - {"123", false}, - {"", false}, - {"abacaba", false}, - {"00:25:96:FF:FE:12:34:56", true}, - {"0025:96FF:FE12:3456", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "mac") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d mac failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d mac failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "mac" { - t.Fatalf("Index: %d mac failed Error: %s", i, errs) - } - } - } - } -} - -func TestIPValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"10.0.0.1", true}, - {"172.16.0.1", true}, - {"192.168.0.1", true}, - {"192.168.255.254", true}, - {"192.168.255.256", false}, - {"172.16.255.254", true}, - {"172.16.256.255", false}, - {"2001:cdba:0000:0000:0000:0000:3257:9652", true}, - {"2001:cdba:0:0:0:0:3257:9652", true}, - {"2001:cdba::3257:9652", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "ip") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d ip failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d ip failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "ip" { - t.Fatalf("Index: %d ip failed Error: %s", i, errs) - } - } - } - } -} - -func TestIPv6Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"10.0.0.1", false}, - {"172.16.0.1", false}, - {"192.168.0.1", false}, - {"192.168.255.254", false}, - {"192.168.255.256", false}, - {"172.16.255.254", false}, - {"172.16.256.255", false}, - {"2001:cdba:0000:0000:0000:0000:3257:9652", true}, - {"2001:cdba:0:0:0:0:3257:9652", true}, - {"2001:cdba::3257:9652", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "ipv6") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "ipv6" { - t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs) - } - } - } - } -} - -func TestIPv4Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"10.0.0.1", true}, - {"172.16.0.1", true}, - {"192.168.0.1", true}, - {"192.168.255.254", true}, - {"192.168.255.256", false}, - {"172.16.255.254", true}, - {"172.16.256.255", false}, - {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, - {"2001:cdba:0:0:0:0:3257:9652", false}, - {"2001:cdba::3257:9652", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "ipv4") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "ipv4" { - t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs) - } - } - } - } -} - -func TestCIDRValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"10.0.0.0/0", true}, - {"10.0.0.1/8", true}, - {"172.16.0.1/16", true}, - {"192.168.0.1/24", true}, - {"192.168.255.254/24", true}, - {"192.168.255.254/48", false}, - {"192.168.255.256/24", false}, - {"172.16.255.254/16", true}, - {"172.16.256.255/16", false}, - {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true}, - {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false}, - {"2001:cdba:0:0:0:0:3257:9652/32", true}, - {"2001:cdba::3257:9652/16", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "cidr") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d cidr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d cidr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "cidr" { - t.Fatalf("Index: %d cidr failed Error: %s", i, errs) - } - } - } - } -} - -func TestCIDRv6Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"10.0.0.0/0", false}, - {"10.0.0.1/8", false}, - {"172.16.0.1/16", false}, - {"192.168.0.1/24", false}, - {"192.168.255.254/24", false}, - {"192.168.255.254/48", false}, - {"192.168.255.256/24", false}, - {"172.16.255.254/16", false}, - {"172.16.256.255/16", false}, - {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true}, - {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false}, - {"2001:cdba:0:0:0:0:3257:9652/32", true}, - {"2001:cdba::3257:9652/16", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "cidrv6") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "cidrv6" { - t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs) - } - } - } - } -} - -func TestCIDRv4Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"10.0.0.0/0", true}, - {"10.0.0.1/8", true}, - {"172.16.0.1/16", true}, - {"192.168.0.1/24", true}, - {"192.168.255.254/24", true}, - {"192.168.255.254/48", false}, - {"192.168.255.256/24", false}, - {"172.16.255.254/16", true}, - {"172.16.256.255/16", false}, - {"2001:cdba:0000:0000:0000:0000:3257:9652/64", false}, - {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false}, - {"2001:cdba:0:0:0:0:3257:9652/32", false}, - {"2001:cdba::3257:9652/16", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "cidrv4") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "cidrv4" { - t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs) - } - } - } - } -} - -func TestTCPAddrValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {":80", false}, - {"127.0.0.1:80", true}, - {"[::1]:80", true}, - {"256.0.0.0:1", false}, - {"[::1]", false}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Var(test.param, "tcp_addr") - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "tcp_addr" { - t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs) - } - } - } - } -} - -func TestTCP6AddrValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {":80", false}, - {"127.0.0.1:80", false}, - {"[::1]:80", true}, - {"256.0.0.0:1", false}, - {"[::1]", false}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Var(test.param, "tcp6_addr") - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "tcp6_addr" { - t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs) - } - } - } - } -} - -func TestTCP4AddrValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {":80", false}, - {"127.0.0.1:80", true}, - {"[::1]:80", false}, // https://github.com/golang/go/issues/14037 - {"256.0.0.0:1", false}, - {"[::1]", false}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Var(test.param, "tcp4_addr") - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Log(test.param, IsEqual(errs, nil)) - t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "tcp4_addr" { - t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs) - } - } - } - } -} - -func TestUDPAddrValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {":80", false}, - {"127.0.0.1:80", true}, - {"[::1]:80", true}, - {"256.0.0.0:1", false}, - {"[::1]", false}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Var(test.param, "udp_addr") - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "udp_addr" { - t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs) - } - } - } - } -} - -func TestUDP6AddrValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {":80", false}, - {"127.0.0.1:80", false}, - {"[::1]:80", true}, - {"256.0.0.0:1", false}, - {"[::1]", false}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Var(test.param, "udp6_addr") - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "udp6_addr" { - t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs) - } - } - } - } -} - -func TestUDP4AddrValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {":80", false}, - {"127.0.0.1:80", true}, - {"[::1]:80", false}, // https://github.com/golang/go/issues/14037 - {"256.0.0.0:1", false}, - {"[::1]", false}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Var(test.param, "udp4_addr") - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Log(test.param, IsEqual(errs, nil)) - t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "udp4_addr" { - t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs) - } - } - } - } -} - -func TestIPAddrValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"127.0.0.1", true}, - {"127.0.0.1:80", false}, - {"::1", true}, - {"256.0.0.0", false}, - {"localhost", false}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Var(test.param, "ip_addr") - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "ip_addr" { - t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs) - } - } - } - } -} - -func TestIP6AddrValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"127.0.0.1", false}, // https://github.com/golang/go/issues/14037 - {"127.0.0.1:80", false}, - {"::1", true}, - {"0:0:0:0:0:0:0:1", true}, - {"256.0.0.0", false}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Var(test.param, "ip6_addr") - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "ip6_addr" { - t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs) - } - } - } - } -} - -func TestIP4AddrValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"127.0.0.1", true}, - {"127.0.0.1:80", false}, - {"::1", false}, // https://github.com/golang/go/issues/14037 - {"256.0.0.0", false}, - {"localhost", false}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Var(test.param, "ip4_addr") - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Log(test.param, IsEqual(errs, nil)) - t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "ip4_addr" { - t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs) - } - } - } - } -} - -func TestUnixAddrValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", true}, - {"v.sock", true}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Var(test.param, "unix_addr") - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Log(test.param, IsEqual(errs, nil)) - t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "unix_addr" { - t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs) - } - } - } - } -} - -func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) { - - validate := New() - - var m map[string]string - - errs := validate.Var(m, "required") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "required") - - m = map[string]string{} - errs = validate.Var(m, "required") - Equal(t, errs, nil) - - var arr [5]string - errs = validate.Var(arr, "required") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "required") - - arr[0] = "ok" - errs = validate.Var(arr, "required") - Equal(t, errs, nil) - - var s []string - errs = validate.Var(s, "required") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "required") - - s = []string{} - errs = validate.Var(s, "required") - Equal(t, errs, nil) - - var c chan string - errs = validate.Var(c, "required") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "required") - - c = make(chan string) - errs = validate.Var(c, "required") - Equal(t, errs, nil) - - var tst *int - errs = validate.Var(tst, "required") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "required") - - one := 1 - tst = &one - errs = validate.Var(tst, "required") - Equal(t, errs, nil) - - var iface interface{} - - errs = validate.Var(iface, "required") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "required") - - errs = validate.Var(iface, "omitempty,required") - Equal(t, errs, nil) - - errs = validate.Var(iface, "") - Equal(t, errs, nil) - - errs = validate.VarWithValue(nil, iface, "") - Equal(t, errs, nil) - - var f func(string) - - errs = validate.Var(f, "required") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "required") - - f = func(name string) {} - - errs = validate.Var(f, "required") - Equal(t, errs, nil) -} - -func TestDatePtrValidationIssueValidation(t *testing.T) { - - type Test struct { - LastViewed *time.Time - Reminder *time.Time - } - - test := &Test{} - - validate := New() - errs := validate.Struct(test) - Equal(t, errs, nil) -} - -func TestCommaAndPipeObfuscationValidation(t *testing.T) { - s := "My Name Is, |joeybloggs|" - - validate := New() - - errs := validate.Var(s, "excludesall=0x2C") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "excludesall") - - errs = validate.Var(s, "excludesall=0x7C") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "excludesall") -} - -func TestBadKeyValidation(t *testing.T) { - type Test struct { - Name string `validate:"required, "` - } - - tst := &Test{ - Name: "test", - } - - validate := New() - - PanicMatches(t, func() { _ = validate.Struct(tst) }, "Undefined validation function ' ' on field 'Name'") - - type Test2 struct { - Name string `validate:"required,,len=2"` - } - - tst2 := &Test2{ - Name: "test", - } - - PanicMatches(t, func() { _ = validate.Struct(tst2) }, "Invalid validation tag on field 'Name'") -} - -func TestInterfaceErrValidation(t *testing.T) { - - var v2 interface{} = 1 - var v1 interface{} = v2 - - validate := New() - errs := validate.Var(v1, "len=1") - Equal(t, errs, nil) - - errs = validate.Var(v2, "len=1") - Equal(t, errs, nil) - - type ExternalCMD struct { - Userid string `json:"userid"` - Action uint32 `json:"action"` - Data interface{} `json:"data,omitempty" validate:"required"` - } - - s := &ExternalCMD{ - Userid: "123456", - Action: 10000, - // Data: 1, - } - - errs = validate.Struct(s) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "ExternalCMD.Data", "ExternalCMD.Data", "Data", "Data", "required") - - type ExternalCMD2 struct { - Userid string `json:"userid"` - Action uint32 `json:"action"` - Data interface{} `json:"data,omitempty" validate:"len=1"` - } - - s2 := &ExternalCMD2{ - Userid: "123456", - Action: 10000, - // Data: 1, - } - - errs = validate.Struct(s2) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "ExternalCMD2.Data", "ExternalCMD2.Data", "Data", "Data", "len") - - s3 := &ExternalCMD2{ - Userid: "123456", - Action: 10000, - Data: 2, - } - - errs = validate.Struct(s3) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "ExternalCMD2.Data", "ExternalCMD2.Data", "Data", "Data", "len") - - type Inner struct { - Name string `validate:"required"` - } - - inner := &Inner{ - Name: "", - } - - s4 := &ExternalCMD{ - Userid: "123456", - Action: 10000, - Data: inner, - } - - errs = validate.Struct(s4) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "ExternalCMD.Data.Name", "ExternalCMD.Data.Name", "Name", "Name", "required") - - type TestMapStructPtr struct { - Errs map[int]interface{} `validate:"gt=0,dive,len=2"` - } - - mip := map[int]interface{}{0: &Inner{"ok"}, 3: nil, 4: &Inner{"ok"}} - - msp := &TestMapStructPtr{ - Errs: mip, - } - - errs = validate.Struct(msp) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "TestMapStructPtr.Errs[3]", "TestMapStructPtr.Errs[3]", "Errs[3]", "Errs[3]", "len") - - type TestMultiDimensionalStructs struct { - Errs [][]interface{} `validate:"gt=0,dive,dive"` - } - - var errStructArray [][]interface{} - - errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}}) - errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}}) - - tms := &TestMultiDimensionalStructs{ - Errs: errStructArray, - } - - errs = validate.Struct(tms) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 4) - AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "Name", "required") - - type TestMultiDimensionalStructsPtr2 struct { - Errs [][]*Inner `validate:"gt=0,dive,dive,required"` - } - - var errStructPtr2Array [][]*Inner - - errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) - errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) - errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil}) - - tmsp2 := &TestMultiDimensionalStructsPtr2{ - Errs: errStructPtr2Array, - } - - errs = validate.Struct(tmsp2) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 6) - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required") - - m := map[int]interface{}{0: "ok", 3: "", 4: "ok"} - - errs = validate.Var(m, "len=3,dive,len=2") - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "[3]", "[3]", "[3]", "[3]", "len") - - errs = validate.Var(m, "len=2,dive,required") - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "", "", "", "", "len") - - arr := []interface{}{"ok", "", "ok"} - - errs = validate.Var(arr, "len=3,dive,len=2") - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "[1]", "[1]", "[1]", "[1]", "len") - - errs = validate.Var(arr, "len=2,dive,required") - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "", "", "", "", "len") - - type MyStruct struct { - A, B string - C interface{} - } - - var a MyStruct - - a.A = "value" - a.C = "nu" - - errs = validate.Struct(a) - Equal(t, errs, nil) -} - -func TestMapDiveValidation(t *testing.T) { - - validate := New() - - n := map[int]interface{}{0: nil} - errs := validate.Var(n, "omitempty,required") - Equal(t, errs, nil) - - m := map[int]string{0: "ok", 3: "", 4: "ok"} - - errs = validate.Var(m, "len=3,dive,required") - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "[3]", "[3]", "[3]", "[3]", "required") - - errs = validate.Var(m, "len=2,dive,required") - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "", "", "", "", "len") - - type Inner struct { - Name string `validate:"required"` - } - - type TestMapStruct struct { - Errs map[int]Inner `validate:"gt=0,dive"` - } - - mi := map[int]Inner{0: {"ok"}, 3: {""}, 4: {"ok"}} - - ms := &TestMapStruct{ - Errs: mi, - } - - errs = validate.Struct(ms) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "TestMapStruct.Errs[3].Name", "TestMapStruct.Errs[3].Name", "Name", "Name", "required") - - // for full test coverage - s := fmt.Sprint(errs.Error()) - NotEqual(t, s, "") - - type TestMapTimeStruct struct { - Errs map[int]*time.Time `validate:"gt=0,dive,required"` - } - - t1 := time.Now().UTC() - - mta := map[int]*time.Time{0: &t1, 3: nil, 4: nil} - - mt := &TestMapTimeStruct{ - Errs: mta, - } - - errs = validate.Struct(mt) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 2) - AssertError(t, errs, "TestMapTimeStruct.Errs[3]", "TestMapTimeStruct.Errs[3]", "Errs[3]", "Errs[3]", "required") - AssertError(t, errs, "TestMapTimeStruct.Errs[4]", "TestMapTimeStruct.Errs[4]", "Errs[4]", "Errs[4]", "required") - - type TestMapStructPtr struct { - Errs map[int]*Inner `validate:"gt=0,dive,required"` - } - - mip := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}} - - msp := &TestMapStructPtr{ - Errs: mip, - } - - errs = validate.Struct(msp) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "TestMapStructPtr.Errs[3]", "TestMapStructPtr.Errs[3]", "Errs[3]", "Errs[3]", "required") - - type TestMapStructPtr2 struct { - Errs map[int]*Inner `validate:"gt=0,dive,omitempty,required"` - } - - mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}} - - msp2 := &TestMapStructPtr2{ - Errs: mip2, - } - - errs = validate.Struct(msp2) - Equal(t, errs, nil) - - v2 := New() - v2.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - - if name == "-" { - return "" - } - - return name - }) - - type MapDiveJSONTest struct { - Map map[string]string `validate:"required,gte=1,dive,gte=1" json:"MyName"` - } - - mdjt := &MapDiveJSONTest{ - Map: map[string]string{ - "Key1": "Value1", - "Key2": "", - }, - } - - err := v2.Struct(mdjt) - NotEqual(t, err, nil) - - errs = err.(ValidationErrors) - fe := getError(errs, "MapDiveJSONTest.MyName[Key2]", "MapDiveJSONTest.Map[Key2]") - NotEqual(t, fe, nil) - Equal(t, fe.Tag(), "gte") - Equal(t, fe.ActualTag(), "gte") - Equal(t, fe.Field(), "MyName[Key2]") - Equal(t, fe.StructField(), "Map[Key2]") -} - -func TestArrayDiveValidation(t *testing.T) { - - validate := New() - - arr := []string{"ok", "", "ok"} - - errs := validate.Var(arr, "len=3,dive,required") - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "[1]", "[1]", "[1]", "[1]", "required") - - errs = validate.Var(arr, "len=2,dive,required") - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "", "", "", "", "len") - - type BadDive struct { - Name string `validate:"dive"` - } - - bd := &BadDive{ - Name: "TEST", - } - - PanicMatches(t, func() { _ = validate.Struct(bd) }, "dive error! can't dive on a non slice or map") - - type Test struct { - Errs []string `validate:"gt=0,dive,required"` - } - - test := &Test{ - Errs: []string{"ok", "", "ok"}, - } - - errs = validate.Struct(test) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "Test.Errs[1]", "Test.Errs[1]", "Errs[1]", "Errs[1]", "required") - - test = &Test{ - Errs: []string{"ok", "ok", ""}, - } - - errs = validate.Struct(test) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "Test.Errs[2]", "Test.Errs[2]", "Errs[2]", "Errs[2]", "required") - - type TestMultiDimensional struct { - Errs [][]string `validate:"gt=0,dive,dive,required"` - } - - var errArray [][]string - - errArray = append(errArray, []string{"ok", "", ""}) - errArray = append(errArray, []string{"ok", "", ""}) - - tm := &TestMultiDimensional{ - Errs: errArray, - } - - errs = validate.Struct(tm) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 4) - AssertError(t, errs, "TestMultiDimensional.Errs[0][1]", "TestMultiDimensional.Errs[0][1]", "Errs[0][1]", "Errs[0][1]", "required") - AssertError(t, errs, "TestMultiDimensional.Errs[0][2]", "TestMultiDimensional.Errs[0][2]", "Errs[0][2]", "Errs[0][2]", "required") - AssertError(t, errs, "TestMultiDimensional.Errs[1][1]", "TestMultiDimensional.Errs[1][1]", "Errs[1][1]", "Errs[1][1]", "required") - AssertError(t, errs, "TestMultiDimensional.Errs[1][2]", "TestMultiDimensional.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required") - - type Inner struct { - Name string `validate:"required"` - } - - type TestMultiDimensionalStructs struct { - Errs [][]Inner `validate:"gt=0,dive,dive"` - } - - var errStructArray [][]Inner - - errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}}) - errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}}) - - tms := &TestMultiDimensionalStructs{ - Errs: errStructArray, - } - - errs = validate.Struct(tms) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 4) - AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "Name", "required") - - type TestMultiDimensionalStructsPtr struct { - Errs [][]*Inner `validate:"gt=0,dive,dive"` - } - - var errStructPtrArray [][]*Inner - - errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}}) - errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}}) - errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, nil}) - - tmsp := &TestMultiDimensionalStructsPtr{ - Errs: errStructPtrArray, - } - - errs = validate.Struct(tmsp) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 5) - AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][1].Name", "TestMultiDimensionalStructsPtr.Errs[0][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[2][1].Name", "TestMultiDimensionalStructsPtr.Errs[2][1].Name", "Name", "Name", "required") - - // for full test coverage - s := fmt.Sprint(errs.Error()) - NotEqual(t, s, "") - - type TestMultiDimensionalStructsPtr2 struct { - Errs [][]*Inner `validate:"gt=0,dive,dive,required"` - } - - var errStructPtr2Array [][]*Inner - - errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) - errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) - errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil}) - - tmsp2 := &TestMultiDimensionalStructsPtr2{ - Errs: errStructPtr2Array, - } - - errs = validate.Struct(tmsp2) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 6) - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required") - - type TestMultiDimensionalStructsPtr3 struct { - Errs [][]*Inner `validate:"gt=0,dive,dive,omitempty"` - } - - var errStructPtr3Array [][]*Inner - - errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}}) - errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}}) - errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, nil}) - - tmsp3 := &TestMultiDimensionalStructsPtr3{ - Errs: errStructPtr3Array, - } - - errs = validate.Struct(tmsp3) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 5) - AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][1].Name", "TestMultiDimensionalStructsPtr3.Errs[0][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "Name", "Name", "required") - AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[2][1].Name", "TestMultiDimensionalStructsPtr3.Errs[2][1].Name", "Name", "Name", "required") - - type TestMultiDimensionalTimeTime struct { - Errs [][]*time.Time `validate:"gt=0,dive,dive,required"` - } - - var errTimePtr3Array [][]*time.Time - - t1 := time.Now().UTC() - t2 := time.Now().UTC() - t3 := time.Now().UTC().Add(time.Hour * 24) - - errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, &t3}) - errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, nil}) - errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, nil, nil}) - - tmtp3 := &TestMultiDimensionalTimeTime{ - Errs: errTimePtr3Array, - } - - errs = validate.Struct(tmtp3) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 3) - AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[1][2]", "TestMultiDimensionalTimeTime.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required") - AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][1]", "TestMultiDimensionalTimeTime.Errs[2][1]", "Errs[2][1]", "Errs[2][1]", "required") - AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][2]", "TestMultiDimensionalTimeTime.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required") - - type TestMultiDimensionalTimeTime2 struct { - Errs [][]*time.Time `validate:"gt=0,dive,dive,required"` - } - - var errTimeArray [][]*time.Time - - t1 = time.Now().UTC() - t2 = time.Now().UTC() - t3 = time.Now().UTC().Add(time.Hour * 24) - - errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, &t3}) - errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, nil}) - errTimeArray = append(errTimeArray, []*time.Time{&t1, nil, nil}) - - tmtp := &TestMultiDimensionalTimeTime2{ - Errs: errTimeArray, - } - - errs = validate.Struct(tmtp) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 3) - AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[1][2]", "TestMultiDimensionalTimeTime2.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required") - AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][1]", "TestMultiDimensionalTimeTime2.Errs[2][1]", "Errs[2][1]", "Errs[2][1]", "required") - AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][2]", "TestMultiDimensionalTimeTime2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required") -} - -func TestNilStructPointerValidation(t *testing.T) { - type Inner struct { - Data string - } - - type Outer struct { - Inner *Inner `validate:"omitempty"` - } - - inner := &Inner{ - Data: "test", - } - - outer := &Outer{ - Inner: inner, - } - - validate := New() - errs := validate.Struct(outer) - Equal(t, errs, nil) - - outer = &Outer{ - Inner: nil, - } - - errs = validate.Struct(outer) - Equal(t, errs, nil) - - type Inner2 struct { - Data string - } - - type Outer2 struct { - Inner2 *Inner2 `validate:"required"` - } - - inner2 := &Inner2{ - Data: "test", - } - - outer2 := &Outer2{ - Inner2: inner2, - } - - errs = validate.Struct(outer2) - Equal(t, errs, nil) - - outer2 = &Outer2{ - Inner2: nil, - } - - errs = validate.Struct(outer2) - NotEqual(t, errs, nil) - AssertError(t, errs, "Outer2.Inner2", "Outer2.Inner2", "Inner2", "Inner2", "required") - - type Inner3 struct { - Data string - } - - type Outer3 struct { - Inner3 *Inner3 - } - - inner3 := &Inner3{ - Data: "test", - } - - outer3 := &Outer3{ - Inner3: inner3, - } - - errs = validate.Struct(outer3) - Equal(t, errs, nil) - - type Inner4 struct { - Data string - } - - type Outer4 struct { - Inner4 *Inner4 `validate:"-"` - } - - inner4 := &Inner4{ - Data: "test", - } - - outer4 := &Outer4{ - Inner4: inner4, - } - - errs = validate.Struct(outer4) - Equal(t, errs, nil) -} - -func TestSSNValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"00-90-8787", false}, - {"66690-76", false}, - {"191 60 2869", true}, - {"191-60-2869", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "ssn") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d SSN failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d SSN failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "ssn" { - t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) - } - } - } - } -} - -func TestLongitudeValidation(t *testing.T) { - tests := []struct { - param interface{} - expected bool - }{ - {"", false}, - {"-180.000", true}, - {"180.1", false}, - {"+73.234", true}, - {"+382.3811", false}, - {"23.11111111", true}, - {uint(180), true}, - {float32(-180.0), true}, - {-180, true}, - {180.1, false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "longitude") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d Longitude failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d Longitude failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "longitude" { - t.Fatalf("Index: %d Longitude failed Error: %s", i, errs) - } - } - } - } - - PanicMatches(t, func() { _ = validate.Var(true, "longitude") }, "Bad field type bool") -} - -func TestLatitudeValidation(t *testing.T) { - tests := []struct { - param interface{} - expected bool - }{ - {"", false}, - {"-90.000", true}, - {"+90", true}, - {"47.1231231", true}, - {"+99.9", false}, - {"108", false}, - {uint(90), true}, - {float32(-90.0), true}, - {-90, true}, - {90.1, false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "latitude") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "latitude" { - t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) - } - } - } - } - - PanicMatches(t, func() { _ = validate.Var(true, "latitude") }, "Bad field type bool") -} - -func TestDataURIValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"data:image/png;base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true}, - {"data:text/plain;base64,Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true}, - {"image/gif;base64,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false}, - {"data:image/gif;base64,MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" + - "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" + - "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" + - "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" + - "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" + - "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true}, - {"data:image/png;base64,12345", false}, - {"", false}, - {"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false}, - {"data:image/jpeg;key=value;base64,UEsDBBQAAAAI", true}, - {"data:image/jpeg;key=value,UEsDBBQAAAAI", true}, - {"data:;base64;sdfgsdfgsdfasdfa=s,UEsDBBQAAAAI", true}, - {"data:,UEsDBBQAAAAI", true}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Var(test.param, "datauri") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d DataURI failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d DataURI failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "datauri" { - t.Fatalf("Index: %d DataURI failed Error: %s", i, errs) - } - } - } - } -} - -func TestMultibyteValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", true}, - {"abc", false}, - {"123", false}, - {"<>@;.-=", false}, - {"ひらがな・カタカナ、.漢字", true}, - {"あいうえお foobar", true}, - {"test@example.com", true}, - {"test@example.com", true}, - {"1234abcDExyz", true}, - {"カタカナ", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "multibyte") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "multibyte" { - t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs) - } - } - } - } -} - -func TestPrintableASCIIValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", true}, - {"foobar", false}, - {"xyz098", false}, - {"123456", false}, - {"カタカナ", false}, - {"foobar", true}, - {"0987654321", true}, - {"test@example.com", true}, - {"1234abcDEF", true}, - {"newline\n", false}, - {"\x19test\x7F", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "printascii") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "printascii" { - t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs) - } - } - } - } -} - -func TestASCIIValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", true}, - {"foobar", false}, - {"xyz098", false}, - {"123456", false}, - {"カタカナ", false}, - {"foobar", true}, - {"0987654321", true}, - {"test@example.com", true}, - {"1234abcDEF", true}, - {"", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "ascii") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d ASCII failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d ASCII failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "ascii" { - t.Fatalf("Index: %d ASCII failed Error: %s", i, errs) - } - } - } - } -} - -func TestUUID5Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - - {"", false}, - {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, - {"9c858901-8a57-4791-81fe-4c455b099bc9", false}, - {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, - {"987fbc97-4bed-5078-af07-9141ba07c9f3", true}, - {"987fbc97-4bed-5078-9f07-9141ba07c9f3", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "uuid5") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "uuid5" { - t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs) - } - } - } - } -} - -func TestUUID4Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, - {"a987fbc9-4bed-5078-af07-9141ba07c9f3", false}, - {"934859", false}, - {"57b73598-8764-4ad0-a76a-679bb6640eb1", true}, - {"625e63f3-58f5-40b7-83a1-a72ad31acffb", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "uuid4") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "uuid4" { - t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs) - } - } - } - } -} - -func TestUUID3Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"412452646", false}, - {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, - {"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false}, - {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "uuid3") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "uuid3" { - t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs) - } - } - } - } -} - -func TestUUIDValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, - {"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false}, - {"a987fbc94bed3078cf079141ba07c9f3", false}, - {"934859", false}, - {"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false}, - {"aaaaaaaa-1111-1111-aaag-111111111111", false}, - {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "uuid") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "uuid" { - t.Fatalf("Index: %d UUID failed Error: %s", i, errs) - } - } - } - } -} - -func TestUUID5RFC4122Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - - {"", false}, - {"xxxa987Fbc9-4bed-3078-cf07-9141ba07c9f3", false}, - {"9c858901-8a57-4791-81Fe-4c455b099bc9", false}, - {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3", false}, - {"987Fbc97-4bed-5078-af07-9141ba07c9f3", true}, - {"987Fbc97-4bed-5078-9f07-9141ba07c9f3", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "uuid5_rfc4122") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "uuid5_rfc4122" { - t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs) - } - } - } - } -} - -func TestUUID4RFC4122Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9F3", false}, - {"a987fbc9-4bed-5078-af07-9141ba07c9F3", false}, - {"934859", false}, - {"57b73598-8764-4ad0-a76A-679bb6640eb1", true}, - {"625e63f3-58f5-40b7-83a1-a72ad31acFfb", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "uuid4_rfc4122") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "uuid4_rfc4122" { - t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs) - } - } - } - } -} - -func TestUUID3RFC4122Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"412452646", false}, - {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9F3", false}, - {"a987fbc9-4bed-4078-8f07-9141ba07c9F3", false}, - {"a987fbc9-4bed-3078-cf07-9141ba07c9F3", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "uuid3_rfc4122") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "uuid3_rfc4122" { - t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs) - } - } - } - } -} - -func TestUUIDRFC4122Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"xxxa987Fbc9-4bed-3078-cf07-9141ba07c9f3", false}, - {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false}, - {"a987Fbc94bed3078cf079141ba07c9f3", false}, - {"934859", false}, - {"987fbc9-4bed-3078-cf07a-9141ba07c9F3", false}, - {"aaaaaaaa-1111-1111-aaaG-111111111111", false}, - {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "uuid_rfc4122") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "uuid_rfc4122" { - t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs) - } - } - } - } -} - -func TestISBNValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"foo", false}, - {"3836221195", true}, - {"1-61729-085-8", true}, - {"3 423 21412 0", true}, - {"3 401 01319 X", true}, - {"9784873113685", true}, - {"978-4-87311-368-5", true}, - {"978 3401013190", true}, - {"978-3-8362-2119-1", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "isbn") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d ISBN failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d ISBN failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "isbn" { - t.Fatalf("Index: %d ISBN failed Error: %s", i, errs) - } - } - } - } -} - -func TestISBN13Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"foo", false}, - {"3-8362-2119-5", false}, - {"01234567890ab", false}, - {"978 3 8362 2119 0", false}, - {"9784873113685", true}, - {"978-4-87311-368-5", true}, - {"978 3401013190", true}, - {"978-3-8362-2119-1", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "isbn13") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "isbn13" { - t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs) - } - } - } - } -} - -func TestISBN10Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"foo", false}, - {"3423214121", false}, - {"978-3836221191", false}, - {"3-423-21412-1", false}, - {"3 423 21412 1", false}, - {"3836221195", true}, - {"1-61729-085-8", true}, - {"3 423 21412 0", true}, - {"3 401 01319 X", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "isbn10") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "isbn10" { - t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs) - } - } - } - } -} - -func TestExcludesRuneValidation(t *testing.T) { - - tests := []struct { - Value string `validate:"excludesrune=☻"` - Tag string - ExpectedNil bool - }{ - {Value: "a☺b☻c☹d", Tag: "excludesrune=☻", ExpectedNil: false}, - {Value: "abcd", Tag: "excludesrune=☻", ExpectedNil: true}, - } - - validate := New() - - for i, s := range tests { - errs := validate.Var(s.Value, s.Tag) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - - errs = validate.Struct(s) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - } -} - -func TestExcludesAllValidation(t *testing.T) { - - tests := []struct { - Value string `validate:"excludesall=@!{}[]"` - Tag string - ExpectedNil bool - }{ - {Value: "abcd@!jfk", Tag: "excludesall=@!{}[]", ExpectedNil: false}, - {Value: "abcdefg", Tag: "excludesall=@!{}[]", ExpectedNil: true}, - } - - validate := New() - - for i, s := range tests { - errs := validate.Var(s.Value, s.Tag) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - - errs = validate.Struct(s) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - } - - username := "joeybloggs " - - errs := validate.Var(username, "excludesall=@ ") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "excludesall") - - excluded := "," - - errs = validate.Var(excluded, "excludesall=!@#$%^&*()_+.0x2C?") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "excludesall") - - excluded = "=" - - errs = validate.Var(excluded, "excludesall=!@#$%^&*()_+.0x2C=?") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "excludesall") -} - -func TestExcludesValidation(t *testing.T) { - - tests := []struct { - Value string `validate:"excludes=@"` - Tag string - ExpectedNil bool - }{ - {Value: "abcd@!jfk", Tag: "excludes=@", ExpectedNil: false}, - {Value: "abcdq!jfk", Tag: "excludes=@", ExpectedNil: true}, - } - - validate := New() - - for i, s := range tests { - errs := validate.Var(s.Value, s.Tag) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - - errs = validate.Struct(s) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - } -} - -func TestContainsRuneValidation(t *testing.T) { - - tests := []struct { - Value string `validate:"containsrune=☻"` - Tag string - ExpectedNil bool - }{ - {Value: "a☺b☻c☹d", Tag: "containsrune=☻", ExpectedNil: true}, - {Value: "abcd", Tag: "containsrune=☻", ExpectedNil: false}, - } - - validate := New() - - for i, s := range tests { - errs := validate.Var(s.Value, s.Tag) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - - errs = validate.Struct(s) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - } -} - -func TestContainsAnyValidation(t *testing.T) { - - tests := []struct { - Value string `validate:"containsany=@!{}[]"` - Tag string - ExpectedNil bool - }{ - {Value: "abcd@!jfk", Tag: "containsany=@!{}[]", ExpectedNil: true}, - {Value: "abcdefg", Tag: "containsany=@!{}[]", ExpectedNil: false}, - } - - validate := New() - - for i, s := range tests { - errs := validate.Var(s.Value, s.Tag) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - - errs = validate.Struct(s) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - } -} - -func TestContainsValidation(t *testing.T) { - - tests := []struct { - Value string `validate:"contains=@"` - Tag string - ExpectedNil bool - }{ - {Value: "abcd@!jfk", Tag: "contains=@", ExpectedNil: true}, - {Value: "abcdq!jfk", Tag: "contains=@", ExpectedNil: false}, - } - - validate := New() - - for i, s := range tests { - errs := validate.Var(s.Value, s.Tag) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - - errs = validate.Struct(s) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - } -} - -func TestIsNeFieldValidation(t *testing.T) { - var errs error - validate := New() - - var j uint64 - var k float64 - s := "abcd" - i := 1 - j = 1 - k = 1.543 - arr := []string{"test"} - now := time.Now().UTC() - - var j2 uint64 - var k2 float64 - s2 := "abcdef" - i2 := 3 - j2 = 2 - k2 = 1.5434456 - arr2 := []string{"test", "test2"} - arr3 := []string{"test"} - now2 := now - - errs = validate.VarWithValue(s, s2, "nefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(i2, i, "nefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(j2, j, "nefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(k2, k, "nefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(arr2, arr, "nefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(now2, now, "nefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "nefield") - - errs = validate.VarWithValue(arr3, arr, "nefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "nefield") - - type Test struct { - Start *time.Time `validate:"nefield=End"` - End *time.Time - } - - sv := &Test{ - Start: &now, - End: &now, - } - - errs = validate.Struct(sv) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.Start", "Test.Start", "Start", "Start", "nefield") - - now3 := time.Now().UTC() - - sv = &Test{ - Start: &now, - End: &now3, - } - - errs = validate.Struct(sv) - Equal(t, errs, nil) - - errs = validate.VarWithValue(nil, 1, "nefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "nefield") - - errs = validate.VarWithValue(sv, now, "nefield") - Equal(t, errs, nil) - - type Test2 struct { - Start *time.Time `validate:"nefield=NonExistantField"` - End *time.Time - } - - sv2 := &Test2{ - Start: &now, - End: &now, - } - - errs = validate.Struct(sv2) - Equal(t, errs, nil) - - type Other struct { - Value string - } - - type Test3 struct { - Value Other - Time time.Time `validate:"nefield=Value"` - } - - tst := Test3{ - Value: Other{Value: "StringVal"}, - Time: now, - } - - errs = validate.Struct(tst) - Equal(t, errs, nil) - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "nefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "nefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour, "nefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "nefield") - - errs = validate.VarWithValue(time.Duration(0), time.Duration(0), "omitempty,nefield") - Equal(t, errs, nil) - - // -- Validations for a struct with time.Duration type fields. - - type TimeDurationTest struct { - First time.Duration `validate:"nefield=Second"` - Second time.Duration - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "nefield") - - type TimeDurationOmitemptyTest struct { - First time.Duration `validate:"omitempty,nefield=Second"` - Second time.Duration - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestIsNeValidation(t *testing.T) { - var errs error - validate := New() - - var j uint64 - var k float64 - s := "abcdef" - i := 3 - j = 2 - k = 1.5434 - arr := []string{"test"} - now := time.Now().UTC() - - errs = validate.Var(s, "ne=abcd") - Equal(t, errs, nil) - - errs = validate.Var(i, "ne=1") - Equal(t, errs, nil) - - errs = validate.Var(j, "ne=1") - Equal(t, errs, nil) - - errs = validate.Var(k, "ne=1.543") - Equal(t, errs, nil) - - errs = validate.Var(arr, "ne=2") - Equal(t, errs, nil) - - errs = validate.Var(arr, "ne=1") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ne") - - PanicMatches(t, func() { _ = validate.Var(now, "ne=now") }, "Bad field type time.Time") - - // Tests for time.Duration type. - - // -- Validations for a variable of time.Duration type. - - errs = validate.Var(time.Hour-time.Minute, "ne=1h") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour+time.Minute, "ne=1h") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour, "ne=1h") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ne") - - errs = validate.Var(time.Duration(0), "omitempty,ne=0") - Equal(t, errs, nil) - - // -- Validations for a struct with a time.Duration type field. - - type TimeDurationTest struct { - Duration time.Duration `validate:"ne=1h"` - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ne") - - type TimeDurationOmitemptyTest struct { - Duration time.Duration `validate:"omitempty,ne=0"` - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestIsEqFieldValidation(t *testing.T) { - var errs error - validate := New() - - var j uint64 - var k float64 - s := "abcd" - i := 1 - j = 1 - k = 1.543 - arr := []string{"test"} - now := time.Now().UTC() - - var j2 uint64 - var k2 float64 - s2 := "abcd" - i2 := 1 - j2 = 1 - k2 = 1.543 - arr2 := []string{"test"} - arr3 := []string{"test", "test2"} - now2 := now - - errs = validate.VarWithValue(s, s2, "eqfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(i2, i, "eqfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(j2, j, "eqfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(k2, k, "eqfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(arr2, arr, "eqfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(now2, now, "eqfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(arr3, arr, "eqfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eqfield") - - type Test struct { - Start *time.Time `validate:"eqfield=End"` - End *time.Time - } - - sv := &Test{ - Start: &now, - End: &now, - } - - errs = validate.Struct(sv) - Equal(t, errs, nil) - - now3 := time.Now().UTC() - - sv = &Test{ - Start: &now, - End: &now3, - } - - errs = validate.Struct(sv) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.Start", "Test.Start", "Start", "Start", "eqfield") - - errs = validate.VarWithValue(nil, 1, "eqfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eqfield") - - channel := make(chan string) - errs = validate.VarWithValue(5, channel, "eqfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eqfield") - - errs = validate.VarWithValue(5, now, "eqfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eqfield") - - type Test2 struct { - Start *time.Time `validate:"eqfield=NonExistantField"` - End *time.Time - } - - sv2 := &Test2{ - Start: &now, - End: &now, - } - - errs = validate.Struct(sv2) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test2.Start", "Test2.Start", "Start", "Start", "eqfield") - - type Inner struct { - Name string - } - - type TStruct struct { - Inner *Inner - CreatedAt *time.Time `validate:"eqfield=Inner"` - } - - inner := &Inner{ - Name: "NAME", - } - - test := &TStruct{ - Inner: inner, - CreatedAt: &now, - } - - errs = validate.Struct(test) - NotEqual(t, errs, nil) - AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqfield") - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour, "eqfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "eqfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eqfield") - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "eqfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eqfield") - - errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,eqfield") - Equal(t, errs, nil) - - // -- Validations for a struct with time.Duration type fields. - - type TimeDurationTest struct { - First time.Duration `validate:"eqfield=Second"` - Second time.Duration - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "eqfield") - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "eqfield") - - type TimeDurationOmitemptyTest struct { - First time.Duration `validate:"omitempty,eqfield=Second"` - Second time.Duration - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestIsEqValidation(t *testing.T) { - var errs error - validate := New() - - var j uint64 - var k float64 - s := "abcd" - i := 1 - j = 1 - k = 1.543 - arr := []string{"test"} - now := time.Now().UTC() - - errs = validate.Var(s, "eq=abcd") - Equal(t, errs, nil) - - errs = validate.Var(i, "eq=1") - Equal(t, errs, nil) - - errs = validate.Var(j, "eq=1") - Equal(t, errs, nil) - - errs = validate.Var(k, "eq=1.543") - Equal(t, errs, nil) - - errs = validate.Var(arr, "eq=1") - Equal(t, errs, nil) - - errs = validate.Var(arr, "eq=2") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eq") - - PanicMatches(t, func() { _ = validate.Var(now, "eq=now") }, "Bad field type time.Time") - - // Tests for time.Duration type. - - // -- Validations for a variable of time.Duration type. - - errs = validate.Var(time.Hour, "eq=1h") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour-time.Minute, "eq=1h") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eq") - - errs = validate.Var(time.Hour+time.Minute, "eq=1h") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "eq") - - errs = validate.Var(time.Duration(0), "omitempty,eq=1h") - Equal(t, errs, nil) - - // -- Validations for a struct with a time.Duration type field. - - type TimeDurationTest struct { - Duration time.Duration `validate:"eq=1h"` - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eq") - - timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eq") - - type TimeDurationOmitemptyTest struct { - Duration time.Duration `validate:"omitempty,eq=1h"` - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestOneOfValidation(t *testing.T) { - validate := New() - - passSpecs := []struct { - f interface{} - t string - }{ - {f: "red", t: "oneof=red green"}, - {f: "green", t: "oneof=red green"}, - {f: "red green", t: "oneof='red green' blue"}, - {f: "blue", t: "oneof='red green' blue"}, - {f: 5, t: "oneof=5 6"}, - {f: 6, t: "oneof=5 6"}, - {f: int8(6), t: "oneof=5 6"}, - {f: int16(6), t: "oneof=5 6"}, - {f: int32(6), t: "oneof=5 6"}, - {f: int64(6), t: "oneof=5 6"}, - {f: uint(6), t: "oneof=5 6"}, - {f: uint8(6), t: "oneof=5 6"}, - {f: uint16(6), t: "oneof=5 6"}, - {f: uint32(6), t: "oneof=5 6"}, - {f: uint64(6), t: "oneof=5 6"}, - } - - for _, spec := range passSpecs { - t.Logf("%#v", spec) - errs := validate.Var(spec.f, spec.t) - Equal(t, errs, nil) - } - - failSpecs := []struct { - f interface{} - t string - }{ - {f: "", t: "oneof=red green"}, - {f: "yellow", t: "oneof=red green"}, - {f: "green", t: "oneof='red green' blue"}, - {f: 5, t: "oneof=red green"}, - {f: 6, t: "oneof=red green"}, - {f: 6, t: "oneof=7"}, - {f: uint(6), t: "oneof=7"}, - {f: int8(5), t: "oneof=red green"}, - {f: int16(5), t: "oneof=red green"}, - {f: int32(5), t: "oneof=red green"}, - {f: int64(5), t: "oneof=red green"}, - {f: uint(5), t: "oneof=red green"}, - {f: uint8(5), t: "oneof=red green"}, - {f: uint16(5), t: "oneof=red green"}, - {f: uint32(5), t: "oneof=red green"}, - {f: uint64(5), t: "oneof=red green"}, - } - - for _, spec := range failSpecs { - t.Logf("%#v", spec) - errs := validate.Var(spec.f, spec.t) - AssertError(t, errs, "", "", "", "", "oneof") - } - - PanicMatches(t, func() { - _ = validate.Var(3.14, "oneof=red green") - }, "Bad field type float64") -} - -func TestBase64Validation(t *testing.T) { - - validate := New() - - s := "dW5pY29ybg==" - - errs := validate.Var(s, "base64") - Equal(t, errs, nil) - - s = "dGhpIGlzIGEgdGVzdCBiYXNlNjQ=" - errs = validate.Var(s, "base64") - Equal(t, errs, nil) - - s = "" - errs = validate.Var(s, "base64") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "base64") - - s = "dW5pY29ybg== foo bar" - errs = validate.Var(s, "base64") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "base64") -} - -func TestBase64URLValidation(t *testing.T) { - validate := New() - - testCases := []struct { - decoded, encoded string - success bool - }{ - // empty string, although a valid base64 string, should fail - {"", "", false}, - // invalid length - {"", "a", false}, - // base64 with padding - {"f", "Zg==", true}, - {"fo", "Zm8=", true}, - // base64 without padding - {"foo", "Zm9v", true}, - {"", "Zg", false}, - {"", "Zm8", false}, - // base64 URL safe encoding with invalid, special characters '+' and '/' - {"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l+", false}, - {"\x14\xfb\x9c\x03\xf9\x73", "FPucA/lz", false}, - // base64 URL safe encoding with valid, special characters '-' and '_' - {"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l-", true}, - {"\x14\xfb\x9c\x03\xf9\x73", "FPucA_lz", true}, - // non base64 characters - {"", "@mc=", false}, - {"", "Zm 9", false}, - } - for _, tc := range testCases { - err := validate.Var(tc.encoded, "base64url") - if tc.success { - Equal(t, err, nil) - // make sure encoded value is decoded back to the expected value - d, innerErr := base64.URLEncoding.DecodeString(tc.encoded) - Equal(t, innerErr, nil) - Equal(t, tc.decoded, string(d)) - } else { - NotEqual(t, err, nil) - if len(tc.encoded) > 0 { - // make sure that indeed the encoded value was faulty - _, err := base64.URLEncoding.DecodeString(tc.encoded) - NotEqual(t, err, nil) - } - } - } -} - -func TestFileValidation(t *testing.T) { - validate := New() - - tests := []struct { - title string - param string - expected bool - }{ - {"empty path", "", false}, - {"regular file", filepath.Join("testdata", "a.go"), true}, - {"missing file", filepath.Join("testdata", "no.go"), false}, - {"directory, not a file", "testdata", false}, - } - - for _, test := range tests { - errs := validate.Var(test.param, "file") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) - } - } - } - - PanicMatches(t, func() { - _ = validate.Var(6, "file") - }, "Bad field type int") -} - -func TestEthereumAddressValidation(t *testing.T) { - - validate := New() - - tests := []struct { - param string - expected bool - }{ - // All caps. - {"0x52908400098527886E0F7030069857D2E4169EE7", true}, - {"0x8617E340B3D01FA5F11F306F4090FD50E238070D", true}, - - // All lower. - {"0xde709f2102306220921060314715629080e2fb77", true}, - {"0x27b1fdb04752bbc536007a920d24acb045561c26", true}, - {"0x123f681646d4a755815f9cb19e1acc8565a0c2ac", true}, - - // Mixed case: runs checksum validation. - {"0x02F9AE5f22EA3fA88F05780B30385bECFacbf130", true}, - {"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", true}, - {"0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", true}, - {"0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", true}, - {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", true}, - {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDB", false}, // Invalid checksum. - - // Other. - {"", false}, - {"D1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", false}, // Missing "0x" prefix. - {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDbc", false}, // More than 40 hex digits. - {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aD", false}, // Less than 40 hex digits. - {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDw", false}, // Invalid hex digit "w". - } - - for i, test := range tests { - - errs := validate.Var(test.param, "eth_addr") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d eth_addr failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d eth_addr failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "eth_addr" { - t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) - } - } - } - } -} - -func TestBitcoinAddressValidation(t *testing.T) { - - validate := New() - - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"x", false}, - {"0x02F9AE5f22EA3fA88F05780B30385bEC", false}, - {"1A1zP1ePQGefi2DMPTifTL5SLmv7DivfNa", false}, - {"1P9RQEr2XeE3PEb44ZE35sfZRRW1JH8Uqx", false}, - {"3P14159I73E4gFr7JterCCQh9QjiTjiZrG", false}, - {"3P141597f3E4gFr7JterCCQh9QjiTjiZrG", false}, - {"37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y", false}, - {"dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv", false}, - {"MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S", false}, - {"rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf", false}, - {"4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq", false}, - {"7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb", false}, - {"17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs", false}, - {"KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3", false}, - {"7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th", false}, - {"cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va", false}, - {"gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk", false}, - {"emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs", false}, - {"7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo", false}, - {"1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso", false}, - {"31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq", false}, - {"DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN", false}, - {"2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i", false}, - {"7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos", false}, - {"1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu", false}, - {"2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb", false}, - {"8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ", false}, - {"163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ", false}, - {"2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu", false}, - {"461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU", false}, - {"2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs", false}, - {"cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn", false}, - {"gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj", false}, - {"nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny", false}, - {"L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc", false}, - {"7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ ", false}, - {"2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP", false}, - {"dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw", false}, - {"HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX", false}, - {"4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB", false}, - {"31uEbMgunupShBVTewXjtqbBv5MndwfXhb", false}, - {"175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W", false}, - {"Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ", false}, - {"Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs", false}, - {"6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ", false}, - {"giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4", false}, - {"cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK", false}, - {"37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig", false}, - {"EsYbG4tWWWY45G31nox838qNdzksbPySWc", false}, - {"nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT", false}, - {"cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx", false}, - {"1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde", false}, - {"2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU", false}, - {"ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf", false}, - {"Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd", false}, - {"2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED", false}, - {"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", true}, - {"1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ", true}, - {"1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv", true}, - {"1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu", true}, - {"1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4", true}, - {"19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r", true}, - {"13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE", true}, - {"1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2", true}, - {"3P14159f73E4gFr7JterCCQh9QjiTjiZrG", true}, - {"3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou", true}, - {"3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy", true}, - {"3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks", true}, - {"33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk", true}, - {"3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y", true}, - {"37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3", true}, - {"3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G", true}, - {"12KYrjTdVGjFMtaxERSk3gphreJ5US8aUP", true}, - {"12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y", true}, - {"1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs", true}, - {"1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez", true}, - {"116CGDLddrZhMrTwhCVJXtXQpxygTT1kHd", true}, - {"3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt", true}, - } - - for i, test := range tests { - - errs := validate.Var(test.param, "btc_addr") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d btc_addr failed with Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d btc_addr failed with Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "btc_addr" { - t.Fatalf("Index: %d Latitude failed with Error: %s", i, errs) - } - } - } - } -} - -func TestBitcoinBech32AddressValidation(t *testing.T) { - - validate := New() - - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"bc1rw5uspcuh", false}, - {"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", false}, - {"BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2", false}, - {"qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty", false}, - {"bc1rw5uspcuh", false}, - {"bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90", false}, - {"BC1QW508d6QEJxTDG4y5R3ZArVARY0C5XW7KV8F3T4", false}, - {"BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P", false}, - {"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", false}, - {"bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90", false}, - {"bc1pw508d6qejxtdg4y5r3zarqfsj6c3", false}, - {"bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du", false}, - {"bc1gmk9yu", false}, - {"bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv", false}, - {"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", true}, - {"bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx", true}, - {"bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3", true}, - {"BC1SW50QA3JX3S", true}, - {"bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", true}, - } - - for i, test := range tests { - - errs := validate.Var(test.param, "btc_addr_bech32") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d btc_addr_bech32 failed with Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d btc_addr_bech32 failed with Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "btc_addr_bech32" { - t.Fatalf("Index: %d Latitude failed with Error: %s", i, errs) - } - } - } - } -} - -func TestNoStructLevelValidation(t *testing.T) { - - type Inner struct { - Test string `validate:"len=5"` - } - - type Outer struct { - InnerStruct *Inner `validate:"required,nostructlevel"` - } - - outer := &Outer{ - InnerStruct: nil, - } - - validate := New() - - errs := validate.Struct(outer) - NotEqual(t, errs, nil) - AssertError(t, errs, "Outer.InnerStruct", "Outer.InnerStruct", "InnerStruct", "InnerStruct", "required") - - inner := &Inner{ - Test: "1234", - } - - outer = &Outer{ - InnerStruct: inner, - } - - errs = validate.Struct(outer) - Equal(t, errs, nil) -} - -func TestStructOnlyValidation(t *testing.T) { - - type Inner struct { - Test string `validate:"len=5"` - } - - type Outer struct { - InnerStruct *Inner `validate:"required,structonly"` - } - - outer := &Outer{ - InnerStruct: nil, - } - - validate := New() - - errs := validate.Struct(outer) - NotEqual(t, errs, nil) - AssertError(t, errs, "Outer.InnerStruct", "Outer.InnerStruct", "InnerStruct", "InnerStruct", "required") - - inner := &Inner{ - Test: "1234", - } - - outer = &Outer{ - InnerStruct: inner, - } - - errs = validate.Struct(outer) - Equal(t, errs, nil) - - // Address houses a users address information - type Address struct { - Street string `validate:"required"` - City string `validate:"required"` - Planet string `validate:"required"` - Phone string `validate:"required"` - } - - type User struct { - FirstName string `json:"fname"` - LastName string `json:"lname"` - Age uint8 `validate:"gte=0,lte=130"` - Number string `validate:"required,e164"` - Email string `validate:"required,email"` - FavouriteColor string `validate:"hexcolor|rgb|rgba"` - Addresses []*Address `validate:"required"` // a person can have a home and cottage... - Address Address `validate:"structonly"` // a person can have a home and cottage... - } - - address := &Address{ - Street: "Eavesdown Docks", - Planet: "Persphone", - Phone: "none", - City: "Unknown", - } - - user := &User{ - FirstName: "", - LastName: "", - Age: 45, - Number: "+1123456789", - Email: "Badger.Smith@gmail.com", - FavouriteColor: "#000", - Addresses: []*Address{address}, - Address: Address{ - // Street: "Eavesdown Docks", - Planet: "Persphone", - Phone: "none", - City: "Unknown", - }, - } - - errs = validate.Struct(user) - Equal(t, errs, nil) -} - -func TestGtField(t *testing.T) { - var errs error - validate := New() - - type TimeTest struct { - Start *time.Time `validate:"required,gt"` - End *time.Time `validate:"required,gt,gtfield=Start"` - } - - now := time.Now() - start := now.Add(time.Hour * 24) - end := start.Add(time.Hour * 24) - - timeTest := &TimeTest{ - Start: &start, - End: &end, - } - - errs = validate.Struct(timeTest) - Equal(t, errs, nil) - - timeTest = &TimeTest{ - Start: &end, - End: &start, - } - - errs = validate.Struct(timeTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeTest.End", "TimeTest.End", "End", "End", "gtfield") - - errs = validate.VarWithValue(&end, &start, "gtfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(&start, &end, "gtfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtfield") - - errs = validate.VarWithValue(&end, &start, "gtfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(&timeTest, &end, "gtfield") - NotEqual(t, errs, nil) - - errs = validate.VarWithValue("test bigger", "test", "gtfield") - Equal(t, errs, nil) - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour, "gtfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtfield") - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtfield") - - errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtfield") - Equal(t, errs, nil) - - // -- Validations for a struct with time.Duration type fields. - - type TimeDurationTest struct { - First time.Duration `validate:"gtfield=Second"` - Second time.Duration - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtfield") - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtfield") - - type TimeDurationOmitemptyTest struct { - First time.Duration `validate:"omitempty,gtfield=Second"` - Second time.Duration - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) - - // Tests for Ints types. - - type IntTest struct { - Val1 int `validate:"required"` - Val2 int `validate:"required,gtfield=Val1"` - } - - intTest := &IntTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(intTest) - Equal(t, errs, nil) - - intTest = &IntTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(intTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "gtfield") - - errs = validate.VarWithValue(int(5), int(1), "gtfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(int(1), int(5), "gtfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtfield") - - type UIntTest struct { - Val1 uint `validate:"required"` - Val2 uint `validate:"required,gtfield=Val1"` - } - - uIntTest := &UIntTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(uIntTest) - Equal(t, errs, nil) - - uIntTest = &UIntTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(uIntTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "gtfield") - - errs = validate.VarWithValue(uint(5), uint(1), "gtfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(uint(1), uint(5), "gtfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtfield") - - type FloatTest struct { - Val1 float64 `validate:"required"` - Val2 float64 `validate:"required,gtfield=Val1"` - } - - floatTest := &FloatTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(floatTest) - Equal(t, errs, nil) - - floatTest = &FloatTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(floatTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "gtfield") - - errs = validate.VarWithValue(float32(5), float32(1), "gtfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(float32(1), float32(5), "gtfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtfield") - - errs = validate.VarWithValue(nil, 1, "gtfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtfield") - - errs = validate.VarWithValue(5, "T", "gtfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtfield") - - errs = validate.VarWithValue(5, start, "gtfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtfield") - - type TimeTest2 struct { - Start *time.Time `validate:"required"` - End *time.Time `validate:"required,gtfield=NonExistantField"` - } - - timeTest2 := &TimeTest2{ - Start: &start, - End: &end, - } - - errs = validate.Struct(timeTest2) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "gtfield") - - type Other struct { - Value string - } - - type Test struct { - Value Other - Time time.Time `validate:"gtfield=Value"` - } - - tst := Test{ - Value: Other{Value: "StringVal"}, - Time: end, - } - - errs = validate.Struct(tst) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.Time", "Test.Time", "Time", "Time", "gtfield") -} - -func TestLtField(t *testing.T) { - var errs error - validate := New() - - type TimeTest struct { - Start *time.Time `validate:"required,lt,ltfield=End"` - End *time.Time `validate:"required,lt"` - } - - now := time.Now() - start := now.Add(time.Hour * 24 * -1 * 2) - end := start.Add(time.Hour * 24) - - timeTest := &TimeTest{ - Start: &start, - End: &end, - } - - errs = validate.Struct(timeTest) - Equal(t, errs, nil) - - timeTest = &TimeTest{ - Start: &end, - End: &start, - } - - errs = validate.Struct(timeTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeTest.Start", "TimeTest.Start", "Start", "Start", "ltfield") - - errs = validate.VarWithValue(&start, &end, "ltfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(&end, &start, "ltfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltfield") - - errs = validate.VarWithValue(&end, timeTest, "ltfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltfield") - - errs = validate.VarWithValue("tes", "test", "ltfield") - Equal(t, errs, nil) - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour, "ltfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltfield") - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltfield") - - errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltfield") - Equal(t, errs, nil) - - // -- Validations for a struct with time.Duration type fields. - - type TimeDurationTest struct { - First time.Duration `validate:"ltfield=Second"` - Second time.Duration - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltfield") - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltfield") - - type TimeDurationOmitemptyTest struct { - First time.Duration `validate:"omitempty,ltfield=Second"` - Second time.Duration - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), -time.Minute} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) - - // Tests for Ints types. - - type IntTest struct { - Val1 int `validate:"required"` - Val2 int `validate:"required,ltfield=Val1"` - } - - intTest := &IntTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(intTest) - Equal(t, errs, nil) - - intTest = &IntTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(intTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "ltfield") - - errs = validate.VarWithValue(int(1), int(5), "ltfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(int(5), int(1), "ltfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltfield") - - type UIntTest struct { - Val1 uint `validate:"required"` - Val2 uint `validate:"required,ltfield=Val1"` - } - - uIntTest := &UIntTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(uIntTest) - Equal(t, errs, nil) - - uIntTest = &UIntTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(uIntTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "ltfield") - - errs = validate.VarWithValue(uint(1), uint(5), "ltfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(uint(5), uint(1), "ltfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltfield") - - type FloatTest struct { - Val1 float64 `validate:"required"` - Val2 float64 `validate:"required,ltfield=Val1"` - } - - floatTest := &FloatTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(floatTest) - Equal(t, errs, nil) - - floatTest = &FloatTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(floatTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "ltfield") - - errs = validate.VarWithValue(float32(1), float32(5), "ltfield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(float32(5), float32(1), "ltfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltfield") - - errs = validate.VarWithValue(nil, 5, "ltfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltfield") - - errs = validate.VarWithValue(1, "T", "ltfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltfield") - - errs = validate.VarWithValue(1, end, "ltfield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltfield") - - type TimeTest2 struct { - Start *time.Time `validate:"required"` - End *time.Time `validate:"required,ltfield=NonExistantField"` - } - - timeTest2 := &TimeTest2{ - Start: &end, - End: &start, - } - - errs = validate.Struct(timeTest2) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "ltfield") -} - -func TestFieldContains(t *testing.T) { - validate := New() - - type StringTest struct { - Foo string `validate:"fieldcontains=Bar"` - Bar string - } - - stringTest := &StringTest{ - Foo: "foobar", - Bar: "bar", - } - - errs := validate.Struct(stringTest) - Equal(t, errs, nil) - - stringTest = &StringTest{ - Foo: "foo", - Bar: "bar", - } - - errs = validate.Struct(stringTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "StringTest.Foo", "StringTest.Foo", "Foo", "Foo", "fieldcontains") - - errs = validate.VarWithValue("foo", "bar", "fieldcontains") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "fieldcontains") - - errs = validate.VarWithValue("bar", "foobarfoo", "fieldcontains") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "fieldcontains") - - errs = validate.VarWithValue("foobarfoo", "bar", "fieldcontains") - Equal(t, errs, nil) - - type StringTestMissingField struct { - Foo string `validate:"fieldcontains=Bar"` - } - - stringTestMissingField := &StringTestMissingField{ - Foo: "foo", - } - - errs = validate.Struct(stringTestMissingField) - NotEqual(t, errs, nil) - AssertError(t, errs, "StringTestMissingField.Foo", "StringTestMissingField.Foo", "Foo", "Foo", "fieldcontains") -} - -func TestFieldExcludes(t *testing.T) { - validate := New() - - type StringTest struct { - Foo string `validate:"fieldexcludes=Bar"` - Bar string - } - - stringTest := &StringTest{ - Foo: "foobar", - Bar: "bar", - } - - errs := validate.Struct(stringTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "StringTest.Foo", "StringTest.Foo", "Foo", "Foo", "fieldexcludes") - - stringTest = &StringTest{ - Foo: "foo", - Bar: "bar", - } - - errs = validate.Struct(stringTest) - Equal(t, errs, nil) - - errs = validate.VarWithValue("foo", "bar", "fieldexcludes") - Equal(t, errs, nil) - - errs = validate.VarWithValue("bar", "foobarfoo", "fieldexcludes") - Equal(t, errs, nil) - - errs = validate.VarWithValue("foobarfoo", "bar", "fieldexcludes") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "fieldexcludes") - - type StringTestMissingField struct { - Foo string `validate:"fieldexcludes=Bar"` - } - - stringTestMissingField := &StringTestMissingField{ - Foo: "foo", - } - - errs = validate.Struct(stringTestMissingField) - Equal(t, errs, nil) -} - -func TestContainsAndExcludes(t *testing.T) { - validate := New() - - type ImpossibleStringTest struct { - Foo string `validate:"fieldcontains=Bar"` - Bar string `validate:"fieldexcludes=Foo"` - } - - impossibleStringTest := &ImpossibleStringTest{ - Foo: "foo", - Bar: "bar", - } - - errs := validate.Struct(impossibleStringTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "ImpossibleStringTest.Foo", "ImpossibleStringTest.Foo", "Foo", "Foo", "fieldcontains") - - impossibleStringTest = &ImpossibleStringTest{ - Foo: "bar", - Bar: "foo", - } - - errs = validate.Struct(impossibleStringTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "ImpossibleStringTest.Foo", "ImpossibleStringTest.Foo", "Foo", "Foo", "fieldcontains") -} - -func TestLteField(t *testing.T) { - var errs error - validate := New() - - type TimeTest struct { - Start *time.Time `validate:"required,lte,ltefield=End"` - End *time.Time `validate:"required,lte"` - } - - now := time.Now() - start := now.Add(time.Hour * 24 * -1 * 2) - end := start.Add(time.Hour * 24) - - timeTest := &TimeTest{ - Start: &start, - End: &end, - } - - errs = validate.Struct(timeTest) - Equal(t, errs, nil) - - timeTest = &TimeTest{ - Start: &end, - End: &start, - } - - errs = validate.Struct(timeTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeTest.Start", "TimeTest.Start", "Start", "Start", "ltefield") - - errs = validate.VarWithValue(&start, &end, "ltefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(&end, &start, "ltefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltefield") - - errs = validate.VarWithValue(&end, timeTest, "ltefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltefield") - - errs = validate.VarWithValue("tes", "test", "ltefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue("test", "test", "ltefield") - Equal(t, errs, nil) - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour, "ltefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltefield") - - errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltefield") - Equal(t, errs, nil) - - // -- Validations for a struct with time.Duration type fields. - - type TimeDurationTest struct { - First time.Duration `validate:"ltefield=Second"` - Second time.Duration - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltefield") - - type TimeDurationOmitemptyTest struct { - First time.Duration `validate:"omitempty,ltefield=Second"` - Second time.Duration - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), -time.Minute} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) - - // Tests for Ints types. - - type IntTest struct { - Val1 int `validate:"required"` - Val2 int `validate:"required,ltefield=Val1"` - } - - intTest := &IntTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(intTest) - Equal(t, errs, nil) - - intTest = &IntTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(intTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "ltefield") - - errs = validate.VarWithValue(int(1), int(5), "ltefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(int(5), int(1), "ltefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltefield") - - type UIntTest struct { - Val1 uint `validate:"required"` - Val2 uint `validate:"required,ltefield=Val1"` - } - - uIntTest := &UIntTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(uIntTest) - Equal(t, errs, nil) - - uIntTest = &UIntTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(uIntTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "ltefield") - - errs = validate.VarWithValue(uint(1), uint(5), "ltefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(uint(5), uint(1), "ltefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltefield") - - type FloatTest struct { - Val1 float64 `validate:"required"` - Val2 float64 `validate:"required,ltefield=Val1"` - } - - floatTest := &FloatTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(floatTest) - Equal(t, errs, nil) - - floatTest = &FloatTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(floatTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "ltefield") - - errs = validate.VarWithValue(float32(1), float32(5), "ltefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(float32(5), float32(1), "ltefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltefield") - - errs = validate.VarWithValue(nil, 5, "ltefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltefield") - - errs = validate.VarWithValue(1, "T", "ltefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltefield") - - errs = validate.VarWithValue(1, end, "ltefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "ltefield") - - type TimeTest2 struct { - Start *time.Time `validate:"required"` - End *time.Time `validate:"required,ltefield=NonExistantField"` - } - - timeTest2 := &TimeTest2{ - Start: &end, - End: &start, - } - - errs = validate.Struct(timeTest2) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "ltefield") -} - -func TestGteField(t *testing.T) { - var errs error - validate := New() - - type TimeTest struct { - Start *time.Time `validate:"required,gte"` - End *time.Time `validate:"required,gte,gtefield=Start"` - } - - now := time.Now() - start := now.Add(time.Hour * 24) - end := start.Add(time.Hour * 24) - - timeTest := &TimeTest{ - Start: &start, - End: &end, - } - - errs = validate.Struct(timeTest) - Equal(t, errs, nil) - - timeTest = &TimeTest{ - Start: &end, - End: &start, - } - - errs = validate.Struct(timeTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeTest.End", "TimeTest.End", "End", "End", "gtefield") - - errs = validate.VarWithValue(&end, &start, "gtefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(&start, &end, "gtefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtefield") - - errs = validate.VarWithValue(&start, timeTest, "gtefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtefield") - - errs = validate.VarWithValue("test", "test", "gtefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue("test bigger", "test", "gtefield") - Equal(t, errs, nil) - - // Tests for time.Duration type. - - // -- Validations for variables of time.Duration type. - - errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour, "gtefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtefield") - - errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtefield") - Equal(t, errs, nil) - - // -- Validations for a struct with time.Duration type fields. - - type TimeDurationTest struct { - First time.Duration `validate:"gtefield=Second"` - Second time.Duration - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtefield") - - type TimeDurationOmitemptyTest struct { - First time.Duration `validate:"omitempty,gtefield=Second"` - Second time.Duration - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) - - // Tests for Ints types. - - type IntTest struct { - Val1 int `validate:"required"` - Val2 int `validate:"required,gtefield=Val1"` - } - - intTest := &IntTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(intTest) - Equal(t, errs, nil) - - intTest = &IntTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(intTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "gtefield") - - errs = validate.VarWithValue(int(5), int(1), "gtefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(int(1), int(5), "gtefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtefield") - - type UIntTest struct { - Val1 uint `validate:"required"` - Val2 uint `validate:"required,gtefield=Val1"` - } - - uIntTest := &UIntTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(uIntTest) - Equal(t, errs, nil) - - uIntTest = &UIntTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(uIntTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "gtefield") - - errs = validate.VarWithValue(uint(5), uint(1), "gtefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(uint(1), uint(5), "gtefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtefield") - - type FloatTest struct { - Val1 float64 `validate:"required"` - Val2 float64 `validate:"required,gtefield=Val1"` - } - - floatTest := &FloatTest{ - Val1: 1, - Val2: 5, - } - - errs = validate.Struct(floatTest) - Equal(t, errs, nil) - - floatTest = &FloatTest{ - Val1: 5, - Val2: 1, - } - - errs = validate.Struct(floatTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "gtefield") - - errs = validate.VarWithValue(float32(5), float32(1), "gtefield") - Equal(t, errs, nil) - - errs = validate.VarWithValue(float32(1), float32(5), "gtefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtefield") - - errs = validate.VarWithValue(nil, 1, "gtefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtefield") - - errs = validate.VarWithValue(5, "T", "gtefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtefield") - - errs = validate.VarWithValue(5, start, "gtefield") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gtefield") - - type TimeTest2 struct { - Start *time.Time `validate:"required"` - End *time.Time `validate:"required,gtefield=NonExistantField"` - } - - timeTest2 := &TimeTest2{ - Start: &start, - End: &end, - } - - errs = validate.Struct(timeTest2) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "gtefield") -} - -func TestValidateByTagAndValue(t *testing.T) { - validate := New() - - val := "test" - field := "test" - errs := validate.VarWithValue(val, field, "required") - Equal(t, errs, nil) - - fn := func(fl FieldLevel) bool { - - return fl.Parent().String() == fl.Field().String() - } - - errs = validate.RegisterValidation("isequaltestfunc", fn) - Equal(t, errs, nil) - - errs = validate.VarWithValue(val, field, "isequaltestfunc") - Equal(t, errs, nil) - - val = "unequal" - - errs = validate.VarWithValue(val, field, "isequaltestfunc") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "isequaltestfunc") -} - -func TestAddFunctions(t *testing.T) { - - fn := func(fl FieldLevel) bool { - - return true - } - - fnCtx := func(ctx context.Context, fl FieldLevel) bool { - return true - } - - validate := New() - - errs := validate.RegisterValidation("new", fn) - Equal(t, errs, nil) - - errs = validate.RegisterValidation("", fn) - NotEqual(t, errs, nil) - - errs = validate.RegisterValidation("new", nil) - NotEqual(t, errs, nil) - - errs = validate.RegisterValidation("new", fn) - Equal(t, errs, nil) - - errs = validate.RegisterValidationCtx("new", fnCtx) - Equal(t, errs, nil) - - 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") -} - -func TestChangeTag(t *testing.T) { - - validate := New() - validate.SetTagName("val") - - type Test struct { - Name string `val:"len=4"` - } - s := &Test{ - Name: "TEST", - } - - errs := validate.Struct(s) - Equal(t, errs, nil) - - s.Name = "" - - errs = validate.Struct(s) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.Name", "Test.Name", "Name", "Name", "len") -} - -func TestUnexposedStruct(t *testing.T) { - validate := New() - - type Test struct { - Name string - unexposed struct { - A string `validate:"required"` - } - } - - s := &Test{ - Name: "TEST", - } - Equal(t, s.unexposed.A, "") - - errs := validate.Struct(s) - Equal(t, errs, nil) -} - -func TestBadParams(t *testing.T) { - validate := New() - i := 1 - errs := validate.Var(i, "-") - Equal(t, errs, nil) - - PanicMatches(t, func() { _ = validate.Var(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax") - PanicMatches(t, func() { _ = validate.Var(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax") - - var ui uint = 1 - PanicMatches(t, func() { _ = validate.Var(ui, "len=a") }, "strconv.ParseUint: parsing \"a\": invalid syntax") - - f := 1.23 - PanicMatches(t, func() { _ = validate.Var(f, "len=a") }, "strconv.ParseFloat: parsing \"a\": invalid syntax") -} - -func TestLength(t *testing.T) { - validate := New() - i := true - PanicMatches(t, func() { _ = validate.Var(i, "len") }, "Bad field type bool") -} - -func TestIsGt(t *testing.T) { - var errs error - validate := New() - - myMap := map[string]string{} - errs = validate.Var(myMap, "gt=0") - NotEqual(t, errs, nil) - - f := 1.23 - errs = validate.Var(f, "gt=5") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gt") - - var ui uint = 5 - errs = validate.Var(ui, "gt=10") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gt") - - i := true - PanicMatches(t, func() { _ = validate.Var(i, "gt") }, "Bad field type bool") - - tm := time.Now().UTC() - tm = tm.Add(time.Hour * 24) - - errs = validate.Var(tm, "gt") - Equal(t, errs, nil) - - t2 := time.Now().UTC().Add(-time.Hour) - - errs = validate.Var(t2, "gt") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gt") - - type Test struct { - Now *time.Time `validate:"gt"` - } - s := &Test{ - Now: &tm, - } - - errs = validate.Struct(s) - Equal(t, errs, nil) - - s = &Test{ - Now: &t2, - } - - errs = validate.Struct(s) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gt") - - // Tests for time.Duration type. - - // -- Validations for a variable of time.Duration type. - - errs = validate.Var(time.Hour, "gt=59m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour-time.Minute, "gt=59m") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gt") - - errs = validate.Var(time.Hour-2*time.Minute, "gt=59m") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gt") - - errs = validate.Var(time.Duration(0), "omitempty,gt=59m") - Equal(t, errs, nil) - - // -- Validations for a struct with a time.Duration type field. - - type TimeDurationTest struct { - Duration time.Duration `validate:"gt=59m"` - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gt") - - timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gt") - - type TimeDurationOmitemptyTest struct { - Duration time.Duration `validate:"omitempty,gt=59m"` - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestIsGte(t *testing.T) { - var errs error - validate := New() - - i := true - PanicMatches(t, func() { _ = validate.Var(i, "gte") }, "Bad field type bool") - - t1 := time.Now().UTC() - t1 = t1.Add(time.Hour * 24) - - errs = validate.Var(t1, "gte") - Equal(t, errs, nil) - - t2 := time.Now().UTC().Add(-time.Hour) - - errs = validate.Var(t2, "gte") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gte") - - type Test struct { - Now *time.Time `validate:"gte"` - } - s := &Test{ - Now: &t1, - } - - errs = validate.Struct(s) - Equal(t, errs, nil) - - s = &Test{ - Now: &t2, - } - - errs = validate.Struct(s) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gte") - - // Tests for time.Duration type. - - // -- Validations for a variable of time.Duration type. - - errs = validate.Var(time.Hour, "gte=59m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour-time.Minute, "gte=59m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour-2*time.Minute, "gte=59m") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "gte") - - errs = validate.Var(time.Duration(0), "omitempty,gte=59m") - Equal(t, errs, nil) - - // -- Validations for a struct with a time.Duration type field. - - type TimeDurationTest struct { - Duration time.Duration `validate:"gte=59m"` - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gte") - - type TimeDurationOmitemptyTest struct { - Duration time.Duration `validate:"omitempty,gte=59m"` - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestMinValidation(t *testing.T) { - var errs error - validate := New() - - // Tests for time.Duration type. - - // -- Validations for a variable of time.Duration type. - - errs = validate.Var(time.Hour, "min=59m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour-time.Minute, "min=59m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour-2*time.Minute, "min=59m") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "min") - - errs = validate.Var(time.Duration(0), "omitempty,min=59m") - Equal(t, errs, nil) - - // -- Validations for a struct with a time.Duration type field. - - type TimeDurationTest struct { - Duration time.Duration `validate:"min=59m"` - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "min") - - type TimeDurationOmitemptyTest struct { - Duration time.Duration `validate:"omitempty,min=59m"` - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestMaxValidation(t *testing.T) { - var errs error - validate := New() - - // Tests for time.Duration type. - - // -- Validations for a variable of time.Duration type. - - errs = validate.Var(time.Hour, "max=1h1m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour+time.Minute, "max=1h1m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour+2*time.Minute, "max=1h1m") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "max") - - errs = validate.Var(time.Duration(0), "omitempty,max=-1s") - Equal(t, errs, nil) - - // -- Validations for a struct with a time.Duration type field. - - type TimeDurationTest struct { - Duration time.Duration `validate:"max=1h1m"` - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "max") - - type TimeDurationOmitemptyTest struct { - Duration time.Duration `validate:"omitempty,max=-1s"` - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestMinMaxValidation(t *testing.T) { - var errs error - validate := New() - - // Tests for time.Duration type. - - // -- Validations for a variable of time.Duration type. - - errs = validate.Var(time.Hour, "min=59m,max=1h1m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour-time.Minute, "min=59m,max=1h1m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour+time.Minute, "min=59m,max=1h1m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour-2*time.Minute, "min=59m,max=1h1m") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "min") - - errs = validate.Var(time.Hour+2*time.Minute, "min=59m,max=1h1m") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "max") - - errs = validate.Var(time.Duration(0), "omitempty,min=59m,max=1h1m") - Equal(t, errs, nil) - - // -- Validations for a struct with a time.Duration type field. - - type TimeDurationTest struct { - Duration time.Duration `validate:"min=59m,max=1h1m"` - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "min") - - timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "max") - - type TimeDurationOmitemptyTest struct { - Duration time.Duration `validate:"omitempty,min=59m,max=1h1m"` - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestLenValidation(t *testing.T) { - var errs error - validate := New() - - // Tests for time.Duration type. - - // -- Validations for a variable of time.Duration type. - - errs = validate.Var(time.Hour, "len=1h") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour-time.Minute, "len=1h") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "len") - - errs = validate.Var(time.Hour+time.Minute, "len=1h") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "len") - - errs = validate.Var(time.Duration(0), "omitempty,len=1h") - Equal(t, errs, nil) - - // -- Validations for a struct with a time.Duration type field. - - type TimeDurationTest struct { - Duration time.Duration `validate:"len=1h"` - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "len") - - timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "len") - - type TimeDurationOmitemptyTest struct { - Duration time.Duration `validate:"omitempty,len=1h"` - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestIsLt(t *testing.T) { - var errs error - validate := New() - - myMap := map[string]string{} - errs = validate.Var(myMap, "lt=0") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "lt") - - f := 1.23 - errs = validate.Var(f, "lt=0") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "lt") - - var ui uint = 5 - errs = validate.Var(ui, "lt=0") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "lt") - - i := true - PanicMatches(t, func() { _ = validate.Var(i, "lt") }, "Bad field type bool") - - t1 := time.Now().UTC().Add(-time.Hour) - - errs = validate.Var(t1, "lt") - Equal(t, errs, nil) - - t2 := time.Now().UTC() - t2 = t2.Add(time.Hour * 24) - - errs = validate.Var(t2, "lt") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "lt") - - type Test struct { - Now *time.Time `validate:"lt"` - } - - s := &Test{ - Now: &t1, - } - - errs = validate.Struct(s) - Equal(t, errs, nil) - - s = &Test{ - Now: &t2, - } - - errs = validate.Struct(s) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "lt") - - // Tests for time.Duration type. - - // -- Validations for a variable of time.Duration type. - - errs = validate.Var(time.Hour, "lt=1h1m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour+time.Minute, "lt=1h1m") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "lt") - - errs = validate.Var(time.Hour+2*time.Minute, "lt=1h1m") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "lt") - - errs = validate.Var(time.Duration(0), "omitempty,lt=0") - Equal(t, errs, nil) - - // -- Validations for a struct with a time.Duration type field. - - type TimeDurationTest struct { - Duration time.Duration `validate:"lt=1h1m"` - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lt") - - timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lt") - - type TimeDurationOmitemptyTest struct { - Duration time.Duration `validate:"omitempty,lt=0"` - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestIsLte(t *testing.T) { - var errs error - validate := New() - - i := true - PanicMatches(t, func() { _ = validate.Var(i, "lte") }, "Bad field type bool") - - t1 := time.Now().UTC().Add(-time.Hour) - - errs = validate.Var(t1, "lte") - Equal(t, errs, nil) - - t2 := time.Now().UTC() - t2 = t2.Add(time.Hour * 24) - - errs = validate.Var(t2, "lte") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "lte") - - type Test struct { - Now *time.Time `validate:"lte"` - } - - s := &Test{ - Now: &t1, - } - - errs = validate.Struct(s) - Equal(t, errs, nil) - - s = &Test{ - Now: &t2, - } - - errs = validate.Struct(s) - NotEqual(t, errs, nil) - - // Tests for time.Duration type. - - // -- Validations for a variable of time.Duration type. - - errs = validate.Var(time.Hour, "lte=1h1m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour+time.Minute, "lte=1h1m") - Equal(t, errs, nil) - - errs = validate.Var(time.Hour+2*time.Minute, "lte=1h1m") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "lte") - - errs = validate.Var(time.Duration(0), "omitempty,lte=-1s") - Equal(t, errs, nil) - - // -- Validations for a struct with a time.Duration type field. - - type TimeDurationTest struct { - Duration time.Duration `validate:"lte=1h1m"` - } - var timeDurationTest *TimeDurationTest - - timeDurationTest = &TimeDurationTest{time.Hour} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} - errs = validate.Struct(timeDurationTest) - Equal(t, errs, nil) - - timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} - errs = validate.Struct(timeDurationTest) - NotEqual(t, errs, nil) - AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lte") - - type TimeDurationOmitemptyTest struct { - Duration time.Duration `validate:"omitempty,lte=-1s"` - } - - timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} - errs = validate.Struct(timeDurationOmitemptyTest) - Equal(t, errs, nil) -} - -func TestUrnRFC2141(t *testing.T) { - - var tests = []struct { - param string - expected bool - }{ - {"urn:a:b", true}, - {"urn:a::", true}, - {"urn:a:-", true}, - {"URN:simple:simple", true}, - {"urn:urna:simple", true}, - {"urn:burnout:nss", true}, - {"urn:burn:nss", true}, - {"urn:urnurnurn:x", true}, - {"urn:abcdefghilmnopqrstuvzabcdefghilm:x", true}, - {"URN:123:x", true}, - {"URN:abcd-:x", true}, - {"URN:abcd-abcd:x", true}, - {"urn:urnx:urn", true}, - {"urn:ciao:a:b:c", true}, - {"urn:aaa:x:y:", true}, - {"urn:ciao:-", true}, - {"urn:colon:::::nss", true}, - {"urn:ciao:@!=%2C(xyz)+a,b.*@g=$_'", true}, - {"URN:hexes:%25", true}, - {"URN:x:abc%1Dz%2F%3az", true}, - {"URN:foo:a123,456", true}, - {"urn:foo:a123,456", true}, - {"urn:FOO:a123,456", true}, - {"urn:foo:A123,456", true}, - {"urn:foo:a123%2C456", true}, - {"URN:FOO:a123%2c456", true}, - {"URN:FOO:ABC%FFabc123%2c456", true}, - {"URN:FOO:ABC%FFabc123%2C456%9A", true}, - {"urn:ietf:params:scim:schemas:core:2.0:User", true}, - {"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:meta.lastModified", true}, - {"URN:-xxx:x", false}, - {"urn::colon:nss", false}, - {"urn:abcdefghilmnopqrstuvzabcdefghilmn:specificstring", false}, - {"URN:a!?:x", false}, - {"URN:#,:x", false}, - {"urn:urn:NSS", false}, - {"urn:URN:NSS", false}, - {"urn:white space:NSS", false}, - {"urn:concat:no spaces", false}, - {"urn:a:%", false}, - {"urn:", false}, - } - - tag := "urn_rfc2141" - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, tag) - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d URN failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d URN failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != tag { - t.Fatalf("Index: %d URN failed Error: %s", i, errs) - } - } - } - } - - i := 1 - PanicMatches(t, func() { _ = validate.Var(i, tag) }, "Bad field type int") -} - -func TestUrl(t *testing.T) { - - var tests = []struct { - param string - expected bool - }{ - {"http://foo.bar#com", true}, - {"http://foobar.com", true}, - {"https://foobar.com", true}, - {"foobar.com", false}, - {"http://foobar.coffee/", true}, - {"http://foobar.中文网/", true}, - {"http://foobar.org/", true}, - {"http://foobar.org:8080/", true}, - {"ftp://foobar.ru/", true}, - {"http://user:pass@www.foobar.com/", true}, - {"http://127.0.0.1/", true}, - {"http://duckduckgo.com/?q=%2F", true}, - {"http://localhost:3000/", true}, - {"http://foobar.com/?foo=bar#baz=qux", true}, - {"http://foobar.com?foo=bar", true}, - {"http://www.xn--froschgrn-x9a.net/", true}, - {"", false}, - {"xyz://foobar.com", true}, - {"invalid.", false}, - {".com", false}, - {"rtmp://foobar.com", true}, - {"http://www.foo_bar.com/", true}, - {"http://localhost:3000/", true}, - {"http://foobar.com/#baz", true}, - {"http://foobar.com#baz=qux", true}, - {"http://foobar.com/t$-_.+!*\\'(),", true}, - {"http://www.foobar.com/~foobar", true}, - {"http://www.-foobar.com/", true}, - {"http://www.foo---bar.com/", true}, - {"mailto:someone@example.com", true}, - {"irc://irc.server.org/channel", true}, - {"irc://#channel@network", true}, - {"/abs/test/dir", false}, - {"./rel/test/dir", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "url") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d URL failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d URL failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "url" { - t.Fatalf("Index: %d URL failed Error: %s", i, errs) - } - } - } - } - - i := 1 - PanicMatches(t, func() { _ = validate.Var(i, "url") }, "Bad field type int") -} - -func TestUri(t *testing.T) { - - var tests = []struct { - param string - expected bool - }{ - {"http://foo.bar#com", true}, - {"http://foobar.com", true}, - {"https://foobar.com", true}, - {"foobar.com", false}, - {"http://foobar.coffee/", true}, - {"http://foobar.中文网/", true}, - {"http://foobar.org/", true}, - {"http://foobar.org:8080/", true}, - {"ftp://foobar.ru/", true}, - {"http://user:pass@www.foobar.com/", true}, - {"http://127.0.0.1/", true}, - {"http://duckduckgo.com/?q=%2F", true}, - {"http://localhost:3000/", true}, - {"http://foobar.com/?foo=bar#baz=qux", true}, - {"http://foobar.com?foo=bar", true}, - {"http://www.xn--froschgrn-x9a.net/", true}, - {"", false}, - {"xyz://foobar.com", true}, - {"invalid.", false}, - {".com", false}, - {"rtmp://foobar.com", true}, - {"http://www.foo_bar.com/", true}, - {"http://localhost:3000/", true}, - {"http://foobar.com#baz=qux", true}, - {"http://foobar.com/t$-_.+!*\\'(),", true}, - {"http://www.foobar.com/~foobar", true}, - {"http://www.-foobar.com/", true}, - {"http://www.foo---bar.com/", true}, - {"mailto:someone@example.com", true}, - {"irc://irc.server.org/channel", true}, - {"irc://#channel@network", true}, - {"/abs/test/dir", true}, - {"./rel/test/dir", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "uri") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d URI failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d URI failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "uri" { - t.Fatalf("Index: %d URI failed Error: %s", i, errs) - } - } - } - } - - i := 1 - PanicMatches(t, func() { _ = validate.Var(i, "uri") }, "Bad field type int") -} - -func TestOrTag(t *testing.T) { - - validate := New() - - s := "rgba(0,31,255,0.5)" - errs := validate.Var(s, "rgb|rgba") - Equal(t, errs, nil) - - s = "rgba(0,31,255,0.5)" - errs = validate.Var(s, "rgb|rgba|len=18") - Equal(t, errs, nil) - - s = "this ain't right" - errs = validate.Var(s, "rgb|rgba") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgb|rgba") - - s = "this ain't right" - errs = validate.Var(s, "rgb|rgba|len=10") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgb|rgba|len=10") - - s = "this is right" - errs = validate.Var(s, "rgb|rgba|len=13") - Equal(t, errs, nil) - - s = "" - errs = validate.Var(s, "omitempty,rgb|rgba") - Equal(t, errs, nil) - - s = "green" - errs = validate.Var(s, "eq=|eq=blue,rgb|rgba") //should fail on first validation block - NotEqual(t, errs, nil) - ve := errs.(ValidationErrors) - Equal(t, len(ve), 1) - Equal(t, ve[0].Tag(), "eq=|eq=blue") - - s = "this is right, but a blank or isn't" - - PanicMatches(t, func() { _ = validate.Var(s, "rgb||len=13") }, "Invalid validation tag on field ''") - PanicMatches(t, func() { _ = validate.Var(s, "rgb|rgbaa|len=13") }, "Undefined validation function 'rgbaa' on field ''") - - v2 := New() - v2.RegisterTagNameFunc(func(fld reflect.StructField) string { - - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - - if name == "-" { - return "" - } - - return name - }) - - type Colors struct { - Fav string `validate:"rgb|rgba" json:"fc"` - } - - c := Colors{Fav: "this ain't right"} - - err := v2.Struct(c) - NotEqual(t, err, nil) - - errs = err.(ValidationErrors) - fe := getError(errs, "Colors.fc", "Colors.Fav") - NotEqual(t, fe, nil) -} - -func TestHsla(t *testing.T) { - - validate := New() - - s := "hsla(360,100%,100%,1)" - errs := validate.Var(s, "hsla") - Equal(t, errs, nil) - - s = "hsla(360,100%,100%,0.5)" - errs = validate.Var(s, "hsla") - Equal(t, errs, nil) - - s = "hsla(0,0%,0%, 0)" - errs = validate.Var(s, "hsla") - Equal(t, errs, nil) - - s = "hsl(361,100%,50%,1)" - errs = validate.Var(s, "hsla") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hsla") - - s = "hsl(361,100%,50%)" - errs = validate.Var(s, "hsla") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hsla") - - s = "hsla(361,100%,50%)" - errs = validate.Var(s, "hsla") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hsla") - - s = "hsla(360,101%,50%)" - errs = validate.Var(s, "hsla") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hsla") - - s = "hsla(360,100%,101%)" - errs = validate.Var(s, "hsla") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hsla") - - i := 1 - errs = validate.Var(i, "hsla") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hsla") -} - -func TestHsl(t *testing.T) { - - validate := New() - - s := "hsl(360,100%,50%)" - errs := validate.Var(s, "hsl") - Equal(t, errs, nil) - - s = "hsl(0,0%,0%)" - errs = validate.Var(s, "hsl") - Equal(t, errs, nil) - - s = "hsl(361,100%,50%)" - errs = validate.Var(s, "hsl") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hsl") - - s = "hsl(361,101%,50%)" - errs = validate.Var(s, "hsl") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hsl") - - s = "hsl(361,100%,101%)" - errs = validate.Var(s, "hsl") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hsl") - - s = "hsl(-10,100%,100%)" - errs = validate.Var(s, "hsl") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hsl") - - i := 1 - errs = validate.Var(i, "hsl") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hsl") -} - -func TestRgba(t *testing.T) { - - validate := New() - - s := "rgba(0,31,255,0.5)" - errs := validate.Var(s, "rgba") - Equal(t, errs, nil) - - s = "rgba(0,31,255,0.12)" - errs = validate.Var(s, "rgba") - Equal(t, errs, nil) - - s = "rgba(12%,55%,100%,0.12)" - errs = validate.Var(s, "rgba") - Equal(t, errs, nil) - - s = "rgba( 0, 31, 255, 0.5)" - errs = validate.Var(s, "rgba") - Equal(t, errs, nil) - - s = "rgba(12%,55,100%,0.12)" - errs = validate.Var(s, "rgba") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgba") - - s = "rgb(0, 31, 255)" - errs = validate.Var(s, "rgba") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgba") - - s = "rgb(1,349,275,0.5)" - errs = validate.Var(s, "rgba") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgba") - - s = "rgb(01,31,255,0.5)" - errs = validate.Var(s, "rgba") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgba") - - i := 1 - errs = validate.Var(i, "rgba") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgba") -} - -func TestRgb(t *testing.T) { - - validate := New() - - s := "rgb(0,31,255)" - errs := validate.Var(s, "rgb") - Equal(t, errs, nil) - - s = "rgb(0, 31, 255)" - errs = validate.Var(s, "rgb") - Equal(t, errs, nil) - - s = "rgb(10%, 50%, 100%)" - errs = validate.Var(s, "rgb") - Equal(t, errs, nil) - - s = "rgb(10%, 50%, 55)" - errs = validate.Var(s, "rgb") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgb") - - s = "rgb(1,349,275)" - errs = validate.Var(s, "rgb") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgb") - - s = "rgb(01,31,255)" - errs = validate.Var(s, "rgb") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgb") - - s = "rgba(0,31,255)" - errs = validate.Var(s, "rgb") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgb") - - i := 1 - errs = validate.Var(i, "rgb") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "rgb") -} - -func TestEmail(t *testing.T) { - - validate := New() - - s := "test@mail.com" - errs := validate.Var(s, "email") - Equal(t, errs, nil) - - s = "Dörte@Sörensen.example.com" - errs = validate.Var(s, "email") - Equal(t, errs, nil) - - s = "θσερ@εχαμπλε.ψομ" - errs = validate.Var(s, "email") - Equal(t, errs, nil) - - s = "юзер@екзампл.ком" - errs = validate.Var(s, "email") - Equal(t, errs, nil) - - s = "उपयोगकर्ता@उदाहरण.कॉम" - errs = validate.Var(s, "email") - Equal(t, errs, nil) - - s = "用户@例子.广告" - errs = validate.Var(s, "email") - Equal(t, errs, nil) - - s = "mail@domain_with_underscores.org" - errs = validate.Var(s, "email") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "email") - - s = "" - errs = validate.Var(s, "email") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "email") - - s = "test@email" - errs = validate.Var(s, "email") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "email") - - s = "test@email." - errs = validate.Var(s, "email") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "email") - - s = "@email.com" - errs = validate.Var(s, "email") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "email") - - s = `"test test"@email.com` - errs = validate.Var(s, "email") - Equal(t, errs, nil) - - s = `"@email.com` - errs = validate.Var(s, "email") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "email") - - i := true - errs = validate.Var(i, "email") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "email") -} - -func TestHexColor(t *testing.T) { - - validate := New() - - s := "#fff" - errs := validate.Var(s, "hexcolor") - Equal(t, errs, nil) - - s = "#c2c2c2" - errs = validate.Var(s, "hexcolor") - Equal(t, errs, nil) - - s = "fff" - errs = validate.Var(s, "hexcolor") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hexcolor") - - s = "fffFF" - errs = validate.Var(s, "hexcolor") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hexcolor") - - i := true - errs = validate.Var(i, "hexcolor") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hexcolor") -} - -func TestHexadecimal(t *testing.T) { - - validate := New() - - s := "ff0044" - errs := validate.Var(s, "hexadecimal") - Equal(t, errs, nil) - - s = "0xff0044" - errs = validate.Var(s, "hexadecimal") - Equal(t, errs, nil) - - s = "0Xff0044" - errs = validate.Var(s, "hexadecimal") - Equal(t, errs, nil) - - s = "abcdefg" - errs = validate.Var(s, "hexadecimal") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hexadecimal") - - i := true - errs = validate.Var(i, "hexadecimal") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "hexadecimal") -} - -func TestNumber(t *testing.T) { - - validate := New() - - s := "1" - errs := validate.Var(s, "number") - Equal(t, errs, nil) - - s = "+1" - errs = validate.Var(s, "number") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "number") - - s = "-1" - errs = validate.Var(s, "number") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "number") - - s = "1.12" - errs = validate.Var(s, "number") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "number") - - s = "+1.12" - errs = validate.Var(s, "number") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "number") - - s = "-1.12" - errs = validate.Var(s, "number") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "number") - - s = "1." - errs = validate.Var(s, "number") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "number") - - s = "1.o" - errs = validate.Var(s, "number") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "number") - - i := 1 - errs = validate.Var(i, "number") - Equal(t, errs, nil) -} - -func TestNumeric(t *testing.T) { - - validate := New() - - s := "1" - errs := validate.Var(s, "numeric") - Equal(t, errs, nil) - - s = "+1" - errs = validate.Var(s, "numeric") - Equal(t, errs, nil) - - s = "-1" - errs = validate.Var(s, "numeric") - Equal(t, errs, nil) - - s = "1.12" - errs = validate.Var(s, "numeric") - Equal(t, errs, nil) - - s = "+1.12" - errs = validate.Var(s, "numeric") - Equal(t, errs, nil) - - s = "-1.12" - errs = validate.Var(s, "numeric") - Equal(t, errs, nil) - - s = "1." - errs = validate.Var(s, "numeric") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "numeric") - - s = "1.o" - errs = validate.Var(s, "numeric") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "numeric") - - i := 1 - errs = validate.Var(i, "numeric") - Equal(t, errs, nil) -} - -func TestAlphaNumeric(t *testing.T) { - - validate := New() - - s := "abcd123" - errs := validate.Var(s, "alphanum") - Equal(t, errs, nil) - - s = "abc!23" - errs = validate.Var(s, "alphanum") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "alphanum") - - errs = validate.Var(1, "alphanum") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "alphanum") -} - -func TestAlpha(t *testing.T) { - - validate := New() - - s := "abcd" - errs := validate.Var(s, "alpha") - Equal(t, errs, nil) - - s = "abc®" - errs = validate.Var(s, "alpha") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "alpha") - - s = "abc÷" - errs = validate.Var(s, "alpha") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "alpha") - - s = "abc1" - errs = validate.Var(s, "alpha") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "alpha") - - s = "this is a test string" - errs = validate.Var(s, "alpha") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "alpha") - - errs = validate.Var(1, "alpha") - NotEqual(t, errs, nil) - AssertError(t, errs, "", "", "", "", "alpha") - -} - -func TestStructStringValidation(t *testing.T) { - - validate := New() - - tSuccess := &TestString{ - Required: "Required", - Len: "length==10", - Min: "min=1", - Max: "1234567890", - MinMax: "12345", - Lt: "012345678", - Lte: "0123456789", - Gt: "01234567890", - Gte: "0123456789", - OmitEmpty: "", - Sub: &SubTest{ - Test: "1", - }, - SubIgnore: &SubTest{ - Test: "", - }, - Anonymous: struct { - A string `validate:"required"` - }{ - A: "1", - }, - Iface: &Impl{ - F: "123", - }, - } - - errs := validate.Struct(tSuccess) - Equal(t, errs, nil) - - tFail := &TestString{ - Required: "", - Len: "", - Min: "", - Max: "12345678901", - MinMax: "", - Lt: "0123456789", - Lte: "01234567890", - Gt: "1", - Gte: "1", - OmitEmpty: "12345678901", - Sub: &SubTest{ - Test: "", - }, - Anonymous: struct { - A string `validate:"required"` - }{ - A: "", - }, - Iface: &Impl{ - F: "12", - }, - } - - errs = validate.Struct(tFail) - - // Assert Top Level - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 13) - - // Assert Fields - AssertError(t, errs, "TestString.Required", "TestString.Required", "Required", "Required", "required") - AssertError(t, errs, "TestString.Len", "TestString.Len", "Len", "Len", "len") - AssertError(t, errs, "TestString.Min", "TestString.Min", "Min", "Min", "min") - AssertError(t, errs, "TestString.Max", "TestString.Max", "Max", "Max", "max") - AssertError(t, errs, "TestString.MinMax", "TestString.MinMax", "MinMax", "MinMax", "min") - AssertError(t, errs, "TestString.Lt", "TestString.Lt", "Lt", "Lt", "lt") - AssertError(t, errs, "TestString.Lte", "TestString.Lte", "Lte", "Lte", "lte") - AssertError(t, errs, "TestString.Gt", "TestString.Gt", "Gt", "Gt", "gt") - AssertError(t, errs, "TestString.Gte", "TestString.Gte", "Gte", "Gte", "gte") - AssertError(t, errs, "TestString.OmitEmpty", "TestString.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") - - // Nested Struct Field Errs - AssertError(t, errs, "TestString.Anonymous.A", "TestString.Anonymous.A", "A", "A", "required") - AssertError(t, errs, "TestString.Sub.Test", "TestString.Sub.Test", "Test", "Test", "required") - AssertError(t, errs, "TestString.Iface.F", "TestString.Iface.F", "F", "F", "len") -} - -func TestStructInt32Validation(t *testing.T) { - - type TestInt32 struct { - Required int `validate:"required"` - Len int `validate:"len=10"` - Min int `validate:"min=1"` - Max int `validate:"max=10"` - MinMax int `validate:"min=1,max=10"` - Lt int `validate:"lt=10"` - Lte int `validate:"lte=10"` - Gt int `validate:"gt=10"` - Gte int `validate:"gte=10"` - OmitEmpty int `validate:"omitempty,min=1,max=10"` - } - - tSuccess := &TestInt32{ - Required: 1, - Len: 10, - Min: 1, - Max: 10, - MinMax: 5, - Lt: 9, - Lte: 10, - Gt: 11, - Gte: 10, - OmitEmpty: 0, - } - - validate := New() - errs := validate.Struct(tSuccess) - Equal(t, errs, nil) - - tFail := &TestInt32{ - Required: 0, - Len: 11, - Min: -1, - Max: 11, - MinMax: -1, - Lt: 10, - Lte: 11, - Gt: 10, - Gte: 9, - OmitEmpty: 11, - } - - errs = validate.Struct(tFail) - - // Assert Top Level - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 10) - - // Assert Fields - AssertError(t, errs, "TestInt32.Required", "TestInt32.Required", "Required", "Required", "required") - AssertError(t, errs, "TestInt32.Len", "TestInt32.Len", "Len", "Len", "len") - AssertError(t, errs, "TestInt32.Min", "TestInt32.Min", "Min", "Min", "min") - AssertError(t, errs, "TestInt32.Max", "TestInt32.Max", "Max", "Max", "max") - AssertError(t, errs, "TestInt32.MinMax", "TestInt32.MinMax", "MinMax", "MinMax", "min") - AssertError(t, errs, "TestInt32.Lt", "TestInt32.Lt", "Lt", "Lt", "lt") - AssertError(t, errs, "TestInt32.Lte", "TestInt32.Lte", "Lte", "Lte", "lte") - AssertError(t, errs, "TestInt32.Gt", "TestInt32.Gt", "Gt", "Gt", "gt") - AssertError(t, errs, "TestInt32.Gte", "TestInt32.Gte", "Gte", "Gte", "gte") - AssertError(t, errs, "TestInt32.OmitEmpty", "TestInt32.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") -} - -func TestStructUint64Validation(t *testing.T) { - - validate := New() - - tSuccess := &TestUint64{ - Required: 1, - Len: 10, - Min: 1, - Max: 10, - MinMax: 5, - OmitEmpty: 0, - } - - errs := validate.Struct(tSuccess) - Equal(t, errs, nil) - - tFail := &TestUint64{ - Required: 0, - Len: 11, - Min: 0, - Max: 11, - MinMax: 0, - OmitEmpty: 11, - } - - errs = validate.Struct(tFail) - - // Assert Top Level - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 6) - - // Assert Fields - AssertError(t, errs, "TestUint64.Required", "TestUint64.Required", "Required", "Required", "required") - AssertError(t, errs, "TestUint64.Len", "TestUint64.Len", "Len", "Len", "len") - AssertError(t, errs, "TestUint64.Min", "TestUint64.Min", "Min", "Min", "min") - AssertError(t, errs, "TestUint64.Max", "TestUint64.Max", "Max", "Max", "max") - AssertError(t, errs, "TestUint64.MinMax", "TestUint64.MinMax", "MinMax", "MinMax", "min") - AssertError(t, errs, "TestUint64.OmitEmpty", "TestUint64.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") -} - -func TestStructFloat64Validation(t *testing.T) { - - validate := New() - - tSuccess := &TestFloat64{ - Required: 1, - Len: 10, - Min: 1, - Max: 10, - MinMax: 5, - OmitEmpty: 0, - } - - errs := validate.Struct(tSuccess) - Equal(t, errs, nil) - - tFail := &TestFloat64{ - Required: 0, - Len: 11, - Min: 0, - Max: 11, - MinMax: 0, - OmitEmpty: 11, - } - - errs = validate.Struct(tFail) - - // Assert Top Level - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 6) - - // Assert Fields - AssertError(t, errs, "TestFloat64.Required", "TestFloat64.Required", "Required", "Required", "required") - AssertError(t, errs, "TestFloat64.Len", "TestFloat64.Len", "Len", "Len", "len") - AssertError(t, errs, "TestFloat64.Min", "TestFloat64.Min", "Min", "Min", "min") - AssertError(t, errs, "TestFloat64.Max", "TestFloat64.Max", "Max", "Max", "max") - AssertError(t, errs, "TestFloat64.MinMax", "TestFloat64.MinMax", "MinMax", "MinMax", "min") - AssertError(t, errs, "TestFloat64.OmitEmpty", "TestFloat64.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") -} - -func TestStructSliceValidation(t *testing.T) { - - validate := New() - - tSuccess := &TestSlice{ - Required: []int{1}, - Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, - Min: []int{1, 2}, - Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, - MinMax: []int{1, 2, 3, 4, 5}, - OmitEmpty: nil, - } - - errs := validate.Struct(tSuccess) - Equal(t, errs, nil) - - tFail := &TestSlice{ - Required: nil, - Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, - Min: []int{}, - Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, - MinMax: []int{}, - OmitEmpty: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, - } - - errs = validate.Struct(tFail) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 6) - - // Assert Field Errors - AssertError(t, errs, "TestSlice.Required", "TestSlice.Required", "Required", "Required", "required") - AssertError(t, errs, "TestSlice.Len", "TestSlice.Len", "Len", "Len", "len") - AssertError(t, errs, "TestSlice.Min", "TestSlice.Min", "Min", "Min", "min") - AssertError(t, errs, "TestSlice.Max", "TestSlice.Max", "Max", "Max", "max") - AssertError(t, errs, "TestSlice.MinMax", "TestSlice.MinMax", "MinMax", "MinMax", "min") - AssertError(t, errs, "TestSlice.OmitEmpty", "TestSlice.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") - - fe := getError(errs, "TestSlice.Len", "TestSlice.Len") - NotEqual(t, fe, nil) - Equal(t, fe.Field(), "Len") - Equal(t, fe.StructField(), "Len") - Equal(t, fe.Namespace(), "TestSlice.Len") - Equal(t, fe.StructNamespace(), "TestSlice.Len") - Equal(t, fe.Tag(), "len") - Equal(t, fe.ActualTag(), "len") - Equal(t, fe.Param(), "10") - Equal(t, fe.Kind(), reflect.Slice) - Equal(t, fe.Type(), reflect.TypeOf([]int{})) - - _, ok := fe.Value().([]int) - Equal(t, ok, true) - -} - -func TestInvalidStruct(t *testing.T) { - - validate := New() - - s := &SubTest{ - Test: "1", - } - - err := validate.Struct(s.Test) - NotEqual(t, err, nil) - Equal(t, err.Error(), "validator: (nil string)") - - err = validate.Struct(nil) - NotEqual(t, err, nil) - Equal(t, err.Error(), "validator: (nil)") - - err = validate.StructPartial(nil, "SubTest.Test") - NotEqual(t, err, nil) - Equal(t, err.Error(), "validator: (nil)") - - err = validate.StructExcept(nil, "SubTest.Test") - NotEqual(t, err, nil) - Equal(t, err.Error(), "validator: (nil)") -} - -func TestInvalidValidatorFunction(t *testing.T) { - - validate := New() - - s := &SubTest{ - Test: "1", - } - - PanicMatches(t, func() { _ = validate.Var(s.Test, "zzxxBadFunction") }, "Undefined validation function 'zzxxBadFunction' on field ''") -} - -func TestCustomFieldName(t *testing.T) { - - validate := New() - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("schema"), ",", 2)[0] - - if name == "-" { - return "" - } - - return name - }) - - type A struct { - B string `schema:"b" validate:"required"` - C string `schema:"c" validate:"required"` - D []bool `schema:"d" validate:"required"` - E string `schema:"-" validate:"required"` - } - - a := &A{} - - err := validate.Struct(a) - NotEqual(t, err, nil) - - errs := err.(ValidationErrors) - Equal(t, len(errs), 4) - Equal(t, getError(errs, "A.b", "A.B").Field(), "b") - Equal(t, getError(errs, "A.c", "A.C").Field(), "c") - Equal(t, getError(errs, "A.d", "A.D").Field(), "d") - Equal(t, getError(errs, "A.E", "A.E").Field(), "E") - - v2 := New() - err = v2.Struct(a) - NotEqual(t, err, nil) - - errs = err.(ValidationErrors) - Equal(t, len(errs), 4) - Equal(t, getError(errs, "A.B", "A.B").Field(), "B") - Equal(t, getError(errs, "A.C", "A.C").Field(), "C") - Equal(t, getError(errs, "A.D", "A.D").Field(), "D") - Equal(t, getError(errs, "A.E", "A.E").Field(), "E") -} - -func TestMutipleRecursiveExtractStructCache(t *testing.T) { - - validate := New() - - type Recursive struct { - Field *string `validate:"required,len=5,ne=string"` - } - - var test Recursive - - current := reflect.ValueOf(test) - name := "Recursive" - proceed := make(chan struct{}) - - sc := validate.extractStructCache(current, name) - ptr := fmt.Sprintf("%p", sc) - - for i := 0; i < 100; i++ { - - go func() { - <-proceed - sc := validate.extractStructCache(current, name) - Equal(t, ptr, fmt.Sprintf("%p", sc)) - }() - } - - close(proceed) -} - -// Thanks @robbrockbank, see https://github.com/go-playground/validator/issues/249 -func TestPointerAndOmitEmpty(t *testing.T) { - - validate := New() - - type Test struct { - MyInt *int `validate:"omitempty,gte=2,lte=255"` - } - - val1 := 0 - val2 := 256 - - t1 := Test{MyInt: &val1} // This should fail validation on gte because value is 0 - t2 := Test{MyInt: &val2} // This should fail validate on lte because value is 256 - t3 := Test{MyInt: nil} // This should succeed validation because pointer is nil - - errs := validate.Struct(t1) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.MyInt", "Test.MyInt", "MyInt", "MyInt", "gte") - - errs = validate.Struct(t2) - NotEqual(t, errs, nil) - AssertError(t, errs, "Test.MyInt", "Test.MyInt", "MyInt", "MyInt", "lte") - - errs = validate.Struct(t3) - Equal(t, errs, nil) - - type TestIface struct { - MyInt interface{} `validate:"omitempty,gte=2,lte=255"` - } - - ti1 := TestIface{MyInt: &val1} // This should fail validation on gte because value is 0 - ti2 := TestIface{MyInt: &val2} // This should fail validate on lte because value is 256 - ti3 := TestIface{MyInt: nil} // This should succeed validation because pointer is nil - - errs = validate.Struct(ti1) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestIface.MyInt", "TestIface.MyInt", "MyInt", "MyInt", "gte") - - errs = validate.Struct(ti2) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestIface.MyInt", "TestIface.MyInt", "MyInt", "MyInt", "lte") - - errs = validate.Struct(ti3) - Equal(t, errs, nil) -} - -func TestRequired(t *testing.T) { - - validate := New() - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - - if name == "-" { - return "" - } - - return name - }) - - type Test struct { - Value interface{} `validate:"required"` - } - - var test Test - - err := validate.Struct(test) - NotEqual(t, err, nil) - AssertError(t, err.(ValidationErrors), "Test.Value", "Test.Value", "Value", "Value", "required") -} - -func TestBoolEqual(t *testing.T) { - - validate := New() - - type Test struct { - Value bool `validate:"eq=true"` - } - - var test Test - - err := validate.Struct(test) - NotEqual(t, err, nil) - AssertError(t, err.(ValidationErrors), "Test.Value", "Test.Value", "Value", "Value", "eq") - - test.Value = true - err = validate.Struct(test) - Equal(t, err, nil) -} - -func TestTranslations(t *testing.T) { - en := en.New() - uni := ut.New(en, en, fr.New()) - - trans, _ := uni.GetTranslator("en") - fr, _ := uni.GetTranslator("fr") - - validate := New() - err := validate.RegisterTranslation("required", trans, - func(ut ut.Translator) (err error) { - - // using this stype because multiple translation may have to be added for the full translation - if err = ut.Add("required", "{0} is a required field", false); err != nil { - return - } - - return - - }, func(ut ut.Translator, fe FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field()) - if err != nil { - fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError)) - return fe.(*fieldError).Error() - } - - return t - }) - Equal(t, err, nil) - - err = validate.RegisterTranslation("required", fr, - func(ut ut.Translator) (err error) { - - // using this stype because multiple translation may have to be added for the full translation - if err = ut.Add("required", "{0} est un champ obligatoire", false); err != nil { - return - } - - return - - }, func(ut ut.Translator, fe FieldError) string { - - t, transErr := ut.T(fe.Tag(), fe.Field()) - if transErr != nil { - fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError)) - return fe.(*fieldError).Error() - } - - return t - }) - - Equal(t, err, nil) - - type Test struct { - Value interface{} `validate:"required"` - } - - var test Test - - err = validate.Struct(test) - NotEqual(t, err, nil) - - errs := err.(ValidationErrors) - Equal(t, len(errs), 1) - - fe := errs[0] - Equal(t, fe.Tag(), "required") - Equal(t, fe.Namespace(), "Test.Value") - Equal(t, fe.Translate(trans), fmt.Sprintf("%s is a required field", fe.Field())) - Equal(t, fe.Translate(fr), fmt.Sprintf("%s est un champ obligatoire", fe.Field())) - - nl := nl.New() - uni2 := ut.New(nl, nl) - trans2, _ := uni2.GetTranslator("nl") - Equal(t, fe.Translate(trans2), "Key: 'Test.Value' Error:Field validation for 'Value' failed on the 'required' tag") - - terrs := errs.Translate(trans) - Equal(t, len(terrs), 1) - - v, ok := terrs["Test.Value"] - Equal(t, ok, true) - Equal(t, v, fmt.Sprintf("%s is a required field", fe.Field())) - - terrs = errs.Translate(fr) - Equal(t, len(terrs), 1) - - v, ok = terrs["Test.Value"] - Equal(t, ok, true) - Equal(t, v, fmt.Sprintf("%s est un champ obligatoire", fe.Field())) - - type Test2 struct { - Value string `validate:"gt=1"` - } - - var t2 Test2 - - err = validate.Struct(t2) - NotEqual(t, err, nil) - - errs = err.(ValidationErrors) - Equal(t, len(errs), 1) - - fe = errs[0] - Equal(t, fe.Tag(), "gt") - Equal(t, fe.Namespace(), "Test2.Value") - Equal(t, fe.Translate(trans), "Key: 'Test2.Value' Error:Field validation for 'Value' failed on the 'gt' tag") -} - -func TestTranslationErrors(t *testing.T) { - en := en.New() - uni := ut.New(en, en, fr.New()) - - trans, _ := uni.GetTranslator("en") - err := trans.Add("required", "{0} is a required field", false) // using translator outside of validator also - Equal(t, err, nil) - - validate := New() - err = validate.RegisterTranslation("required", trans, - func(ut ut.Translator) (err error) { - - // using this stype because multiple translation may have to be added for the full translation - if err = ut.Add("required", "{0} is a required field", false); err != nil { - return - } - - return - - }, func(ut ut.Translator, fe FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field()) - if err != nil { - fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError)) - return fe.(*fieldError).Error() - } - - return t - }) - - NotEqual(t, err, nil) - Equal(t, err.Error(), "error: conflicting key 'required' rule 'Unknown' with text '{0} is a required field' for locale 'en', value being ignored") -} - -func TestStructFiltered(t *testing.T) { - - p1 := func(ns []byte) bool { - if bytes.HasSuffix(ns, []byte("NoTag")) || bytes.HasSuffix(ns, []byte("Required")) { - return false - } - - return true - } - - p2 := func(ns []byte) bool { - if bytes.HasSuffix(ns, []byte("SubSlice[0].Test")) || - bytes.HasSuffix(ns, []byte("SubSlice[0]")) || - bytes.HasSuffix(ns, []byte("SubSlice")) || - bytes.HasSuffix(ns, []byte("Sub")) || - bytes.HasSuffix(ns, []byte("SubIgnore")) || - bytes.HasSuffix(ns, []byte("Anonymous")) || - bytes.HasSuffix(ns, []byte("Anonymous.A")) { - return false - } - - return true - } - - p3 := func(ns []byte) bool { - return !bytes.HasSuffix(ns, []byte("SubTest.Test")) - } - - // p4 := []string{ - // "A", - // } - - tPartial := &TestPartial{ - NoTag: "NoTag", - Required: "Required", - - SubSlice: []*SubTest{ - { - - Test: "Required", - }, - { - - Test: "Required", - }, - }, - - Sub: &SubTest{ - Test: "1", - }, - SubIgnore: &SubTest{ - Test: "", - }, - Anonymous: struct { - A string `validate:"required"` - ASubSlice []*SubTest `validate:"required,dive"` - SubAnonStruct []struct { - Test string `validate:"required"` - OtherTest string `validate:"required"` - } `validate:"required,dive"` - }{ - A: "1", - ASubSlice: []*SubTest{ - { - Test: "Required", - }, - { - Test: "Required", - }, - }, - - SubAnonStruct: []struct { - Test string `validate:"required"` - OtherTest string `validate:"required"` - }{ - {"Required", "RequiredOther"}, - {"Required", "RequiredOther"}, - }, - }, - } - - validate := New() - - // the following should all return no errors as everything is valid in - // the default state - errs := validate.StructFilteredCtx(context.Background(), tPartial, p1) - Equal(t, errs, nil) - - errs = validate.StructFiltered(tPartial, p2) - Equal(t, errs, nil) - - // this isn't really a robust test, but is ment to illustrate the ANON CASE below - errs = validate.StructFiltered(tPartial.SubSlice[0], p3) - Equal(t, errs, nil) - - // mod tParial for required feild and re-test making sure invalid fields are NOT required: - tPartial.Required = "" - - // inversion and retesting Partial to generate failures: - errs = validate.StructFiltered(tPartial, p1) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required") - - // reset Required field, and set nested struct - tPartial.Required = "Required" - tPartial.Anonymous.A = "" - - // will pass as unset feilds is not going to be tested - errs = validate.StructFiltered(tPartial, p1) - Equal(t, errs, nil) - - // will fail as unset feild is tested - errs = validate.StructFiltered(tPartial, p2) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required") - - // reset nested struct and unset struct in slice - tPartial.Anonymous.A = "Required" - tPartial.SubSlice[0].Test = "" - - // these will pass as unset item is NOT tested - errs = validate.StructFiltered(tPartial, p1) - Equal(t, errs, nil) - - errs = validate.StructFiltered(tPartial, p2) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") - Equal(t, len(errs.(ValidationErrors)), 1) - - // Unset second slice member concurrently to test dive behavior: - tPartial.SubSlice[1].Test = "" - - errs = validate.StructFiltered(tPartial, p1) - Equal(t, errs, nil) - - errs = validate.StructFiltered(tPartial, p2) - NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 1) - AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") - - // reset struct in slice, and unset struct in slice in unset posistion - tPartial.SubSlice[0].Test = "Required" - - // these will pass as the unset item is NOT tested - errs = validate.StructFiltered(tPartial, p1) - Equal(t, errs, nil) - - errs = validate.StructFiltered(tPartial, p2) - Equal(t, errs, nil) - - tPartial.SubSlice[1].Test = "Required" - tPartial.Anonymous.SubAnonStruct[0].Test = "" - - // these will pass as the unset item is NOT tested - errs = validate.StructFiltered(tPartial, p1) - Equal(t, errs, nil) - - errs = validate.StructFiltered(tPartial, p2) - Equal(t, errs, nil) - - dt := time.Now() - err := validate.StructFiltered(&dt, func(ns []byte) bool { return true }) - NotEqual(t, err, nil) - Equal(t, err.Error(), "validator: (nil *time.Time)") -} - -func TestRequiredPtr(t *testing.T) { - - type Test struct { - Bool *bool `validate:"required"` - } - - validate := New() - - f := false - - test := Test{ - Bool: &f, - } - - err := validate.Struct(test) - Equal(t, err, nil) - - tr := true - - test.Bool = &tr - - err = validate.Struct(test) - Equal(t, err, nil) - - test.Bool = nil - - err = validate.Struct(test) - NotEqual(t, err, nil) - - errs, ok := err.(ValidationErrors) - Equal(t, ok, true) - Equal(t, len(errs), 1) - AssertError(t, errs, "Test.Bool", "Test.Bool", "Bool", "Bool", "required") - - type Test2 struct { - Bool bool `validate:"required"` - } - - var test2 Test2 - - err = validate.Struct(test2) - NotEqual(t, err, nil) - - errs, ok = err.(ValidationErrors) - Equal(t, ok, true) - Equal(t, len(errs), 1) - AssertError(t, errs, "Test2.Bool", "Test2.Bool", "Bool", "Bool", "required") - - test2.Bool = true - - err = validate.Struct(test2) - Equal(t, err, nil) - - type Test3 struct { - Arr []string `validate:"required"` - } - - var test3 Test3 - - err = validate.Struct(test3) - NotEqual(t, err, nil) - - errs, ok = err.(ValidationErrors) - Equal(t, ok, true) - Equal(t, len(errs), 1) - AssertError(t, errs, "Test3.Arr", "Test3.Arr", "Arr", "Arr", "required") - - test3.Arr = make([]string, 0) - - err = validate.Struct(test3) - Equal(t, err, nil) - - type Test4 struct { - Arr *[]string `validate:"required"` // I know I know pointer to array, just making sure validation works as expected... - } - - var test4 Test4 - - err = validate.Struct(test4) - NotEqual(t, err, nil) - - errs, ok = err.(ValidationErrors) - Equal(t, ok, true) - Equal(t, len(errs), 1) - AssertError(t, errs, "Test4.Arr", "Test4.Arr", "Arr", "Arr", "required") - - arr := make([]string, 0) - test4.Arr = &arr - - err = validate.Struct(test4) - Equal(t, err, nil) -} - -func TestAlphaUnicodeValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"abc", true}, - {"this is a test string", false}, - {"这是一个测试字符串", true}, - {"123", false}, - {"<>@;.-=", false}, - {"ひらがな・カタカナ、.漢字", false}, - {"あいうえおfoobar", true}, - {"test@example.com", false}, - {"1234abcDE", false}, - {"カタカナ", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "alphaunicode") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "alphaunicode" { - t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs) - } - } - } - } -} - -func TestAlphanumericUnicodeValidation(t *testing.T) { - - tests := []struct { - param string - expected bool - }{ - {"", false}, - {"abc", true}, - {"this is a test string", false}, - {"这是一个测试字符串", true}, - {"\u0031\u0032\u0033", true}, // unicode 5 - {"123", true}, - {"<>@;.-=", false}, - {"ひらがな・カタカナ、.漢字", false}, - {"あいうえおfoobar", true}, - {"test@example.com", false}, - {"1234abcDE", true}, - {"カタカナ", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "alphanumunicode") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "alphanumunicode" { - t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs) - } - } - } - } -} - -func TestArrayStructNamespace(t *testing.T) { - - validate := New() - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - - if name == "-" { - return "" - } - - return name - }) - - type child struct { - Name string `json:"name" validate:"required"` - } - var input struct { - Children []child `json:"children" validate:"required,gt=0,dive"` - } - input.Children = []child{{"ok"}, {""}} - - errs := validate.Struct(input) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 1) - AssertError(t, errs, "children[1].name", "Children[1].Name", "name", "Name", "required") -} - -func TestMapStructNamespace(t *testing.T) { - - validate := New() - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - - if name == "-" { - return "" - } - - return name - }) - - type child struct { - Name string `json:"name" validate:"required"` - } - var input struct { - Children map[int]child `json:"children" validate:"required,gt=0,dive"` - } - input.Children = map[int]child{ - 0: {Name: "ok"}, - 1: {Name: ""}, - } - - errs := validate.Struct(input) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 1) - AssertError(t, errs, "children[1].name", "Children[1].Name", "name", "Name", "required") -} - -func TestFieldLevelName(t *testing.T) { - type Test struct { - String string `validate:"custom1" json:"json1"` - Array []string `validate:"dive,custom2" json:"json2"` - Map map[string]string `validate:"dive,custom3" json:"json3"` - Array2 []string `validate:"custom4" json:"json4"` - Map2 map[string]string `validate:"custom5" json:"json5"` - } - - var res1, res2, res3, res4, res5, alt1, alt2, alt3, alt4, alt5 string - validate := New() - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - - if name == "-" { - return "" - } - - return name - }) - err := validate.RegisterValidation("custom1", func(fl FieldLevel) bool { - res1 = fl.FieldName() - alt1 = fl.StructFieldName() - return true - }) - Equal(t, err, nil) - - err = validate.RegisterValidation("custom2", func(fl FieldLevel) bool { - res2 = fl.FieldName() - alt2 = fl.StructFieldName() - return true - }) - Equal(t, err, nil) - - err = validate.RegisterValidation("custom3", func(fl FieldLevel) bool { - res3 = fl.FieldName() - alt3 = fl.StructFieldName() - return true - }) - Equal(t, err, nil) - - err = validate.RegisterValidation("custom4", func(fl FieldLevel) bool { - res4 = fl.FieldName() - alt4 = fl.StructFieldName() - return true - }) - Equal(t, err, nil) - - err = validate.RegisterValidation("custom5", func(fl FieldLevel) bool { - res5 = fl.FieldName() - alt5 = fl.StructFieldName() - return true - }) - Equal(t, err, nil) - - test := Test{ - String: "test", - Array: []string{"1"}, - Map: map[string]string{"test": "test"}, - } - - errs := validate.Struct(test) - Equal(t, errs, nil) - Equal(t, res1, "json1") - Equal(t, alt1, "String") - Equal(t, res2, "json2[0]") - Equal(t, alt2, "Array[0]") - Equal(t, res3, "json3[test]") - Equal(t, alt3, "Map[test]") - Equal(t, res4, "json4") - Equal(t, alt4, "Array2") - Equal(t, res5, "json5") - Equal(t, alt5, "Map2") -} - -func TestValidateStructRegisterCtx(t *testing.T) { - var ctxVal string - - fnCtx := func(ctx context.Context, fl FieldLevel) bool { - ctxVal = ctx.Value(&ctxVal).(string) - return true - } - - var ctxSlVal string - slFn := func(ctx context.Context, sl StructLevel) { - ctxSlVal = ctx.Value(&ctxSlVal).(string) - } - - type Test struct { - Field string `validate:"val"` - } - - var tst Test - - validate := New() - err := validate.RegisterValidationCtx("val", fnCtx) - Equal(t, err, nil) - - validate.RegisterStructValidationCtx(slFn, Test{}) - - ctx := context.WithValue(context.Background(), &ctxVal, "testval") - ctx = context.WithValue(ctx, &ctxSlVal, "slVal") - errs := validate.StructCtx(ctx, tst) - Equal(t, errs, nil) - Equal(t, ctxVal, "testval") - Equal(t, ctxSlVal, "slVal") -} - -func TestHostnameRFC952Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"test.example.com", true}, - {"example.com", true}, - {"example24.com", true}, - {"test.example24.com", true}, - {"test24.example24.com", true}, - {"example", true}, - {"EXAMPLE", true}, - {"1.foo.com", false}, - {"test.example.com.", false}, - {"example.com.", false}, - {"example24.com.", false}, - {"test.example24.com.", false}, - {"test24.example24.com.", false}, - {"example.", false}, - {"192.168.0.1", false}, - {"email@example.com", false}, - {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, - {"2001:cdba:0:0:0:0:3257:9652", false}, - {"2001:cdba::3257:9652", false}, - {"example..........com", false}, - {"1234", false}, - {"abc1234", true}, - {"example. com", false}, - {"ex ample.com", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "hostname") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d hostname failed Error: %v", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d hostname failed Error: %v", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "hostname" { - t.Fatalf("Index: %d hostname failed Error: %v", i, errs) - } - } - } - } -} - -func TestHostnameRFC1123Validation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"test.example.com", true}, - {"example.com", true}, - {"example24.com", true}, - {"test.example24.com", true}, - {"test24.example24.com", true}, - {"example", true}, - {"1.foo.com", true}, - {"test.example.com.", false}, - {"example.com.", false}, - {"example24.com.", false}, - {"test.example24.com.", false}, - {"test24.example24.com.", false}, - {"example.", false}, - {"192.168.0.1", true}, - {"email@example.com", false}, - {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, - {"2001:cdba:0:0:0:0:3257:9652", false}, - {"2001:cdba::3257:9652", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "hostname_rfc1123") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Hostname: %v failed Error: %v", test, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Hostname: %v failed Error: %v", test, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "hostname_rfc1123" { - t.Fatalf("Hostname: %v failed Error: %v", i, errs) - } - } - } - } -} - -func TestHostnameRFC1123AliasValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"test.example.com", true}, - {"example.com", true}, - {"example24.com", true}, - {"test.example24.com", true}, - {"test24.example24.com", true}, - {"example", true}, - {"1.foo.com", true}, - {"test.example.com.", false}, - {"example.com.", false}, - {"example24.com.", false}, - {"test.example24.com.", false}, - {"test24.example24.com.", false}, - {"example.", false}, - {"192.168.0.1", true}, - {"email@example.com", false}, - {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, - {"2001:cdba:0:0:0:0:3257:9652", false}, - {"2001:cdba::3257:9652", false}, - } - - validate := New() - validate.RegisterAlias("hostname", "hostname_rfc1123") - - for i, test := range tests { - - errs := validate.Var(test.param, "hostname") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d hostname failed Error: %v", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d hostname failed Error: %v", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "hostname" { - t.Fatalf("Index: %d hostname failed Error: %v", i, errs) - } - } - } - } -} - -func TestFQDNValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"test.example.com", true}, - {"example.com", true}, - {"example24.com", true}, - {"test.example24.com", true}, - {"test24.example24.com", true}, - {"test.example.com.", true}, - {"example.com.", true}, - {"example24.com.", true}, - {"test.example24.com.", true}, - {"test24.example24.com.", true}, - {"24.example24.com", true}, - {"test.24.example.com", true}, - {"test24.example24.com..", false}, - {"example", false}, - {"192.168.0.1", false}, - {"email@example.com", false}, - {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, - {"2001:cdba:0:0:0:0:3257:9652", false}, - {"2001:cdba::3257:9652", false}, - {"", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "fqdn") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d fqdn failed Error: %v", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d fqdn failed Error: %v", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "fqdn" { - t.Fatalf("Index: %d fqdn failed Error: %v", i, errs) - } - } - } - } -} - -func TestIsDefault(t *testing.T) { - validate := New() - - type Inner struct { - String string `validate:"isdefault"` - } - type Test struct { - String string `validate:"isdefault"` - Inner *Inner `validate:"isdefault"` - } - - var tt Test - - errs := validate.Struct(tt) - Equal(t, errs, nil) - - tt.Inner = &Inner{String: ""} - errs = validate.Struct(tt) - NotEqual(t, errs, nil) - - fe := errs.(ValidationErrors)[0] - Equal(t, fe.Field(), "Inner") - Equal(t, fe.Namespace(), "Test.Inner") - Equal(t, fe.Tag(), "isdefault") - - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - if name == "-" { - return "" - } - return name - }) - - type Inner2 struct { - String string `validate:"isdefault"` - } - - type Test2 struct { - Inner Inner2 `validate:"isdefault" json:"inner"` - } - - var t2 Test2 - errs = validate.Struct(t2) - Equal(t, errs, nil) - - t2.Inner.String = "Changed" - errs = validate.Struct(t2) - NotEqual(t, errs, nil) - - fe = errs.(ValidationErrors)[0] - Equal(t, fe.Field(), "inner") - Equal(t, fe.Namespace(), "Test2.inner") - Equal(t, fe.Tag(), "isdefault") -} - -func TestUniqueValidation(t *testing.T) { - tests := []struct { - param interface{} - expected bool - }{ - // Arrays - {[2]string{"a", "b"}, true}, - {[2]int{1, 2}, true}, - {[2]float64{1, 2}, true}, - {[2]interface{}{"a", "b"}, true}, - {[2]interface{}{"a", 1}, true}, - {[2]float64{1, 1}, false}, - {[2]int{1, 1}, false}, - {[2]string{"a", "a"}, false}, - {[2]interface{}{"a", "a"}, false}, - {[4]interface{}{"a", 1, "b", 1}, false}, - {[2]*string{stringPtr("a"), stringPtr("b")}, true}, - {[2]*int{intPtr(1), intPtr(2)}, true}, - {[2]*float64{float64Ptr(1), float64Ptr(2)}, true}, - {[2]*string{stringPtr("a"), stringPtr("a")}, false}, - {[2]*float64{float64Ptr(1), float64Ptr(1)}, false}, - {[2]*int{intPtr(1), intPtr(1)}, false}, - // Slices - {[]string{"a", "b"}, true}, - {[]int{1, 2}, true}, - {[]float64{1, 2}, true}, - {[]interface{}{"a", "b"}, true}, - {[]interface{}{"a", 1}, true}, - {[]float64{1, 1}, false}, - {[]int{1, 1}, false}, - {[]string{"a", "a"}, false}, - {[]interface{}{"a", "a"}, false}, - {[]interface{}{"a", 1, "b", 1}, false}, - {[]*string{stringPtr("a"), stringPtr("b")}, true}, - {[]*int{intPtr(1), intPtr(2)}, true}, - {[]*float64{float64Ptr(1), float64Ptr(2)}, true}, - {[]*string{stringPtr("a"), stringPtr("a")}, false}, - {[]*float64{float64Ptr(1), float64Ptr(1)}, false}, - {[]*int{intPtr(1), intPtr(1)}, false}, - // Maps - {map[string]string{"one": "a", "two": "b"}, true}, - {map[string]int{"one": 1, "two": 2}, true}, - {map[string]float64{"one": 1, "two": 2}, true}, - {map[string]interface{}{"one": "a", "two": "b"}, true}, - {map[string]interface{}{"one": "a", "two": 1}, true}, - {map[string]float64{"one": 1, "two": 1}, false}, - {map[string]int{"one": 1, "two": 1}, false}, - {map[string]string{"one": "a", "two": "a"}, false}, - {map[string]interface{}{"one": "a", "two": "a"}, false}, - {map[string]interface{}{"one": "a", "two": 1, "three": "b", "four": 1}, false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "unique") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d unique failed Error: %v", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d unique failed Error: %v", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "unique" { - t.Fatalf("Index: %d unique failed Error: %v", i, errs) - } - } - } - } - PanicMatches(t, func() { _ = validate.Var(1.0, "unique") }, "Bad field type float64") -} - -func TestUniqueValidationStructSlice(t *testing.T) { - testStructs := []struct { - A string - B string - }{ - {A: "one", B: "two"}, - {A: "one", B: "three"}, - } - - tests := []struct { - target interface{} - param string - expected bool - }{ - {testStructs, "unique", true}, - {testStructs, "unique=A", false}, - {testStructs, "unique=B", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.target, test.param) - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d unique failed Error: %v", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d unique failed Error: %v", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "unique" { - t.Fatalf("Index: %d unique failed Error: %v", i, errs) - } - } - } - } - PanicMatches(t, func() { _ = validate.Var(testStructs, "unique=C") }, "Bad field name C") -} - -func TestUniqueValidationStructPtrSlice(t *testing.T) { - testStructs := []*struct { - A *string - B *string - }{ - {A: stringPtr("one"), B: stringPtr("two")}, - {A: stringPtr("one"), B: stringPtr("three")}, - } - - tests := []struct { - target interface{} - param string - expected bool - }{ - {testStructs, "unique", true}, - {testStructs, "unique=A", false}, - {testStructs, "unique=B", true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.target, test.param) - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d unique failed Error: %v", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d unique failed Error: %v", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "unique" { - t.Fatalf("Index: %d unique failed Error: %v", i, errs) - } - } - } - } - PanicMatches(t, func() { _ = validate.Var(testStructs, "unique=C") }, "Bad field name C") -} - -func TestHTMLValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"", true}, - {"", true}, - {"", false}, - {"<123nonsense>", false}, - {"test", false}, - {"&example", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "html") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d html failed Error: %v", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d html failed Error: %v", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "html" { - t.Fatalf("Index: %d html failed Error: %v", i, errs) - } - } - } - } -} - -func TestHTMLEncodedValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"<", true}, - {"¯", true}, - {"�", true}, - {"ð", true}, - {"<", true}, - {"¯", true}, - {"�", true}, - {"ð", true}, - {"&#ab", true}, - {"<", true}, - {">", true}, - {""", true}, - {"&", true}, - {"#x0a", false}, - {"&x00", false}, - {"z", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "html_encoded") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d html_encoded failed Error: %v", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d html_enocded failed Error: %v", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "html_encoded" { - t.Fatalf("Index: %d html_encoded failed Error: %v", i, errs) - } - } - } - } -} - -func TestURLEncodedValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {"%20", true}, - {"%af", true}, - {"%ff", true}, - {"<%az", false}, - {"%test%", false}, - {"a%b", false}, - {"1%2", false}, - {"%%a%%", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "url_encoded") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d url_encoded failed Error: %v", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d url_enocded failed Error: %v", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "url_encoded" { - t.Fatalf("Index: %d url_encoded failed Error: %v", i, errs) - } - } - } - } -} - -func TestKeys(t *testing.T) { - - type Test struct { - Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey,endkeys,eq=testval" json:"test1"` - Test2 map[int]int `validate:"gt=0,dive,keys,eq=3,endkeys,eq=4" json:"test2"` - Test3 map[int]int `validate:"gt=0,dive,keys,eq=3,endkeys" json:"test3"` - } - - var tst Test - - validate := New() - err := validate.Struct(tst) - NotEqual(t, err, nil) - Equal(t, len(err.(ValidationErrors)), 3) - AssertError(t, err.(ValidationErrors), "Test.Test1", "Test.Test1", "Test1", "Test1", "gt") - AssertError(t, err.(ValidationErrors), "Test.Test2", "Test.Test2", "Test2", "Test2", "gt") - AssertError(t, err.(ValidationErrors), "Test.Test3", "Test.Test3", "Test3", "Test3", "gt") - - tst.Test1 = map[string]string{ - "testkey": "testval", - } - - tst.Test2 = map[int]int{ - 3: 4, - } - - tst.Test3 = map[int]int{ - 3: 4, - } - - err = validate.Struct(tst) - Equal(t, err, nil) - - tst.Test1["badtestkey"] = "badtestvalue" - tst.Test2[10] = 11 - - err = validate.Struct(tst) - NotEqual(t, err, nil) - - errs := err.(ValidationErrors) - - Equal(t, len(errs), 4) - - AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") - AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") - AssertDeepError(t, errs, "Test.Test2[10]", "Test.Test2[10]", "Test2[10]", "Test2[10]", "eq", "eq") - AssertDeepError(t, errs, "Test.Test2[10]", "Test.Test2[10]", "Test2[10]", "Test2[10]", "eq", "eq") - - type Test2 struct { - NestedKeys map[[1]string]string `validate:"gt=0,dive,keys,dive,eq=innertestkey,endkeys,eq=outertestval"` - } - - var tst2 Test2 - - err = validate.Struct(tst2) - NotEqual(t, err, nil) - Equal(t, len(err.(ValidationErrors)), 1) - AssertError(t, err.(ValidationErrors), "Test2.NestedKeys", "Test2.NestedKeys", "NestedKeys", "NestedKeys", "gt") - - tst2.NestedKeys = map[[1]string]string{ - [1]string{"innertestkey"}: "outertestval", - } - - err = validate.Struct(tst2) - Equal(t, err, nil) - - tst2.NestedKeys[[1]string{"badtestkey"}] = "badtestvalue" - - err = validate.Struct(tst2) - NotEqual(t, err, nil) - - errs = err.(ValidationErrors) - - Equal(t, len(errs), 2) - AssertDeepError(t, errs, "Test2.NestedKeys[[badtestkey]][0]", "Test2.NestedKeys[[badtestkey]][0]", "NestedKeys[[badtestkey]][0]", "NestedKeys[[badtestkey]][0]", "eq", "eq") - AssertDeepError(t, errs, "Test2.NestedKeys[[badtestkey]]", "Test2.NestedKeys[[badtestkey]]", "NestedKeys[[badtestkey]]", "NestedKeys[[badtestkey]]", "eq", "eq") - - // test bad tag definitions - - PanicMatches(t, func() { _ = validate.Var(map[string]string{"key": "val"}, "endkeys,dive,eq=val") }, "'endkeys' tag encountered without a corresponding 'keys' tag") - PanicMatches(t, func() { _ = validate.Var(1, "keys,eq=1,endkeys") }, "'keys' tag must be immediately preceded by the 'dive' tag") - - // test custom tag name - validate = New() - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - - if name == "-" { - return "" - } - return name - }) - - err = validate.Struct(tst) - NotEqual(t, err, nil) - - errs = err.(ValidationErrors) - - Equal(t, len(errs), 4) - - AssertDeepError(t, errs, "Test.test1[badtestkey]", "Test.Test1[badtestkey]", "test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") - AssertDeepError(t, errs, "Test.test1[badtestkey]", "Test.Test1[badtestkey]", "test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") - AssertDeepError(t, errs, "Test.test2[10]", "Test.Test2[10]", "test2[10]", "Test2[10]", "eq", "eq") - AssertDeepError(t, errs, "Test.test2[10]", "Test.Test2[10]", "test2[10]", "Test2[10]", "eq", "eq") -} - -// Thanks @adrian-sgn specific test for your specific scenario -func TestKeysCustomValidation(t *testing.T) { - type LangCode string - type Label map[LangCode]string - - type TestMapStructPtr struct { - Label Label `validate:"dive,keys,lang_code,endkeys,required"` - } - - validate := New() - err := validate.RegisterValidation("lang_code", func(fl FieldLevel) bool { - validLangCodes := map[LangCode]struct{}{ - "en": {}, - "es": {}, - "pt": {}, - } - - _, ok := validLangCodes[fl.Field().Interface().(LangCode)] - return ok - }) - Equal(t, err, nil) - - label := Label{ - "en": "Good morning!", - "pt": "", - "es": "¡Buenos días!", - "xx": "Bad key", - "xxx": "", - } - - err = validate.Struct(TestMapStructPtr{label}) - NotEqual(t, err, nil) - - errs := err.(ValidationErrors) - Equal(t, len(errs), 4) - - AssertDeepError(t, errs, "TestMapStructPtr.Label[xx]", "TestMapStructPtr.Label[xx]", "Label[xx]", "Label[xx]", "lang_code", "lang_code") - AssertDeepError(t, errs, "TestMapStructPtr.Label[pt]", "TestMapStructPtr.Label[pt]", "Label[pt]", "Label[pt]", "required", "required") - AssertDeepError(t, errs, "TestMapStructPtr.Label[xxx]", "TestMapStructPtr.Label[xxx]", "Label[xxx]", "Label[xxx]", "lang_code", "lang_code") - AssertDeepError(t, errs, "TestMapStructPtr.Label[xxx]", "TestMapStructPtr.Label[xxx]", "Label[xxx]", "Label[xxx]", "required", "required") - - // find specific error - - var e FieldError - for _, e = range errs { - if e.Namespace() == "TestMapStructPtr.Label[xxx]" { - break - } - } - - Equal(t, e.Param(), "") - Equal(t, e.Value().(LangCode), LangCode("xxx")) - - for _, e = range errs { - if e.Namespace() == "TestMapStructPtr.Label[xxx]" && e.Tag() == "required" { - break - } - } - - Equal(t, e.Param(), "") - Equal(t, e.Value().(string), "") -} - -func TestKeyOrs(t *testing.T) { - - type Test struct { - Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey|eq=testkeyok,endkeys,eq=testval" json:"test1"` - } - - var tst Test - - validate := New() - err := validate.Struct(tst) - NotEqual(t, err, nil) - Equal(t, len(err.(ValidationErrors)), 1) - AssertError(t, err.(ValidationErrors), "Test.Test1", "Test.Test1", "Test1", "Test1", "gt") - - tst.Test1 = map[string]string{ - "testkey": "testval", - } - - err = validate.Struct(tst) - Equal(t, err, nil) - - tst.Test1["badtestkey"] = "badtestval" - - err = validate.Struct(tst) - NotEqual(t, err, nil) - - errs := err.(ValidationErrors) - - Equal(t, len(errs), 2) - - AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq=testkey|eq=testkeyok", "eq=testkey|eq=testkeyok") - AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") - - validate.RegisterAlias("okkey", "eq=testkey|eq=testkeyok") - - type Test2 struct { - Test1 map[string]string `validate:"gt=0,dive,keys,okkey,endkeys,eq=testval" json:"test1"` - } - - var tst2 Test2 - - err = validate.Struct(tst2) - NotEqual(t, err, nil) - Equal(t, len(err.(ValidationErrors)), 1) - AssertError(t, err.(ValidationErrors), "Test2.Test1", "Test2.Test1", "Test1", "Test1", "gt") - - tst2.Test1 = map[string]string{ - "testkey": "testval", - } - - err = validate.Struct(tst2) - Equal(t, err, nil) - - tst2.Test1["badtestkey"] = "badtestval" - - err = validate.Struct(tst2) - NotEqual(t, err, nil) - - errs = err.(ValidationErrors) - - Equal(t, len(errs), 2) - - AssertDeepError(t, errs, "Test2.Test1[badtestkey]", "Test2.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "okkey", "eq=testkey|eq=testkeyok") - AssertDeepError(t, errs, "Test2.Test1[badtestkey]", "Test2.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") -} - -func TestStructLevelValidationsPointerPassing(t *testing.T) { - v1 := New() - v1.RegisterStructValidation(StructValidationTestStruct, &TestStruct{}) - - tst := &TestStruct{ - String: "good value", - } - - errs := v1.Struct(tst) - NotEqual(t, errs, nil) - AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct") -} - -func TestDirValidation(t *testing.T) { - validate := New() - - tests := []struct { - title string - param string - expected bool - }{ - {"existing dir", "testdata", true}, - {"existing self dir", ".", true}, - {"existing parent dir", "..", true}, - {"empty dir", "", false}, - {"missing dir", "non_existing_testdata", false}, - {"a file not a directory", filepath.Join("testdata", "a.go"), false}, - } - - for _, test := range tests { - errs := validate.Var(test.param, "dir") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) - } - } - } - - PanicMatches(t, func() { - _ = validate.Var(2, "dir") - }, "Bad field type int") -} - -func TestStartsWithValidation(t *testing.T) { - tests := []struct { - Value string `validate:"startswith=(/^ヮ^)/*:・゚✧"` - Tag string - ExpectedNil bool - }{ - {Value: "(/^ヮ^)/*:・゚✧ glitter", Tag: "startswith=(/^ヮ^)/*:・゚✧", ExpectedNil: true}, - {Value: "abcd", Tag: "startswith=(/^ヮ^)/*:・゚✧", ExpectedNil: false}, - } - - validate := New() - - for i, s := range tests { - errs := validate.Var(s.Value, s.Tag) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - - errs = validate.Struct(s) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - } -} - -func TestEndsWithValidation(t *testing.T) { - tests := []struct { - Value string `validate:"endswith=(/^ヮ^)/*:・゚✧"` - Tag string - ExpectedNil bool - }{ - {Value: "glitter (/^ヮ^)/*:・゚✧", Tag: "endswith=(/^ヮ^)/*:・゚✧", ExpectedNil: true}, - {Value: "(/^ヮ^)/*:・゚✧ glitter", Tag: "endswith=(/^ヮ^)/*:・゚✧", ExpectedNil: false}, - } - - validate := New() - - for i, s := range tests { - errs := validate.Var(s.Value, s.Tag) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - - errs = validate.Struct(s) - - if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { - t.Fatalf("Index: %d failed Error: %s", i, errs) - } - } -} - -func TestRequiredIf(t *testing.T) { - type Inner struct { - Field *string - } - - fieldVal := "test" - test := struct { - Inner *Inner - FieldE string `validate:"omitempty" json:"field_e"` - FieldER string `validate:"required_if=FieldE test" json:"field_er"` - Field1 string `validate:"omitempty" json:"field_1"` - Field2 *string `validate:"required_if=Field1 test" json:"field_2"` - Field3 map[string]string `validate:"required_if=Field2 test" json:"field_3"` - Field4 interface{} `validate:"required_if=Field3 1" json:"field_4"` - Field5 int `validate:"required_if=Inner.Field test" json:"field_5"` - Field6 uint `validate:"required_if=Field5 1" json:"field_6"` - Field7 float32 `validate:"required_if=Field6 1" json:"field_7"` - Field8 float64 `validate:"required_if=Field7 1.0" json:"field_8"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: 2, - } - - validate := New() - - errs := validate.Struct(test) - Equal(t, errs, nil) - - test2 := struct { - Inner *Inner - Inner2 *Inner - FieldE string `validate:"omitempty" json:"field_e"` - FieldER string `validate:"required_if=FieldE test" json:"field_er"` - Field1 string `validate:"omitempty" json:"field_1"` - Field2 *string `validate:"required_if=Field1 test" json:"field_2"` - Field3 map[string]string `validate:"required_if=Field2 test" json:"field_3"` - Field4 interface{} `validate:"required_if=Field2 test" json:"field_4"` - Field5 string `validate:"required_if=Field3 1" json:"field_5"` - Field6 string `validate:"required_if=Inner.Field test" json:"field_6"` - Field7 string `validate:"required_if=Inner2.Field test" json:"field_7"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field2: &fieldVal, - } - - errs = validate.Struct(test2) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 3) - AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_if") - AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "required_if") - AssertError(t, errs, "Field6", "Field6", "Field6", "Field6", "required_if") - - defer func() { - if r := recover(); r == nil { - t.Errorf("test3 should have panicked!") - } - }() - - test3 := struct { - Inner *Inner - Field1 string `validate:"required_if=Inner.Field" json:"field_1"` - }{ - Inner: &Inner{Field: &fieldVal}, - } - _ = validate.Struct(test3) -} - -func TestRequiredUnless(t *testing.T) { - type Inner struct { - Field *string - } - - fieldVal := "test" - test := struct { - Inner *Inner - FieldE string `validate:"omitempty" json:"field_e"` - FieldER string `validate:"required_unless=FieldE test" json:"field_er"` - Field1 string `validate:"omitempty" json:"field_1"` - Field2 *string `validate:"required_unless=Field1 test" json:"field_2"` - Field3 map[string]string `validate:"required_unless=Field2 test" json:"field_3"` - Field4 interface{} `validate:"required_unless=Field3 1" json:"field_4"` - Field5 int `validate:"required_unless=Inner.Field test" json:"field_5"` - Field6 uint `validate:"required_unless=Field5 2" json:"field_6"` - Field7 float32 `validate:"required_unless=Field6 0" json:"field_7"` - Field8 float64 `validate:"required_unless=Field7 0.0" json:"field_8"` - }{ - FieldE: "test", - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: 2, - } - - validate := New() - - errs := validate.Struct(test) - Equal(t, errs, nil) - - test2 := struct { - Inner *Inner - Inner2 *Inner - FieldE string `validate:"omitempty" json:"field_e"` - FieldER string `validate:"required_unless=FieldE test" json:"field_er"` - Field1 string `validate:"omitempty" json:"field_1"` - Field2 *string `validate:"required_unless=Field1 test" json:"field_2"` - Field3 map[string]string `validate:"required_unless=Field2 test" json:"field_3"` - Field4 interface{} `validate:"required_unless=Field2 test" json:"field_4"` - Field5 string `validate:"required_unless=Field3 0" json:"field_5"` - Field6 string `validate:"required_unless=Inner.Field test" json:"field_6"` - Field7 string `validate:"required_unless=Inner2.Field test" json:"field_7"` - }{ - Inner: &Inner{Field: &fieldVal}, - FieldE: "test", - Field1: "test", - } - - errs = validate.Struct(test2) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 3) - AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_unless") - AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "required_unless") - AssertError(t, errs, "Field7", "Field7", "Field7", "Field7", "required_unless") - - defer func() { - if r := recover(); r == nil { - t.Errorf("test3 should have panicked!") - } - }() - - test3 := struct { - Inner *Inner - Field1 string `validate:"required_unless=Inner.Field" json:"field_1"` - }{ - Inner: &Inner{Field: &fieldVal}, - } - _ = validate.Struct(test3) -} - -func TestRequiredWith(t *testing.T) { - type Inner struct { - Field *string - } - - fieldVal := "test" - test := struct { - Inner *Inner - FieldE string `validate:"omitempty" json:"field_e"` - FieldER string `validate:"required_with=FieldE" json:"field_er"` - Field1 string `validate:"omitempty" json:"field_1"` - Field2 *string `validate:"required_with=Field1" json:"field_2"` - Field3 map[string]string `validate:"required_with=Field2" json:"field_3"` - Field4 interface{} `validate:"required_with=Field3" json:"field_4"` - Field5 string `validate:"required_with=Inner.Field" json:"field_5"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - } - - validate := New() - - errs := validate.Struct(test) - Equal(t, errs, nil) - - test2 := struct { - Inner *Inner - Inner2 *Inner - FieldE string `validate:"omitempty" json:"field_e"` - FieldER string `validate:"required_with=FieldE" json:"field_er"` - Field1 string `validate:"omitempty" json:"field_1"` - Field2 *string `validate:"required_with=Field1" json:"field_2"` - Field3 map[string]string `validate:"required_with=Field2" json:"field_3"` - Field4 interface{} `validate:"required_with=Field2" json:"field_4"` - Field5 string `validate:"required_with=Field3" json:"field_5"` - Field6 string `validate:"required_with=Inner.Field" json:"field_6"` - Field7 string `validate:"required_with=Inner2.Field" json:"field_7"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field2: &fieldVal, - } - - errs = validate.Struct(test2) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 3) - AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_with") - AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "required_with") - AssertError(t, errs, "Field6", "Field6", "Field6", "Field6", "required_with") -} - -func TestExcludedWith(t *testing.T) { - type Inner struct { - FieldE string - Field *string - } - - fieldVal := "test" - test := struct { - Inner *Inner - Inner2 *Inner - Field string `validate:"omitempty" json:"field"` - FieldE string `validate:"omitempty" json:"field_e"` - Field1 string `validate:"excluded_with=FieldE" json:"field_1"` - Field2 *string `validate:"excluded_with=FieldE" json:"field_2"` - Field3 map[string]string `validate:"excluded_with=FieldE" json:"field_3"` - Field4 interface{} `validate:"excluded_with=FieldE" json:"field_4"` - Field5 string `validate:"excluded_with=Inner.FieldE" json:"field_5"` - Field6 string `validate:"excluded_with=Inner2.FieldE" json:"field_6"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field1: fieldVal, - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - Field6: "test", - } - - validate := New() - - errs := validate.Struct(test) - Equal(t, errs, nil) - - test2 := struct { - Inner *Inner - Inner2 *Inner - Field string `validate:"omitempty" json:"field"` - FieldE string `validate:"omitempty" json:"field_e"` - Field1 string `validate:"excluded_with=Field" json:"field_1"` - Field2 *string `validate:"excluded_with=Field" json:"field_2"` - Field3 map[string]string `validate:"excluded_with=Field" json:"field_3"` - Field4 interface{} `validate:"excluded_with=Field" json:"field_4"` - Field5 string `validate:"excluded_with=Inner.Field" json:"field_5"` - Field6 string `validate:"excluded_with=Inner2.Field" json:"field_6"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field: "populated", - Field1: fieldVal, - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - Field6: "test", - } - - errs = validate.Struct(test2) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 5) - for i := 1; i <= 5; i++ { - name := fmt.Sprintf("Field%d", i) - AssertError(t, errs, name, name, name, name, "excluded_with") - } -} - -func TestExcludedWithout(t *testing.T) { - type Inner struct { - FieldE string - Field *string - } - - fieldVal := "test" - test := struct { - Inner *Inner - Inner2 *Inner - Field string `validate:"omitempty" json:"field"` - FieldE string `validate:"omitempty" json:"field_e"` - Field1 string `validate:"excluded_without=Field" json:"field_1"` - Field2 *string `validate:"excluded_without=Field" json:"field_2"` - Field3 map[string]string `validate:"excluded_without=Field" json:"field_3"` - Field4 interface{} `validate:"excluded_without=Field" json:"field_4"` - Field5 string `validate:"excluded_without=Inner.Field" json:"field_5"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field: "populated", - Field1: fieldVal, - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - } - - validate := New() - - errs := validate.Struct(test) - Equal(t, errs, nil) - - test2 := struct { - Inner *Inner - Inner2 *Inner - Field string `validate:"omitempty" json:"field"` - FieldE string `validate:"omitempty" json:"field_e"` - Field1 string `validate:"excluded_without=FieldE" json:"field_1"` - Field2 *string `validate:"excluded_without=FieldE" json:"field_2"` - Field3 map[string]string `validate:"excluded_without=FieldE" json:"field_3"` - Field4 interface{} `validate:"excluded_without=FieldE" json:"field_4"` - Field5 string `validate:"excluded_without=Inner.FieldE" json:"field_5"` - Field6 string `validate:"excluded_without=Inner2.FieldE" json:"field_6"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field1: fieldVal, - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - Field6: "test", - } - - errs = validate.Struct(test2) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 6) - for i := 1; i <= 6; i++ { - name := fmt.Sprintf("Field%d", i) - AssertError(t, errs, name, name, name, name, "excluded_without") - } -} - -func TestExcludedWithAll(t *testing.T) { - type Inner struct { - FieldE string - Field *string - } - - fieldVal := "test" - test := struct { - Inner *Inner - Inner2 *Inner - Field string `validate:"omitempty" json:"field"` - FieldE string `validate:"omitempty" json:"field_e"` - Field1 string `validate:"excluded_with_all=FieldE Field" json:"field_1"` - Field2 *string `validate:"excluded_with_all=FieldE Field" json:"field_2"` - Field3 map[string]string `validate:"excluded_with_all=FieldE Field" json:"field_3"` - Field4 interface{} `validate:"excluded_with_all=FieldE Field" json:"field_4"` - Field5 string `validate:"excluded_with_all=Inner.FieldE" json:"field_5"` - Field6 string `validate:"excluded_with_all=Inner2.FieldE" json:"field_6"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field: fieldVal, - Field1: fieldVal, - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - Field6: "test", - } - - validate := New() - - errs := validate.Struct(test) - Equal(t, errs, nil) - - test2 := struct { - Inner *Inner - Inner2 *Inner - Field string `validate:"omitempty" json:"field"` - FieldE string `validate:"omitempty" json:"field_e"` - Field1 string `validate:"excluded_with_all=Field FieldE" json:"field_1"` - Field2 *string `validate:"excluded_with_all=Field FieldE" json:"field_2"` - Field3 map[string]string `validate:"excluded_with_all=Field FieldE" json:"field_3"` - Field4 interface{} `validate:"excluded_with_all=Field FieldE" json:"field_4"` - Field5 string `validate:"excluded_with_all=Inner.Field" json:"field_5"` - Field6 string `validate:"excluded_with_all=Inner2.Field" json:"field_6"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field: "populated", - FieldE: "populated", - Field1: fieldVal, - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - Field6: "test", - } - - errs = validate.Struct(test2) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 5) - for i := 1; i <= 5; i++ { - name := fmt.Sprintf("Field%d", i) - AssertError(t, errs, name, name, name, name, "excluded_with_all") - } -} - -func TestExcludedWithoutAll(t *testing.T) { - type Inner struct { - FieldE string - Field *string - } - - fieldVal := "test" - test := struct { - Inner *Inner - Inner2 *Inner - Field string `validate:"omitempty" json:"field"` - FieldE string `validate:"omitempty" json:"field_e"` - Field1 string `validate:"excluded_without_all=Field FieldE" json:"field_1"` - Field2 *string `validate:"excluded_without_all=Field FieldE" json:"field_2"` - Field3 map[string]string `validate:"excluded_without_all=Field FieldE" json:"field_3"` - Field4 interface{} `validate:"excluded_without_all=Field FieldE" json:"field_4"` - Field5 string `validate:"excluded_without_all=Inner.Field Inner.Field2" json:"field_5"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field: "populated", - Field1: fieldVal, - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - } - - validate := New() - - errs := validate.Struct(test) - Equal(t, errs, nil) - - test2 := struct { - Inner *Inner - Inner2 *Inner - Field string `validate:"omitempty" json:"field"` - FieldE string `validate:"omitempty" json:"field_e"` - Field1 string `validate:"excluded_without_all=FieldE Field" json:"field_1"` - Field2 *string `validate:"excluded_without_all=FieldE Field" json:"field_2"` - Field3 map[string]string `validate:"excluded_without_all=FieldE Field" json:"field_3"` - Field4 interface{} `validate:"excluded_without_all=FieldE Field" json:"field_4"` - Field5 string `validate:"excluded_without_all=Inner.FieldE" json:"field_5"` - Field6 string `validate:"excluded_without_all=Inner2.FieldE" json:"field_6"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field1: fieldVal, - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - Field6: "test", - } - - errs = validate.Struct(test2) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 6) - for i := 1; i <= 6; i++ { - name := fmt.Sprintf("Field%d", i) - AssertError(t, errs, name, name, name, name, "excluded_without_all") - } -} - -func TestRequiredWithAll(t *testing.T) { - type Inner struct { - Field *string - } - - fieldVal := "test" - test := struct { - Inner *Inner - FieldE string `validate:"omitempty" json:"field_e"` - FieldER string `validate:"required_with_all=FieldE" json:"field_er"` - Field1 string `validate:"omitempty" json:"field_1"` - Field2 *string `validate:"required_with_all=Field1" json:"field_2"` - Field3 map[string]string `validate:"required_with_all=Field2" json:"field_3"` - Field4 interface{} `validate:"required_with_all=Field3" json:"field_4"` - Field5 string `validate:"required_with_all=Inner.Field" json:"field_5"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field1: "test_field1", - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - } - - validate := New() - - errs := validate.Struct(test) - Equal(t, errs, nil) - - test2 := struct { - Inner *Inner - Inner2 *Inner - FieldE string `validate:"omitempty" json:"field_e"` - FieldER string `validate:"required_with_all=FieldE" json:"field_er"` - Field1 string `validate:"omitempty" json:"field_1"` - Field2 *string `validate:"required_with_all=Field1" json:"field_2"` - Field3 map[string]string `validate:"required_with_all=Field2" json:"field_3"` - Field4 interface{} `validate:"required_with_all=Field1 FieldE" json:"field_4"` - Field5 string `validate:"required_with_all=Inner.Field Field2" json:"field_5"` - Field6 string `validate:"required_with_all=Inner2.Field Field2" json:"field_6"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field2: &fieldVal, - } - - errs = validate.Struct(test2) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 2) - AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_with_all") - AssertError(t, errs, "Field5", "Field5", "Field5", "Field5", "required_with_all") -} - -func TestRequiredWithout(t *testing.T) { - - type Inner struct { - Field *string - } - - fieldVal := "test" - test := struct { - Inner *Inner - Field1 string `validate:"omitempty" json:"field_1"` - Field2 *string `validate:"required_without=Field1" json:"field_2"` - Field3 map[string]string `validate:"required_without=Field2" json:"field_3"` - Field4 interface{} `validate:"required_without=Field3" json:"field_4"` - Field5 string `validate:"required_without=Field3" json:"field_5"` - }{ - Inner: &Inner{Field: &fieldVal}, - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - } - - validate := New() - - errs := validate.Struct(test) - Equal(t, errs, nil) - - test2 := struct { - Inner *Inner - Inner2 *Inner - Field1 string `json:"field_1"` - Field2 *string `validate:"required_without=Field1" json:"field_2"` - Field3 map[string]string `validate:"required_without=Field2" json:"field_3"` - Field4 interface{} `validate:"required_without=Field3" json:"field_4"` - Field5 string `validate:"required_without=Field3" json:"field_5"` - Field6 string `validate:"required_without=Field1" json:"field_6"` - Field7 string `validate:"required_without=Inner.Field" json:"field_7"` - Field8 string `validate:"required_without=Inner.Field" json:"field_8"` - }{ - Inner: &Inner{}, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - } - - errs = validate.Struct(&test2) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 4) - AssertError(t, errs, "Field2", "Field2", "Field2", "Field2", "required_without") - AssertError(t, errs, "Field6", "Field6", "Field6", "Field6", "required_without") - AssertError(t, errs, "Field7", "Field7", "Field7", "Field7", "required_without") - AssertError(t, errs, "Field8", "Field8", "Field8", "Field8", "required_without") - - test3 := struct { - Field1 *string `validate:"required_without=Field2,omitempty,min=1" json:"field_1"` - Field2 *string `validate:"required_without=Field1,omitempty,min=1" json:"field_2"` - }{ - Field1: &fieldVal, - } - - errs = validate.Struct(&test3) - Equal(t, errs, nil) -} - -func TestRequiredWithoutAll(t *testing.T) { - - fieldVal := "test" - test := struct { - Field1 string `validate:"omitempty" json:"field_1"` - Field2 *string `validate:"required_without_all=Field1" json:"field_2"` - Field3 map[string]string `validate:"required_without_all=Field2" json:"field_3"` - Field4 interface{} `validate:"required_without_all=Field3" json:"field_4"` - Field5 string `validate:"required_without_all=Field3" json:"field_5"` - }{ - Field1: "", - Field2: &fieldVal, - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - } - - validate := New() - - errs := validate.Struct(test) - Equal(t, errs, nil) - - test2 := struct { - Field1 string `validate:"omitempty" json:"field_1"` - Field2 *string `validate:"required_without_all=Field1" json:"field_2"` - Field3 map[string]string `validate:"required_without_all=Field2" json:"field_3"` - Field4 interface{} `validate:"required_without_all=Field3" json:"field_4"` - Field5 string `validate:"required_without_all=Field3" json:"field_5"` - Field6 string `validate:"required_without_all=Field1 Field3" json:"field_6"` - }{ - Field3: map[string]string{"key": "val"}, - Field4: "test", - Field5: "test", - } - - errs = validate.Struct(test2) - NotEqual(t, errs, nil) - - ve := errs.(ValidationErrors) - Equal(t, len(ve), 1) - AssertError(t, errs, "Field2", "Field2", "Field2", "Field2", "required_without_all") -} - -func TestLookup(t *testing.T) { - type Lookup struct { - FieldA *string `json:"fieldA,omitempty" validate:"required_without=FieldB"` - FieldB *string `json:"fieldB,omitempty" validate:"required_without=FieldA"` - } - - fieldAValue := "1232" - lookup := Lookup{ - FieldA: &fieldAValue, - FieldB: nil, - } - Equal(t, New().Struct(lookup), nil) -} - -func TestAbilityToValidateNils(t *testing.T) { - - type TestStruct struct { - Test *string `validate:"nil"` - } - - ts := TestStruct{} - val := New() - fn := func(fl FieldLevel) bool { - return fl.Field().Kind() == reflect.Ptr && fl.Field().IsNil() - } - - err := val.RegisterValidation("nil", fn, true) - Equal(t, err, nil) - - errs := val.Struct(ts) - Equal(t, errs, nil) - - str := "string" - ts.Test = &str - - errs = val.Struct(ts) - NotEqual(t, errs, nil) -} - -func TestRequiredWithoutPointers(t *testing.T) { - type Lookup struct { - FieldA *bool `json:"fieldA,omitempty" validate:"required_without=FieldB"` - FieldB *bool `json:"fieldB,omitempty" validate:"required_without=FieldA"` - } - - b := true - lookup := Lookup{ - FieldA: &b, - FieldB: nil, - } - - val := New() - errs := val.Struct(lookup) - Equal(t, errs, nil) - - b = false - lookup = Lookup{ - FieldA: &b, - FieldB: nil, - } - errs = val.Struct(lookup) - Equal(t, errs, nil) -} - -func TestRequiredWithoutAllPointers(t *testing.T) { - type Lookup struct { - FieldA *bool `json:"fieldA,omitempty" validate:"required_without_all=FieldB"` - FieldB *bool `json:"fieldB,omitempty" validate:"required_without_all=FieldA"` - } - - b := true - lookup := Lookup{ - FieldA: &b, - FieldB: nil, - } - - val := New() - errs := val.Struct(lookup) - Equal(t, errs, nil) - - b = false - lookup = Lookup{ - FieldA: &b, - FieldB: nil, - } - errs = val.Struct(lookup) - Equal(t, errs, nil) -} - -func TestGetTag(t *testing.T) { - var tag string - - type Test struct { - String string `validate:"mytag"` - } - - val := New() - _ = val.RegisterValidation("mytag", func(fl FieldLevel) bool { - tag = fl.GetTag() - return true - }) - - var test Test - errs := val.Struct(test) - Equal(t, errs, nil) - Equal(t, tag, "mytag") -} - -func TestJSONValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {`foo`, false}, - {`}{`, false}, - {`{]`, false}, - {`{}`, true}, - {`{"foo":"bar"}`, true}, - {`{"foo":"bar","bar":{"baz":["qux"]}}`, true}, - {`{"foo": 3 "bar": 4}`, false}, - {`{"foo": 3 ,"bar": 4`, false}, - {`{foo": 3, "bar": 4}`, false}, - {`foo`, false}, - {`1`, true}, - {`true`, true}, - {`null`, true}, - {`"null"`, true}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "json") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d json failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d json failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "json" { - t.Fatalf("Index: %d json failed Error: %s", i, errs) - } - } - } - } - - PanicMatches(t, func() { - _ = validate.Var(2, "json") - }, "Bad field type int") -} - -func Test_hostnameport_validator(t *testing.T) { - - type Host struct { - Addr string `validate:"hostname_port"` - } - - type testInput struct { - data string - expected bool - } - testData := []testInput{ - {"bad..domain.name:234", false}, - {"extra.dot.com.", false}, - {"localhost:1234", true}, - {"192.168.1.1:1234", true}, - {":1234", true}, - {"domain.com:1334", true}, - {"this.domain.com:234", true}, - {"domain:75000", false}, - {"missing.port", false}, - } - for _, td := range testData { - h := Host{Addr: td.data} - v := New() - err := v.Struct(h) - if td.expected != (err == nil) { - t.Fatalf("Test failed for data: %v Error: %v", td.data, err) - } - } -} - -func TestLowercaseValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {`abcdefg`, true}, - {`Abcdefg`, false}, - {"", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "lowercase") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d lowercase failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d lowercase failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "lowercase" { - t.Fatalf("Index: %d lowercase failed Error: %s", i, errs) - } - } - } - } - - PanicMatches(t, func() { - _ = validate.Var(2, "lowercase") - }, "Bad field type int") -} - -func TestUppercaseValidation(t *testing.T) { - tests := []struct { - param string - expected bool - }{ - {`ABCDEFG`, true}, - {`aBCDEFG`, false}, - {"", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.param, "uppercase") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d uppercase failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d uppercase failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "uppercase" { - t.Fatalf("Index: %d uppercase failed Error: %s", i, errs) - } - } - } - } - - PanicMatches(t, func() { - _ = validate.Var(2, "uppercase") - }, "Bad field type int") - -} - -func TestDatetimeValidation(t *testing.T) { - tests := []struct { - value string `validate:"datetime=2006-01-02"` - tag string - expected bool - }{ - {"2008-02-01", `datetime=2006-01-02`, true}, - {"2008-Feb-01", `datetime=2006-01-02`, false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.value, test.tag) - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d datetime failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d datetime failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "datetime" { - t.Fatalf("Index: %d datetime failed Error: %s", i, errs) - } - } - } - } - - PanicMatches(t, func() { - _ = validate.Var(2, "datetime") - }, "Bad field type int") -} - -func TestIsIso3166Alpha2Validation(t *testing.T) { - tests := []struct { - value string `validate:"iso3166_1_alpha2"` - expected bool - }{ - {"PL", true}, - {"POL", false}, - {"AA", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.value, "iso3166_1_alpha2") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d iso3166_1_alpha2 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d iso3166_1_alpha2 failed Error: %s", i, errs) - } - } - } -} - -func TestIsIso3166Alpha3Validation(t *testing.T) { - tests := []struct { - value string `validate:"iso3166_1_alpha3"` - expected bool - }{ - {"POL", true}, - {"PL", false}, - {"AAA", false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.value, "iso3166_1_alpha3") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d iso3166_1_alpha3 failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d iso3166_1_alpha3 failed Error: %s", i, errs) - } - } - } -} - -func TestIsIso3166AlphaNumericValidation(t *testing.T) { - tests := []struct { - value int - expected bool - }{ - {248, true}, - {0, false}, - {1, false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.value, "iso3166_1_alpha_numeric") - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d iso3166_1_alpha_numeric failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d iso3166_1_alpha_numeric failed Error: %s", i, errs) - } - } - } - - PanicMatches(t, func() { - _ = validate.Var("1", "iso3166_1_alpha_numeric") - }, "Bad field type string") -} - -func TestTimeZoneValidation(t *testing.T) { - tests := []struct { - value string `validate:"timezone"` - tag string - expected bool - }{ - // systems may have different time zone database, some systems time zone are case insensitive - {"America/New_York", `timezone`, true}, - {"UTC", `timezone`, true}, - {"", `timezone`, false}, - {"Local", `timezone`, false}, - {"Unknown", `timezone`, false}, - } - - validate := New() - - for i, test := range tests { - - errs := validate.Var(test.value, test.tag) - - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d time zone failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d time zone failed Error: %s", i, errs) - } else { - val := getError(errs, "", "") - if val.Tag() != "timezone" { - t.Fatalf("Index: %d time zone failed Error: %s", i, errs) - } - } - } - } - - PanicMatches(t, func() { - _ = validate.Var(2, "timezone") - }, "Bad field type int") -} - -func TestDurationType(t *testing.T) { - tests := []struct { - name string - s interface{} // struct - success bool - }{ - { - name: "valid duration string pass", - s: struct { - Value time.Duration `validate:"gte=500ns"` - }{ - Value: time.Second, - }, - success: true, - }, - { - name: "valid duration int pass", - s: struct { - Value time.Duration `validate:"gte=500"` - }{ - Value: time.Second, - }, - success: true, - }, - } - - validate := New() - - for _, tc := range tests { - tc := tc - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - errs := validate.Struct(tc.s) - if tc.success { - Equal(t, errs, nil) - return - } - NotEqual(t, errs, nil) - }) - } -}