diff --git a/field_level.go b/field_level.go index 4ffb5f3..7c74151 100644 --- a/field_level.go +++ b/field_level.go @@ -9,7 +9,8 @@ type FieldLevel interface { // returns the top level struct, if any Top() reflect.Value - // returns the current fields parent struct, if any + // returns the current fields parent struct, if any or + // the comparison value if called 'VarWithValue' Parent() reflect.Value // returns current field for validation diff --git a/validator.go b/validator.go index 63d9082..3ef9636 100644 --- a/validator.go +++ b/validator.go @@ -33,14 +33,12 @@ type validate struct { // parent and current will be the same the first run of validateStruct func (v *validate) validateStruct(parent reflect.Value, current reflect.Value, typ reflect.Type, ns []byte, structNs []byte, ct *cTag) { - first := len(ns) == 0 - cs, ok := v.v.structCache.Get(typ) if !ok { cs = v.v.extractStructCache(current, typ.Name()) } - if first { + if len(ns) == 0 { ns = append(ns, cs.Name...) ns = append(ns, '.') @@ -154,7 +152,16 @@ func (v *validate) traverseField(parent reflect.Value, current reflect.Value, ns return } - v.validateStruct(current, current, typ, append(append(ns, cf.AltName...), '.'), append(append(structNs, cf.Name...), '.'), ct) + // if len == 0 then validating using 'Var' or 'VarWithValue' + // Var - doesn't make much sense to do it that way, should call 'Struct', but no harm... + // VarWithField - this allows for validating against each field withing the struct against a specific value + // pretty handly in certain situations + if len(ns) > 0 { + ns = append(append(ns, cf.AltName...), '.') + structNs = append(append(structNs, cf.Name...), '.') + } + + v.validateStruct(current, current, typ, ns, structNs, ct) return } } diff --git a/validator_instance.go b/validator_instance.go index 8ade9cc..1433259 100644 --- a/validator_instance.go +++ b/validator_instance.go @@ -182,6 +182,8 @@ func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{ for _, t := range types { v.customFuncs[reflect.TypeOf(t)] = fn } + + v.hasCustomFuncs = true } // Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified. @@ -351,6 +353,10 @@ func (v *Validate) StructExcept(s interface{}, fields ...string) (err error) { // var i int // validate.Var(i, "gt=1,lt=10") // +// WARNING: a struct can be passed for validation eg. time.Time is a struct or if you have a custom type and have registered +// a custom type handler, so must allow it; however unforseen validations will occur if trying to validate a struct +// that is meant to be passed to 'validate.Struct' +// // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. // validate Array, Slice and maps fields which may contain more than one error @@ -399,6 +405,10 @@ func (v *Validate) Var(field interface{}, tag string) (err error) { // s2 := "abcd" // validate.VarWithValue(s1, s2, "eqcsfield") // returns true // +// WARNING: a struct can be passed for validation eg. time.Time is a struct or if you have a custom type and have registered +// a custom type handler, so must allow it; however unforseen validations will occur if trying to validate a struct +// that is meant to be passed to 'validate.Struct' +// // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. // validate Array, Slice and maps fields which may contain more than one error diff --git a/validator_test.go b/validator_test.go index f90142f..d125068 100644 --- a/validator_test.go +++ b/validator_test.go @@ -1,10 +1,14 @@ package validator import ( + "database/sql" "database/sql/driver" + "encoding/json" + "fmt" "reflect" "strings" "testing" + "time" . "gopkg.in/go-playground/assert.v1" ) @@ -67,35 +71,33 @@ type TestString struct { 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"` -// } - -// var validate = New(&Config{TagName: "validate"}) +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) { @@ -139,57 +141,58 @@ type valuer struct { Name string } -// func (v valuer) Value() (driver.Value, error) { +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 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 + } -// if len(v.Name) == 0 { -// return nil, nil -// } + return v.Name, nil +} -// return v.Name, nil -// } +type MadeUpCustomType struct { + FirstName string + LastName string +} -// type MadeUpCustomType struct { -// FirstName string -// LastName string -// } +func ValidateCustomType(field reflect.Value) interface{} { -// func ValidateCustomType(field reflect.Value) interface{} { -// if cust, ok := field.Interface().(MadeUpCustomType); ok { + if cust, ok := field.Interface().(MadeUpCustomType); ok { -// if len(cust.FirstName) == 0 || len(cust.LastName) == 0 { -// return "" -// } + if len(cust.FirstName) == 0 || len(cust.LastName) == 0 { + return "" + } -// return cust.FirstName + " " + cust.LastName -// } + return cust.FirstName + " " + cust.LastName + } -// return "" -// } + return "" +} -// func OverrideIntTypeForSomeReason(field reflect.Value) interface{} { +func OverrideIntTypeForSomeReason(field reflect.Value) interface{} { -// if i, ok := field.Interface().(int); ok { -// if i == 1 { -// return "1" -// } + if i, ok := field.Interface().(int); ok { + if i == 1 { + return "1" + } -// if i == 2 { -// return "12" -// } -// } + if i == 2 { + return "12" + } + } -// return "" -// } + return "" +} -// type CustomMadeUpStruct struct { -// MadeUp MadeUpCustomType `validate:"required"` -// OverriddenInt int `validate:"gt=1"` -// } +type CustomMadeUpStruct struct { + MadeUp MadeUpCustomType `validate:"required"` + OverriddenInt int `validate:"gt=1"` +} func ValidateValuerType(field reflect.Value) interface{} { @@ -207,23 +210,23 @@ func ValidateValuerType(field reflect.Value) interface{} { 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 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"` @@ -630,5007 +633,5205 @@ func TestAliasTags(t *testing.T) { 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(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - -// return current.String() == field.String() -// } - -// PanicMatches(t, func() { val.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) }, validatorNotInitialized) -// PanicMatches(t, func() { val.RegisterValidation("something", fn) }, validatorNotInitialized) -// PanicMatches(t, func() { val.Field(ts.Test, "required") }, validatorNotInitialized) -// PanicMatches(t, func() { val.FieldWithValue("test", ts.Test, "required") }, validatorNotInitialized) -// PanicMatches(t, func() { val.Struct(ts) }, validatorNotInitialized) -// PanicMatches(t, func() { val.StructExcept(ts, "Test") }, validatorNotInitialized) -// PanicMatches(t, func() { val.StructPartial(ts, "Test") }, validatorNotInitialized) -// } - -// 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"}, -// }, -// }, -// } - -// // the following should all return no errors as everything is valid in -// // the default state -// errs := validate.StructPartial(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.StructExcept(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", "Required", "required") - -// errs = validate.StructExcept(tPartial, p2...) -// AssertError(t, errs, "TestPartial.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", "A", "required") - -// errs = validate.StructExcept(tPartial, p1...) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "TestPartial.Anonymous.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", "Test", "required") -// Equal(t, len(errs.(ValidationErrors)), 1) - -// errs = validate.StructPartial(tPartial, p2...) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "TestPartial.SubSlice[0].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", "Test", "required") - -// errs = validate.StructExcept(tPartial, p1...) -// Equal(t, len(errs.(ValidationErrors)), 2) -// AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required") -// AssertError(t, errs, "TestPartial.SubSlice[1].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", "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", "Test", "required") - -// errs = validate.StructExcept(tPartial, p2...) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "TestPartial.SubSlice[1].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", "Test", "required") - -// errs = validate.StructExcept(tPartial, p2...) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "required") - -// } - -// func TestCrossStructLteFieldValidation(t *testing.T) { - -// 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", "CreatedAt", "ltecsfield") -// AssertError(t, errs, "Test.String", "String", "ltecsfield") -// AssertError(t, errs, "Test.Int", "Int", "ltecsfield") -// AssertError(t, errs, "Test.Uint", "Uint", "ltecsfield") -// AssertError(t, errs, "Test.Float", "Float", "ltecsfield") -// AssertError(t, errs, "Test.Array", "Array", "ltecsfield") - -// errs = validate.VarWithValue(1, "", "ltecsfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "ltecsfield") - -// errs = validate.VarWithValue(test, now, "ltecsfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "ltecsfield") -// } - -// func TestCrossStructLtFieldValidation(t *testing.T) { - -// 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", "CreatedAt", "ltcsfield") -// AssertError(t, errs, "Test.String", "String", "ltcsfield") -// AssertError(t, errs, "Test.Int", "Int", "ltcsfield") -// AssertError(t, errs, "Test.Uint", "Uint", "ltcsfield") -// AssertError(t, errs, "Test.Float", "Float", "ltcsfield") -// AssertError(t, errs, "Test.Array", "Array", "ltcsfield") - -// errs = validate.VarWithValue(1, "", "ltcsfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "ltcsfield") - -// errs = validate.VarWithValue(test, now, "ltcsfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "ltcsfield") -// } - -// func TestCrossStructGteFieldValidation(t *testing.T) { - -// 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", "CreatedAt", "gtecsfield") -// AssertError(t, errs, "Test.String", "String", "gtecsfield") -// AssertError(t, errs, "Test.Int", "Int", "gtecsfield") -// AssertError(t, errs, "Test.Uint", "Uint", "gtecsfield") -// AssertError(t, errs, "Test.Float", "Float", "gtecsfield") -// AssertError(t, errs, "Test.Array", "Array", "gtecsfield") - -// errs = validate.VarWithValue(1, "", "gtecsfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtecsfield") - -// errs = validate.VarWithValue(test, now, "gtecsfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtecsfield") -// } - -// func TestCrossStructGtFieldValidation(t *testing.T) { - -// 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", "CreatedAt", "gtcsfield") -// AssertError(t, errs, "Test.String", "String", "gtcsfield") -// AssertError(t, errs, "Test.Int", "Int", "gtcsfield") -// AssertError(t, errs, "Test.Uint", "Uint", "gtcsfield") -// AssertError(t, errs, "Test.Float", "Float", "gtcsfield") -// AssertError(t, errs, "Test.Array", "Array", "gtcsfield") - -// errs = validate.VarWithValue(1, "", "gtcsfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtcsfield") - -// errs = validate.VarWithValue(test, now, "gtcsfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtcsfield") -// } - -// func TestCrossStructNeFieldValidation(t *testing.T) { - -// 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", "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") -// Equal(t, errs, nil) -// } - -// func TestCrossStructEqFieldValidation(t *testing.T) { - -// 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", "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", "CreatedAt", "eqcsfield") - -// test2.Inner = nil -// errs = validate.Struct(test2) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqcsfield") - -// errs = validate.VarWithValue(nil, 1, "eqcsfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "eqcsfield") -// } - -// func TestCrossNamespaceFieldValidation(t *testing.T) { - -// type SliceStruct struct { -// Name string -// } - -// type MapStruct 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) - -// current, kind, ok := validate.GetStructFieldOK(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 = validate.GetStructFieldOK(val, "Inner.Slice[1]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.CrazyNonExistantField") -// Equal(t, ok, false) - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.Slice[101]") -// Equal(t, ok, false) - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.Map[key3]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val3") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapMap[key2][key2-1]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapStructs[key2].Name") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "name2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapMapStruct[key3][key3-1].Name") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "name3") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceSlice[2][0]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "7") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceSliceStruct[2][1].Name") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "name8") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceMap[1][key5]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val5") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapSlice[key3][2]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "9") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt[2]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt8[2]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt16[2]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt32[2]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt64[2]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint[2]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint8[2]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint16[2]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint32[2]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint64[2]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapFloat32[3.03]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val3") - -// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapFloat64[2.02]") -// Equal(t, ok, true) -// Equal(t, kind, reflect.String) -// Equal(t, current.String(), "val2") - -// current, kind, ok = validate.GetStructFieldOK(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 = validate.GetStructFieldOK(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 = validate.GetStructFieldOK(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() { validate.GetStructFieldOK(reflect.ValueOf(1), "crazyinput") }, "Invalid field namespace") -// } - -// func TestExistsValidation(t *testing.T) { - -// jsonText := "{ \"truthiness2\": true }" - -// type Thing struct { -// Truthiness *bool `json:"truthiness" validate:"exists,required"` -// } - -// var ting Thing - -// err := json.Unmarshal([]byte(jsonText), &ting) -// Equal(t, err, nil) -// NotEqual(t, ting, nil) -// Equal(t, ting.Truthiness, nil) - -// errs := validate.Struct(ting) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "Thing.Truthiness", "Truthiness", "exists") +func TestNilValidator(t *testing.T) { -// jsonText = "{ \"truthiness\": true }" + type TestStruct struct { + Test string `validate:"required"` + } -// err = json.Unmarshal([]byte(jsonText), &ting) -// Equal(t, err, nil) -// NotEqual(t, ting, nil) -// Equal(t, ting.Truthiness, true) + ts := TestStruct{} -// errs = validate.Struct(ting) -// Equal(t, errs, nil) -// } + var val *Validate -// func TestSQLValue2Validation(t *testing.T) { + fn := func(fl FieldLevel) bool { -// config := &Config{ -// TagName: "validate", -// } + return fl.Parent().String() == fl.Field().String() + } -// validate := New(config) -// validate.RegisterCustomTypeFunc(ValidateValuerType, valuer{}, (*driver.Valuer)(nil), sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{}) -// validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) -// validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1) + 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") +} -// val := valuer{ -// Name: "", -// } +func TestStructPartial(t *testing.T) { -// errs := validate.Var(val, "required") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "required") + p1 := []string{ + "NoTag", + "Required", + } -// val.Name = "Valid Name" -// errs = validate.Var(val, "required") -// Equal(t, errs, nil) - -// val.Name = "errorme" - -// PanicMatches(t, func() { validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error") + p2 := []string{ + "SubSlice[0].Test", + "Sub", + "SubIgnore", + "Anonymous.A", + } -// type myValuer valuer + p3 := []string{ + "SubTest.Test", + } -// myVal := valuer{ -// Name: "", -// } + p4 := []string{ + "A", + } -// 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) + tPartial := &TestPartial{ + NoTag: "NoTag", + Required: "Required", -// 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", "MadeUp", "required") -// AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "gt") -// } - -// func TestSQLValueValidation(t *testing.T) { - -// validate := New(&Config{TagName: "validate"}) -// 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") - -// type myValuer valuer - -// 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", "MadeUp", "required") -// AssertError(t, errs, "CustomMadeUpStruct.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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// if val.Tag != "unix_addr" { -// t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs) -// } -// } -// } -// } -// } - -// func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) { - -// 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{} - -// errs := validate.Struct(test) -// Equal(t, errs, nil) -// } - -// func TestCommaAndPipeObfuscationValidation(t *testing.T) { -// s := "My Name Is, |joeybloggs|" + SubSlice: []*SubTest{ + { -// errs := validate.Var(s, "excludesall=0x2C") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "excludesall") + Test: "Required", + }, + { -// errs = validate.Var(s, "excludesall=0x7C") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "excludesall") -// } + Test: "Required", + }, + }, -// func TestBadKeyValidation(t *testing.T) { -// type Test struct { -// Name string `validate:"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"}, + }, + }, + } -// tst := &Test{ -// Name: "test", -// } + validate := New() -// PanicMatches(t, func() { validate.Struct(tst) }, "Undefined validation function on field Name") + // the following should all return no errors as everything is valid in + // the default state + errs := validate.StructPartial(tPartial, p1...) + Equal(t, errs, nil) -// type Test2 struct { -// Name string `validate:"required,,len=2"` -// } + errs = validate.StructPartial(tPartial, p2...) + Equal(t, errs, nil) -// tst2 := &Test2{ -// Name: "test", -// } + // 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) -// PanicMatches(t, func() { validate.Struct(tst2) }, "Invalid validation tag on field Name") -// } + errs = validate.StructExcept(tPartial, p1...) + Equal(t, errs, nil) -// func TestInterfaceErrValidation(t *testing.T) { + errs = validate.StructExcept(tPartial, p2...) + Equal(t, errs, nil) -// var v1 interface{} -// var v2 interface{} + // mod tParial for required feild and re-test making sure invalid fields are NOT required: + tPartial.Required = "" -// v2 = 1 -// v1 = v2 + errs = validate.StructExcept(tPartial, p1...) + Equal(t, errs, nil) -// errs := validate.Var(v1, "len=1") -// Equal(t, errs, nil) + errs = validate.StructPartial(tPartial, p2...) + Equal(t, errs, nil) -// errs = validate.Var(v2, "len=1") -// 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") -// type ExternalCMD struct { -// Userid string `json:"userid"` -// Action uint32 `json:"action"` -// Data interface{} `json:"data,omitempty" validate:"required"` -// } + errs = validate.StructExcept(tPartial, p2...) + AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required") -// s := &ExternalCMD{ -// Userid: "123456", -// Action: 10000, -// // Data: 1, -// } + // reset Required field, and set nested struct + tPartial.Required = "Required" + tPartial.Anonymous.A = "" -// errs = validate.Struct(s) -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 1) -// AssertError(t, errs, "ExternalCMD.Data", "Data", "required") + // will pass as unset feilds is not going to be tested + errs = validate.StructPartial(tPartial, p1...) + Equal(t, errs, nil) -// 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", "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", "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", "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]", "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", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].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", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.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]", "len") + errs = validate.StructExcept(tPartial, p2...) + Equal(t, errs, nil) -// errs = validate.Var(m, "len=2,dive,required") -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 1) -// AssertError(t, errs, "", "", "len") + // 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) -// arr := []interface{}{"ok", "", "ok"} + // 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.Var(arr, "len=3,dive,len=2") -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 1) -// AssertError(t, errs, "[1]", "[1]", "len") + errs = validate.StructExcept(tPartial, p1...) + NotEqual(t, errs, nil) + AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required") -// errs = validate.Var(arr, "len=2,dive,required") -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 1) -// AssertError(t, errs, "", "", "len") + // reset nested struct and unset struct in slice + tPartial.Anonymous.A = "Required" + tPartial.SubSlice[0].Test = "" -// type MyStruct struct { -// A, B string -// C interface{} -// } + // these will pass as unset item is NOT tested + errs = validate.StructPartial(tPartial, p1...) + Equal(t, errs, nil) -// var a MyStruct + errs = validate.StructExcept(tPartial, p2...) + Equal(t, errs, nil) -// a.A = "value" -// a.C = "nu" + // 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.Struct(a) -// Equal(t, errs, nil) -// } + 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) -// func TestMapDiveValidation(t *testing.T) { + // Unset second slice member concurrently to test dive behavior: + tPartial.SubSlice[1].Test = "" -// n := map[int]interface{}{0: nil} -// errs := validate.Var(n, "omitempty,required") -// Equal(t, errs, nil) + errs = validate.StructPartial(tPartial, p1...) + Equal(t, errs, nil) -// m := map[int]string{0: "ok", 3: "", 4: "ok"} + // 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.Var(m, "len=3,dive,required") -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 1) -// AssertError(t, errs, "[3]", "[3]", "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.Var(m, "len=2,dive,required") -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 1) -// AssertError(t, errs, "", "", "len") + 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") -// type Inner struct { -// Name string `validate:"required"` -// } + // reset struct in slice, and unset struct in slice in unset posistion + tPartial.SubSlice[0].Test = "Required" -// type TestMapStruct struct { -// Errs map[int]Inner `validate:"gt=0,dive"` -// } + // these will pass as the unset item is NOT tested + errs = validate.StructPartial(tPartial, p1...) + Equal(t, errs, nil) -// mi := map[int]Inner{0: {"ok"}, 3: {""}, 4: {"ok"}} + errs = validate.StructPartial(tPartial, p2...) + Equal(t, errs, nil) -// ms := &TestMapStruct{ -// Errs: mi, -// } + // 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.Struct(ms) -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 1) -// AssertError(t, errs, "TestMapStruct.Errs[3].Name", "Name", "required") + errs = validate.StructExcept(tPartial, p2...) + NotEqual(t, errs, nil) + AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required") -// // for full test coverage -// s := fmt.Sprint(errs.Error()) -// NotEqual(t, s, "") + tPartial.SubSlice[1].Test = "Required" -// type TestMapTimeStruct struct { -// Errs map[int]*time.Time `validate:"gt=0,dive,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) -// t1 := time.Now().UTC() + errs = validate.StructPartial(tPartial, p2...) + Equal(t, errs, nil) -// mta := map[int]*time.Time{0: &t1, 3: nil, 4: 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") -// mt := &TestMapTimeStruct{ -// Errs: mta, -// } + 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") -// errs = validate.Struct(mt) -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 2) -// AssertError(t, errs, "TestMapTimeStruct.Errs[3]", "Errs[3]", "required") -// AssertError(t, errs, "TestMapTimeStruct.Errs[4]", "Errs[4]", "required") +} -// type TestMapStructPtr struct { -// Errs map[int]*Inner `validate:"gt=0,dive,required"` -// } +func TestCrossStructLteFieldValidation(t *testing.T) { -// mip := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}} + type Inner struct { + CreatedAt *time.Time + String string + Int int + Uint uint + Float float64 + Array []string + } -// msp := &TestMapStructPtr{ -// Errs: mip, -// } + 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"` + } -// errs = validate.Struct(msp) -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 1) -// AssertError(t, errs, "TestMapStructPtr.Errs[3]", "Errs[3]", "required") + now := time.Now().UTC() + then := now.Add(time.Hour * 5) -// type TestMapStructPtr2 struct { -// Errs map[int]*Inner `validate:"gt=0,dive,omitempty,required"` -// } + inner := &Inner{ + CreatedAt: &then, + String: "abcd", + Int: 13, + Uint: 13, + Float: 1.13, + Array: []string{"val1", "val2"}, + } -// mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}} + test := &Test{ + Inner: inner, + CreatedAt: &now, + String: "abc", + Int: 12, + Uint: 12, + Float: 1.12, + Array: []string{"val1"}, + } -// msp2 := &TestMapStructPtr2{ -// Errs: mip2, -// } + validate := New() + errs := validate.Struct(test) + Equal(t, errs, nil) -// errs = validate.Struct(msp2) -// 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"} -// func TestArrayDiveValidation(t *testing.T) { + errs = validate.Struct(test) + Equal(t, errs, nil) -// arr := []string{"ok", "", "ok"} + after := now.Add(time.Hour * 10) -// errs := validate.Var(arr, "len=3,dive,required") -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 1) -// AssertError(t, errs, "[1]", "[1]", "required") + test.CreatedAt = &after + test.String = "abce" + test.Int = 14 + test.Uint = 14 + test.Float = 1.14 + test.Array = []string{"val1", "val2", "val3"} -// errs = validate.Var(arr, "len=2,dive,required") -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 1) -// AssertError(t, errs, "", "", "len") + 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.VarWithValue(1, "", "ltecsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "ltecsfield") -// type BadDive struct { -// Name string `validate:"dive"` -// } + // this test is for the WARNING about unforseen 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") +} -// bd := &BadDive{ -// Name: "TEST", -// } +func TestCrossStructLtFieldValidation(t *testing.T) { -// PanicMatches(t, func() { validate.Struct(bd) }, "dive error! can't dive on a non slice or map") + type Inner struct { + CreatedAt *time.Time + String string + Int int + Uint uint + Float float64 + Array []string + } -// type Test struct { -// Errs []string `validate:"gt=0,dive,required"` -// } + 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"` + } -// test := &Test{ -// Errs: []string{"ok", "", "ok"}, -// } + now := time.Now().UTC() + then := now.Add(time.Hour * 5) -// errs = validate.Struct(test) -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 1) -// AssertError(t, errs, "Test.Errs[1]", "Errs[1]", "required") + inner := &Inner{ + CreatedAt: &then, + String: "abcd", + Int: 13, + Uint: 13, + Float: 1.13, + Array: []string{"val1", "val2"}, + } -// 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]", "Errs[2]", "required") - -// type TestMultiDimensional struct { -// Errs [][]string `validate:"gt=0,dive,dive,required"` -// } + test := &Test{ + Inner: inner, + CreatedAt: &now, + String: "abc", + Int: 12, + Uint: 12, + Float: 1.12, + Array: []string{"val1"}, + } -// var errArray [][]string + validate := New() + errs := validate.Struct(test) + Equal(t, errs, nil) -// errArray = append(errArray, []string{"ok", "", ""}) -// errArray = append(errArray, []string{"ok", "", ""}) + test.CreatedAt = &then + test.String = "abcd" + test.Int = 13 + test.Uint = 13 + test.Float = 1.13 + test.Array = []string{"val1", "val2"} -// tm := &TestMultiDimensional{ -// Errs: errArray, -// } + 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") -// errs = validate.Struct(tm) -// NotEqual(t, errs, nil) -// Equal(t, len(errs.(ValidationErrors)), 4) -// AssertError(t, errs, "TestMultiDimensional.Errs[0][1]", "Errs[0][1]", "required") -// AssertError(t, errs, "TestMultiDimensional.Errs[0][2]", "Errs[0][2]", "required") -// AssertError(t, errs, "TestMultiDimensional.Errs[1][1]", "Errs[1][1]", "required") -// AssertError(t, errs, "TestMultiDimensional.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", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].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", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[2][1].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", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.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", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "Name", "required") -// AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[2][1].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]", "Errs[1][2]", "required") -// AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][1]", "Errs[2][1]", "required") -// AssertError(t, errs, "TestMultiDimensionalTimeTime.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]", "Errs[1][2]", "required") -// AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][1]", "Errs[2][1]", "required") -// AssertError(t, errs, "TestMultiDimensionalTimeTime2.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, -// } - -// 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", "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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// if val.Tag != "ssn" { -// t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) -// } -// } -// } -// } -// } - -// func TestLongitudeValidation(t *testing.T) { -// tests := []struct { -// param string -// expected bool -// }{ -// {"", false}, -// {"-180.000", true}, -// {"180.1", false}, -// {"+73.234", true}, -// {"+382.3811", false}, -// {"23.11111111", true}, -// } - -// 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 := errs.(ValidationErrors)[""] -// if val.Tag != "longitude" { -// t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) -// } -// } -// } -// } -// } - -// func TestLatitudeValidation(t *testing.T) { -// tests := []struct { -// param string -// expected bool -// }{ -// {"", false}, -// {"-90.000", true}, -// {"+90", true}, -// {"47.1231231", true}, -// {"+99.9", false}, -// {"108", false}, -// } - -// 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 := errs.(ValidationErrors)[""] -// if val.Tag != "latitude" { -// t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) -// } -// } -// } -// } -// } - -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// if val.Tag != "uuid" { -// t.Fatalf("Index: %d UUID 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } - -// 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}, -// } - -// 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}, -// } - -// 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}, -// } - -// 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}, -// } - -// 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}, -// } - -// 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 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", "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") -// Equal(t, errs, nil) - -// 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, -// } + // this test is for the WARNING about unforseen 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") +} -// errs = validate.Struct(sv2) -// Equal(t, errs, nil) -// } +func TestCrossStructGteFieldValidation(t *testing.T) { -// func TestIsNeValidation(t *testing.T) { - -// 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) + type Inner struct { + CreatedAt *time.Time + String string + Int int + Uint uint + Float float64 + Array []string + } -// errs = validate.Var(arr, "ne=2") -// Equal(t, errs, nil) - -// errs = validate.Var(arr, "ne=1") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "ne") + 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"` + } -// PanicMatches(t, func() { validate.Var(now, "ne=now") }, "Bad field type time.Time") -// } + now := time.Now().UTC() + then := now.Add(time.Hour * -5) -// func TestIsEqFieldValidation(t *testing.T) { + inner := &Inner{ + CreatedAt: &then, + String: "abcd", + Int: 13, + Uint: 13, + Float: 1.13, + Array: []string{"val1", "val2"}, + } -// 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") + test := &Test{ + Inner: inner, + CreatedAt: &now, + String: "abcde", + Int: 14, + Uint: 14, + Float: 1.14, + Array: []string{"val1", "val2", "val3"}, + } -// type Test struct { -// Start *time.Time `validate:"eqfield=End"` -// End *time.Time -// } - -// sv := &Test{ -// Start: &now, -// End: &now, -// } + validate := New() + errs := validate.Struct(test) + Equal(t, errs, nil) -// errs = validate.Struct(sv) -// 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"} -// now3 := time.Now().UTC() + errs = validate.Struct(test) + Equal(t, errs, nil) -// sv = &Test{ -// Start: &now, -// End: &now3, -// } + before := now.Add(time.Hour * -10) -// errs = validate.Struct(sv) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "Test.Start", "Start", "eqfield") + test.CreatedAt = &before + test.String = "abc" + test.Int = 12 + test.Uint = 12 + test.Float = 1.12 + test.Array = []string{"val1"} -// 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.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") -// errs = validate.VarWithValue(5, now, "eqfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "eqfield") + // this test is for the WARNING about unforseen 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 Test2 struct { -// Start *time.Time `validate:"eqfield=NonExistantField"` -// End *time.Time -// } +func TestCrossStructGtFieldValidation(t *testing.T) { -// sv2 := &Test2{ -// Start: &now, -// End: &now, -// } + type Inner struct { + CreatedAt *time.Time + String string + Int int + Uint uint + Float float64 + Array []string + } -// errs = validate.Struct(sv2) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "Test2.Start", "Start", "eqfield") + 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"` + } -// type Inner struct { -// Name string -// } + now := time.Now().UTC() + then := now.Add(time.Hour * -5) -// type TStruct struct { -// Inner *Inner -// CreatedAt *time.Time `validate:"eqfield=Inner"` -// } - -// inner := &Inner{ -// Name: "NAME", -// } + inner := &Inner{ + CreatedAt: &then, + String: "abcd", + Int: 13, + Uint: 13, + Float: 1.13, + Array: []string{"val1", "val2"}, + } -// test := &TStruct{ -// Inner: inner, -// CreatedAt: &now, -// } + test := &Test{ + Inner: inner, + CreatedAt: &now, + String: "abcde", + Int: 14, + Uint: 14, + Float: 1.14, + Array: []string{"val1", "val2", "val3"}, + } -// errs = validate.Struct(test) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqfield") -// } + validate := New() + errs := validate.Struct(test) + Equal(t, errs, nil) -// func TestIsEqValidation(t *testing.T) { + test.CreatedAt = &then + test.String = "abcd" + test.Int = 13 + test.Uint = 13 + test.Float = 1.13 + test.Array = []string{"val1", "val2"} -// var j uint64 -// var k float64 -// s := "abcd" -// i := 1 -// j = 1 -// k = 1.543 -// arr := []string{"test"} -// now := time.Now().UTC() + 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") -// errs := validate.Var(s, "eq=abcd") -// Equal(t, errs, nil) + // this test is for the WARNING about unforseen 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") +} -// errs = validate.Var(i, "eq=1") -// Equal(t, errs, nil) +func TestCrossStructNeFieldValidation(t *testing.T) { -// errs = validate.Var(j, "eq=1") -// Equal(t, errs, nil) + type Inner struct { + CreatedAt *time.Time + } -// errs = validate.Var(k, "eq=1.543") -// Equal(t, errs, nil) + type Test struct { + Inner *Inner + CreatedAt *time.Time `validate:"necsfield=Inner.CreatedAt"` + } -// errs = validate.Var(arr, "eq=1") -// Equal(t, errs, nil) + now := time.Now().UTC() + then := now.Add(time.Hour * 5) -// errs = validate.Var(arr, "eq=2") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "eq") + inner := &Inner{ + CreatedAt: &then, + } -// PanicMatches(t, func() { validate.Var(now, "eq=now") }, "Bad field type time.Time") -// } + test := &Test{ + Inner: inner, + CreatedAt: &now, + } -// func TestBase64Validation(t *testing.T) { + validate := New() + errs := validate.Struct(test) + Equal(t, errs, nil) -// s := "dW5pY29ybg==" + test.CreatedAt = &then -// errs := validate.Var(s, "base64") -// Equal(t, errs, nil) + 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") -// s = "dGhpIGlzIGEgdGVzdCBiYXNlNjQ=" -// errs = validate.Var(s, "base64") -// Equal(t, errs, nil) + errs = validate.VarWithValue(i2, i, "necsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "necsfield") -// s = "" -// errs = validate.Var(s, "base64") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "base64") + errs = validate.VarWithValue(j2, j, "necsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "necsfield") -// s = "dW5pY29ybg== foo bar" -// errs = validate.Var(s, "base64") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "base64") -// } + errs = validate.VarWithValue(k2, k, "necsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "necsfield") -// func TestNoStructLevelValidation(t *testing.T) { + errs = validate.VarWithValue(arr2, arr, "necsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "necsfield") -// type Inner struct { -// Test string `validate:"len=5"` -// } + errs = validate.VarWithValue(now2, now, "necsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "necsfield") -// type Outer struct { -// InnerStruct *Inner `validate:"required,nostructlevel"` -// } + errs = validate.VarWithValue(arr3, arr, "necsfield") + Equal(t, errs, nil) -// outer := &Outer{ -// InnerStruct: nil, -// } + type SInner struct { + Name string + } -// errs := validate.Struct(outer) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required") + type TStruct struct { + Inner *SInner + CreatedAt *time.Time `validate:"necsfield=Inner"` + } -// inner := &Inner{ -// Test: "1234", -// } + sinner := &SInner{ + Name: "NAME", + } -// outer = &Outer{ -// InnerStruct: inner, -// } + test2 := &TStruct{ + Inner: sinner, + CreatedAt: &now, + } -// errs = validate.Struct(outer) -// Equal(t, errs, nil) -// } + errs = validate.Struct(test2) + Equal(t, errs, nil) -// func TestStructOnlyValidation(t *testing.T) { + test2.Inner = nil + errs = validate.Struct(test2) + Equal(t, errs, nil) -// type Inner struct { -// Test string `validate:"len=5"` -// } + errs = validate.VarWithValue(nil, 1, "necsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "necsfield") +} -// type Outer struct { -// InnerStruct *Inner `validate:"required,structonly"` -// } +func TestCrossStructEqFieldValidation(t *testing.T) { -// outer := &Outer{ -// InnerStruct: nil, -// } + type Inner struct { + CreatedAt *time.Time + } -// errs := validate.Struct(outer) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required") + type Test struct { + Inner *Inner + CreatedAt *time.Time `validate:"eqcsfield=Inner.CreatedAt"` + } -// inner := &Inner{ -// Test: "1234", -// } + now := time.Now().UTC() -// outer = &Outer{ -// InnerStruct: inner, -// } + inner := &Inner{ + CreatedAt: &now, + } -// errs = validate.Struct(outer) -// Equal(t, errs, nil) -// } + test := &Test{ + Inner: inner, + CreatedAt: &now, + } -// func TestGtField(t *testing.T) { + validate := New() + errs := validate.Struct(test) + Equal(t, errs, nil) -// type TimeTest struct { -// Start *time.Time `validate:"required,gt"` -// End *time.Time `validate:"required,gt,gtfield=Start"` -// } + newTime := time.Now().UTC() + test.CreatedAt = &newTime -// now := time.Now() -// start := now.Add(time.Hour * 24) -// end := start.Add(time.Hour * 24) + 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) -// timeTest := &TimeTest{ -// Start: &start, -// End: &end, -// } + errs = validate.VarWithValue(i2, i, "eqcsfield") + Equal(t, errs, nil) -// errs := validate.Struct(timeTest) -// Equal(t, errs, nil) + errs = validate.VarWithValue(j2, j, "eqcsfield") + Equal(t, errs, nil) -// timeTest = &TimeTest{ -// Start: &end, -// End: &start, -// } + errs = validate.VarWithValue(k2, k, "eqcsfield") + Equal(t, errs, nil) -// errs = validate.Struct(timeTest) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "TimeTest.End", "End", "gtfield") + errs = validate.VarWithValue(arr2, arr, "eqcsfield") + Equal(t, errs, nil) -// errs = validate.VarWithValue(&start, &end, "gtfield") -// Equal(t, errs, nil) + errs = validate.VarWithValue(now2, now, "eqcsfield") + Equal(t, errs, nil) -// errs = validate.VarWithValue(&end, &start, "gtfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtfield") + errs = validate.VarWithValue(arr3, arr, "eqcsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "eqcsfield") -// errs = validate.VarWithValue(&timeTest, &end, "gtfield") -// NotEqual(t, errs, nil) + type SInner struct { + Name string + } -// errs = validate.VarWithValue("test", "test bigger", "gtfield") -// Equal(t, errs, nil) + type TStruct struct { + Inner *SInner + CreatedAt *time.Time `validate:"eqcsfield=Inner"` + } -// type IntTest struct { -// Val1 int `validate:"required"` -// Val2 int `validate:"required,gtfield=Val1"` -// } + sinner := &SInner{ + Name: "NAME", + } -// intTest := &IntTest{ -// Val1: 1, -// Val2: 5, -// } + test2 := &TStruct{ + Inner: sinner, + CreatedAt: &now, + } -// errs = validate.Struct(intTest) -// Equal(t, errs, nil) + errs = validate.Struct(test2) + NotEqual(t, errs, nil) + AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield") -// intTest = &IntTest{ -// Val1: 5, -// Val2: 1, -// } + test2.Inner = nil + errs = validate.Struct(test2) + NotEqual(t, errs, nil) + AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield") -// errs = validate.Struct(intTest) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "IntTest.Val2", "Val2", "gtfield") + errs = validate.VarWithValue(nil, 1, "eqcsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "eqcsfield") +} -// errs = validate.VarWithValue(int(1), int(5), "gtfield") -// Equal(t, errs, nil) +func TestCrossNamespaceFieldValidation(t *testing.T) { -// errs = validate.VarWithValue(int(5), int(1), "gtfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtfield") + type SliceStruct struct { + Name string + } -// type UIntTest struct { -// Val1 uint `validate:"required"` -// Val2 uint `validate:"required,gtfield=Val1"` -// } + type MapStruct struct { + Name string + } -// uIntTest := &UIntTest{ -// Val1: 1, -// Val2: 5, -// } + 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 + } -// errs = validate.Struct(uIntTest) -// Equal(t, errs, nil) + type Test struct { + Inner *Inner + CreatedAt *time.Time + } -// uIntTest = &UIntTest{ -// Val1: 5, -// Val2: 1, -// } + 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"}, + } -// errs = validate.Struct(uIntTest) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "UIntTest.Val2", "Val2", "gtfield") + test := &Test{ + Inner: inner, + CreatedAt: &now, + } -// errs = validate.VarWithValue(uint(1), uint(5), "gtfield") -// Equal(t, errs, nil) + val := reflect.ValueOf(test) -// errs = validate.VarWithValue(uint(5), uint(1), "gtfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtfield") + vd := New() + v := &validate{ + v: vd, + } -// 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", "Val2", "gtfield") - -// errs = validate.VarWithValue(float32(1), float32(5), "gtfield") -// Equal(t, errs, nil) + 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, kind, ok = v.getStructFieldOKInternal(val, "Inner.CrazyNonExistantField") + Equal(t, ok, false) + + current, kind, 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"}}, + } -// errs = validate.VarWithValue(float32(5), float32(1), "gtfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtfield") + test = &Test{ + Inner: inner, + CreatedAt: nil, + } -// 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", "End", "gtfield") -// } - -// func TestLtField(t *testing.T) { - -// 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", "Start", "ltfield") - -// errs = validate.VarWithValue(&end, &start, "ltfield") -// Equal(t, errs, nil) - -// errs = validate.VarWithValue(&start, &end, "ltfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "ltfield") - -// errs = validate.VarWithValue(timeTest, &end, "ltfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "ltfield") - -// errs = validate.VarWithValue("test", "tes", "ltfield") -// Equal(t, errs, nil) - -// 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", "Val2", "ltfield") - -// errs = validate.VarWithValue(int(5), int(1), "ltfield") -// Equal(t, errs, nil) - -// errs = validate.VarWithValue(int(1), int(5), "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", "Val2", "ltfield") - -// errs = validate.VarWithValue(uint(5), uint(1), "ltfield") -// Equal(t, errs, nil) - -// errs = validate.VarWithValue(uint(1), uint(5), "ltfield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "ltfield") + val = reflect.ValueOf(test) -// 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", "Val2", "ltfield") - -// errs = validate.VarWithValue(float32(5), float32(1), "ltfield") -// Equal(t, errs, nil) - -// errs = validate.VarWithValue(float32(1), float32(5), "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", "End", "ltfield") -// } - -// func TestLteField(t *testing.T) { - -// 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", "Start", "ltefield") + 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) -// errs = validate.VarWithValue(&end, &start, "ltefield") -// Equal(t, errs, nil) - -// errs = validate.VarWithValue(&start, &end, "ltefield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "ltefield") - -// errs = validate.VarWithValue(timeTest, &end, "ltefield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "ltefield") - -// errs = validate.VarWithValue("test", "tes", "ltefield") -// Equal(t, errs, nil) - -// errs = validate.VarWithValue("test", "test", "ltefield") -// Equal(t, errs, nil) - -// 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", "Val2", "ltefield") - -// errs = validate.VarWithValue(int(5), int(1), "ltefield") -// Equal(t, errs, nil) - -// errs = validate.VarWithValue(int(1), int(5), "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", "Val2", "ltefield") - -// errs = validate.VarWithValue(uint(5), uint(1), "ltefield") -// Equal(t, errs, nil) + 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) -// errs = validate.VarWithValue(uint(1), uint(5), "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) + PanicMatches(t, func() { v.getStructFieldOKInternal(reflect.ValueOf(1), "crazyinput") }, "Invalid field namespace") +} -// floatTest = &FloatTest{ -// Val1: 1, -// Val2: 5, -// } - -// errs = validate.Struct(floatTest) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "FloatTest.Val2", "Val2", "ltefield") - -// errs = validate.VarWithValue(float32(5), float32(1), "ltefield") -// Equal(t, errs, nil) +func TestExistsValidation(t *testing.T) { -// errs = validate.VarWithValue(float32(1), float32(5), "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", "End", "ltefield") -// } - -// func TestGteField(t *testing.T) { - -// 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", "End", "gtefield") + jsonText := "{ \"truthiness2\": true }" -// errs = validate.VarWithValue(&start, &end, "gtefield") -// Equal(t, errs, nil) - -// errs = validate.VarWithValue(&end, &start, "gtefield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtefield") - -// errs = validate.VarWithValue(timeTest, &start, "gtefield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtefield") - -// errs = validate.VarWithValue("test", "test", "gtefield") -// Equal(t, errs, nil) - -// errs = validate.VarWithValue("test", "test bigger", "gtefield") -// Equal(t, errs, nil) - -// 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", "Val2", "gtefield") - -// errs = validate.VarWithValue(int(1), int(5), "gtefield") -// Equal(t, errs, nil) - -// errs = validate.VarWithValue(int(5), int(1), "gtefield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtefield") + type Thing struct { + Truthiness *bool `json:"truthiness" validate:"required"` + } -// type UIntTest struct { -// Val1 uint `validate:"required"` -// Val2 uint `validate:"required,gtefield=Val1"` -// } + var ting Thing -// uIntTest := &UIntTest{ -// Val1: 1, -// Val2: 5, -// } + err := json.Unmarshal([]byte(jsonText), &ting) + Equal(t, err, nil) + NotEqual(t, ting, nil) + Equal(t, ting.Truthiness, nil) -// errs = validate.Struct(uIntTest) -// Equal(t, errs, nil) + validate := New() + errs := validate.Struct(ting) + NotEqual(t, errs, nil) + AssertError(t, errs, "Thing.Truthiness", "Thing.Truthiness", "Truthiness", "Truthiness", "required") -// uIntTest = &UIntTest{ -// Val1: 5, -// Val2: 1, -// } + jsonText = "{ \"truthiness\": true }" -// errs = validate.Struct(uIntTest) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "UIntTest.Val2", "Val2", "gtefield") + err = json.Unmarshal([]byte(jsonText), &ting) + Equal(t, err, nil) + NotEqual(t, ting, nil) + Equal(t, ting.Truthiness, true) -// errs = validate.VarWithValue(uint(1), uint(5), "gtefield") -// Equal(t, errs, nil) + errs = validate.Struct(ting) + Equal(t, errs, nil) +} -// errs = validate.VarWithValue(uint(5), uint(1), "gtefield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtefield") +func TestSQLValue2Validation(t *testing.T) { -// type FloatTest struct { -// Val1 float64 `validate:"required"` -// Val2 float64 `validate:"required,gtefield=Val1"` -// } + 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) -// floatTest := &FloatTest{ -// Val1: 1, -// Val2: 5, -// } + val := valuer{ + Name: "", + } -// errs = validate.Struct(floatTest) -// Equal(t, errs, nil) + errs := validate.Var(val, "required") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "required") -// floatTest = &FloatTest{ -// Val1: 5, -// Val2: 1, -// } + val.Name = "Valid Name" + errs = validate.Var(val, "required") + Equal(t, errs, nil) -// errs = validate.Struct(floatTest) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "FloatTest.Val2", "Val2", "gtefield") + val.Name = "errorme" -// errs = validate.VarWithValue(float32(1), float32(5), "gtefield") -// Equal(t, errs, nil) + PanicMatches(t, func() { validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error") -// errs = validate.VarWithValue(float32(5), float32(1), "gtefield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtefield") + type myValuer valuer -// errs = validate.VarWithValue(nil, 1, "gtefield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtefield") + myVal := valuer{ + Name: "", + } -// errs = validate.VarWithValue(5, "T", "gtefield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtefield") + errs = validate.Var(myVal, "required") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "required") -// errs = validate.VarWithValue(5, start, "gtefield") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gtefield") + cust := MadeUpCustomType{ + FirstName: "Joey", + LastName: "Bloggs", + } -// type TimeTest2 struct { -// Start *time.Time `validate:"required"` -// End *time.Time `validate:"required,gtefield=NonExistantField"` -// } + c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2} -// timeTest2 := &TimeTest2{ -// Start: &start, -// End: &end, -// } + errs = validate.Struct(c) + Equal(t, errs, nil) -// errs = validate.Struct(timeTest2) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "TimeTest2.End", "End", "gtefield") -// } + c.MadeUp.FirstName = "" + c.OverriddenInt = 1 -// func TestValidateByTagAndValue(t *testing.T) { + 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") +} -// val := "test" -// field := "test" -// errs := validate.VarWithValue(val, field, "required") -// Equal(t, errs, nil) +func TestSQLValueValidation(t *testing.T) { -// fn := func(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { + validate := New() + validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{}) + validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) + validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1) -// return current.String() == field.String() -// } + val := valuer{ + Name: "", + } -// validate.RegisterValidation("isequaltestfunc", fn) + errs := validate.Var(val, "required") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "required") -// errs = validate.VarWithValue(val, field, "isequaltestfunc") -// Equal(t, errs, nil) + val.Name = "Valid Name" + errs = validate.Var(val, "required") + Equal(t, errs, nil) -// val = "unequal" + val.Name = "errorme" -// errs = validate.VarWithValue(val, field, "isequaltestfunc") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "isequaltestfunc") -// } + PanicMatches(t, func() { errs = validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error") -// func TestAddFunctions(t *testing.T) { + type myValuer valuer -// fn := func(v *Validate, topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { + myVal := valuer{ + Name: "", + } -// return true -// } + errs = validate.Var(myVal, "required") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "required") -// config := &Config{ -// TagName: "validateme", -// } + cust := MadeUpCustomType{ + FirstName: "Joey", + LastName: "Bloggs", + } -// validate := New(config) + c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2} -// errs := validate.RegisterValidation("new", fn) -// Equal(t, errs, nil) + errs = validate.Struct(c) + Equal(t, errs, nil) -// errs = validate.RegisterValidation("", fn) -// NotEqual(t, errs, nil) + c.MadeUp.FirstName = "" + c.OverriddenInt = 1 -// validate.RegisterValidation("new", nil) -// NotEqual(t, errs, nil) + 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") +} -// errs = validate.RegisterValidation("new", fn) -// Equal(t, errs, nil) +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}, + } -// 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") -// } + validate := New() -// func TestChangeTag(t *testing.T) { + 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) + } + } + } + } +} -// config := &Config{ -// TagName: "val", -// } -// validate := New(config) +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}, + } -// type Test struct { -// Name string `val:"len=4"` -// } -// s := &Test{ -// Name: "TEST", -// } + validate := New() -// errs := validate.Struct(s) -// Equal(t, errs, nil) -// } + 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 TestUnexposedStruct(t *testing.T) { +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}, + } -// type Test struct { -// Name string -// unexposed struct { -// A string `validate:"required"` -// } -// } + validate := New() -// s := &Test{ -// Name: "TEST", -// } + 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) + } + } + } + } +} -// errs := validate.Struct(s) -// Equal(t, errs, nil) -// } +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}, + } -// func TestBadParams(t *testing.T) { + validate := New() -// i := 1 -// errs := validate.Var(i, "-") -// Equal(t, errs, nil) + 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) + } + } + } + } +} -// 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") +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}, + } -// var ui uint = 1 -// PanicMatches(t, func() { validate.Var(ui, "len=a") }, "strconv.ParseUint: parsing \"a\": invalid syntax") + validate := New() -// f := 1.23 -// PanicMatches(t, func() { validate.Var(f, "len=a") }, "strconv.ParseFloat: parsing \"a\": invalid syntax") -// } + 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 TestLength(t *testing.T) { +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}, + } -// i := true -// PanicMatches(t, func() { validate.Var(i, "len") }, "Bad field type bool") -// } + validate := New() -// func TestIsGt(t *testing.T) { + 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) + } + } + } + } +} -// myMap := map[string]string{} -// errs := validate.Var(myMap, "gt=0") -// NotEqual(t, errs, nil) +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}, + } -// f := 1.23 -// errs = validate.Var(f, "gt=5") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gt") + validate := New() -// var ui uint = 5 -// errs = validate.Var(ui, "gt=10") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gt") + 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) + } + } + } + } +} -// i := true -// PanicMatches(t, func() { validate.Var(i, "gt") }, "Bad field type bool") +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}, + } -// tm := time.Now().UTC() -// tm = tm.Add(time.Hour * 24) + validate := New() -// errs = validate.Var(tm, "gt") -// Equal(t, errs, nil) + 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) + } + } + } + } +} -// t2 := time.Now().UTC() +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}, + } -// errs = validate.Var(t2, "gt") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "gt") + validate := New() -// type Test struct { -// Now *time.Time `validate:"gt"` -// } -// s := &Test{ -// Now: &tm, -// } + 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) + } + } + } + } +} -// errs = validate.Struct(s) -// Equal(t, errs, nil) +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 v1 interface{} + var v2 interface{} + + v2 = 1 + v1 = 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) +} + +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 string + expected bool + }{ + {"", false}, + {"-180.000", true}, + {"180.1", false}, + {"+73.234", true}, + {"+382.3811", false}, + {"23.11111111", true}, + } + + 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 Latitude failed Error: %s", i, errs) + } + } + } + } +} + +func TestLatitudeValidation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", false}, + {"-90.000", true}, + {"+90", true}, + {"47.1231231", true}, + {"+99.9", false}, + {"108", 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) + } + } + } + } +} + +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}, + } + + 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 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) { + + 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) +} + +func TestIsNeValidation(t *testing.T) { + + 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") +} + +func TestIsEqFieldValidation(t *testing.T) { + + 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") +} + +func TestIsEqValidation(t *testing.T) { + + 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") +} + +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 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) +} + +func TestGtField(t *testing.T) { + + 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) + + 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") +} + +func TestLtField(t *testing.T) { + + 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) + + 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 TestLteField(t *testing.T) { + + 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) + + 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) { + + 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) + + 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() + } + + validate.RegisterValidation("isequaltestfunc", fn) + + 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 + } + + validate := New() + + errs := validate.RegisterValidation("new", fn) + Equal(t, errs, nil) + + errs = validate.RegisterValidation("", fn) + NotEqual(t, errs, nil) + + validate.RegisterValidation("new", nil) + NotEqual(t, errs, nil) + + errs = validate.RegisterValidation("new", fn) + 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", + } + + 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) { + + 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() + + 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") +} + +func TestIsGte(t *testing.T) { + + 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() + + 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") +} + +func TestIsLt(t *testing.T) { + + 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() + + 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") +} + +func TestIsLte(t *testing.T) { + + validate := New() + + i := true + PanicMatches(t, func() { validate.Var(i, "lte") }, "Bad field type bool") + + t1 := time.Now().UTC() + + 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) +} + +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") + + 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 = "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 on field") +} + +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 + 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 = "" + 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") + + 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 = "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") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "number") +} + +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") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "numeric") +} + +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") +} -// s = &Test{ -// Now: &t2, -// } +func TestAlpha(t *testing.T) { -// errs = validate.Struct(s) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "Test.Now", "Now", "gt") -// } + validate := New() -// func TestIsGte(t *testing.T) { + s := "abcd" + errs := validate.Var(s, "alpha") + Equal(t, errs, nil) -// i := true -// PanicMatches(t, func() { validate.Var(i, "gte") }, "Bad field type bool") + s = "abc®" + errs = validate.Var(s, "alpha") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "alpha") -// t1 := time.Now().UTC() -// t1 = t1.Add(time.Hour * 24) + s = "abc÷" + errs = validate.Var(s, "alpha") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "alpha") -// errs := validate.Var(t1, "gte") -// Equal(t, errs, nil) + s = "abc1" + errs = validate.Var(s, "alpha") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "alpha") -// t2 := time.Now().UTC() + errs = validate.Var(1, "alpha") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "alpha") -// 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, -// } +func TestStructStringValidation(t *testing.T) { -// errs = validate.Struct(s) -// Equal(t, errs, nil) + validate := New() -// s = &Test{ -// Now: &t2, -// } + 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(s) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "Test.Now", "Now", "gte") -// } + errs := validate.Struct(tSuccess) + Equal(t, errs, nil) -// func TestIsLt(t *testing.T) { + 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", + }, + } -// myMap := map[string]string{} -// errs := validate.Var(myMap, "lt=0") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "lt") + errs = validate.Struct(tFail) -// f := 1.23 -// errs = validate.Var(f, "lt=0") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "lt") + // Assert Top Level + NotEqual(t, errs, nil) + Equal(t, len(errs.(ValidationErrors)), 13) -// 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() - -// 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", "Now", "lt") -// } - -// func TestIsLte(t *testing.T) { - -// i := true -// PanicMatches(t, func() { validate.Var(i, "lte") }, "Bad field type bool") - -// t1 := time.Now().UTC() - -// 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) -// } - -// 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}, -// } -// 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 := errs.(ValidationErrors)[""] -// 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}, -// } -// 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 := errs.(ValidationErrors)[""] -// 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) { -// 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") - -// 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 = "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 on field") -// } - -// func TestHsla(t *testing.T) { - -// 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 -// validate.Var(i, "hsla") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "hsla") -// } - -// func TestHsl(t *testing.T) { - -// 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) { - -// 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) { - -// 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) { - -// 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 = "" -// 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") - -// i := true -// errs = validate.Var(i, "email") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "email") -// } - -// func TestHexColor(t *testing.T) { - -// 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) { - -// s := "ff0044" -// 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) { - -// 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") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "number") -// } - -// func TestNumeric(t *testing.T) { - -// 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") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "numeric") -// } - -// func TestAlphaNumeric(t *testing.T) { - -// 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) { - -// 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") - -// errs = validate.Var(1, "alpha") -// NotEqual(t, errs, nil) -// AssertError(t, errs, "", "", "alpha") - -// } - -// func TestStructStringValidation(t *testing.T) { - -// 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", "Required", "required") -// AssertError(t, errs, "TestString.Len", "Len", "len") -// AssertError(t, errs, "TestString.Min", "Min", "min") -// AssertError(t, errs, "TestString.Max", "Max", "max") -// AssertError(t, errs, "TestString.MinMax", "MinMax", "min") -// AssertError(t, errs, "TestString.Lt", "Lt", "lt") -// AssertError(t, errs, "TestString.Lte", "Lte", "lte") -// AssertError(t, errs, "TestString.Gt", "Gt", "gt") -// AssertError(t, errs, "TestString.Gte", "Gte", "gte") -// AssertError(t, errs, "TestString.OmitEmpty", "OmitEmpty", "max") - -// // Nested Struct Field Errs -// AssertError(t, errs, "TestString.Anonymous.A", "A", "required") -// AssertError(t, errs, "TestString.Sub.Test", "Test", "required") -// AssertError(t, errs, "TestString.Iface.F", "F", "len") -// } + // 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) { @@ -5696,229 +5897,264 @@ func TestStructInt32Validation(t *testing.T) { AssertError(t, errs, "TestInt32.OmitEmpty", "TestInt32.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") } -// func TestStructUint64Validation(t *testing.T) { - -// 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", "Required", "required") -// AssertError(t, errs, "TestUint64.Len", "Len", "len") -// AssertError(t, errs, "TestUint64.Min", "Min", "min") -// AssertError(t, errs, "TestUint64.Max", "Max", "max") -// AssertError(t, errs, "TestUint64.MinMax", "MinMax", "min") -// AssertError(t, errs, "TestUint64.OmitEmpty", "OmitEmpty", "max") -// } - -// func TestStructFloat64Validation(t *testing.T) { - -// 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", "Required", "required") -// AssertError(t, errs, "TestFloat64.Len", "Len", "len") -// AssertError(t, errs, "TestFloat64.Min", "Min", "min") -// AssertError(t, errs, "TestFloat64.Max", "Max", "max") -// AssertError(t, errs, "TestFloat64.MinMax", "MinMax", "min") -// AssertError(t, errs, "TestFloat64.OmitEmpty", "OmitEmpty", "max") -// } - -// func TestStructSliceValidation(t *testing.T) { - -// 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", "Required", "required") -// AssertError(t, errs, "TestSlice.Len", "Len", "len") -// AssertError(t, errs, "TestSlice.Min", "Min", "min") -// AssertError(t, errs, "TestSlice.Max", "Max", "max") -// AssertError(t, errs, "TestSlice.MinMax", "MinMax", "min") -// AssertError(t, errs, "TestSlice.OmitEmpty", "OmitEmpty", "max") -// } - -// func TestInvalidStruct(t *testing.T) { -// s := &SubTest{ -// Test: "1", -// } - -// PanicMatches(t, func() { validate.Struct(s.Test) }, "value passed for validation is not a struct") -// } - -// func TestInvalidValidatorFunction(t *testing.T) { -// s := &SubTest{ -// Test: "1", -// } - -// PanicMatches(t, func() { validate.Var(s.Test, "zzxxBadFunction") }, "Undefined validation function on field") -// } - -// func TestCustomFieldName(t *testing.T) { -// 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{} - -// errs := New(&Config{TagName: "validate", FieldNameTag: "schema"}).Struct(a).(ValidationErrors) -// NotEqual(t, errs, nil) -// Equal(t, len(errs), 4) -// Equal(t, errs["A.B"].Name, "b") -// Equal(t, errs["A.C"].Name, "c") -// Equal(t, errs["A.D"].Name, "d") -// Equal(t, errs["A.E"].Name, "E") - -// errs = New(&Config{TagName: "validate"}).Struct(a).(ValidationErrors) -// NotEqual(t, errs, nil) -// Equal(t, len(errs), 4) -// Equal(t, errs["A.B"].Name, "B") -// Equal(t, errs["A.C"].Name, "C") -// Equal(t, errs["A.D"].Name, "D") -// Equal(t, errs["A.E"].Name, "E") -// } - -// func TestMutipleRecursiveExtractStructCache(t *testing.T) { - -// type Recursive struct { -// Field *string `validate:"exists,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) { - -// 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", "MyInt", "gte") - -// errs = validate.Struct(t2) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "Test.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", "MyInt", "gte") - -// errs = validate.Struct(ti2) -// NotEqual(t, errs, nil) -// AssertError(t, errs, "TestIface.MyInt", "MyInt", "lte") - -// errs = validate.Struct(ti3) -// Equal(t, errs, nil) -// } +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") +} + +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)") +} + +func TestInvalidValidatorFunction(t *testing.T) { + + validate := New() + + s := &SubTest{ + Test: "1", + } + + PanicMatches(t, func() { validate.Var(s.Test, "zzxxBadFunction") }, "Undefined validation function 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) +}