diff --git a/baked_in.go b/baked_in.go index c749266..c735046 100644 --- a/baked_in.go +++ b/baked_in.go @@ -14,14 +14,14 @@ import ( // defines a common or complex set of validation(s) to simplify // adding validation to structs. i.e. set key "_ageok" and the tags // are "gt=0,lte=130" or key "_preferredname" and tags "omitempty,gt=0,lte=60" -var BakedInAliasValidators = map[string]string{ +var bakedInAliasValidators = map[string]string{ "iscolor": "hexcolor|rgb|rgba|hsl|hsla", } // BakedInValidators is the default map of ValidationFunc // you can add, remove or even replace items to suite your needs, // or even disregard and use your own map if so desired. -var BakedInValidators = map[string]Func{ +var bakedInValidators = map[string]Func{ "required": hasValue, "len": hasLengthOf, "min": hasMinOf, diff --git a/benchmarks_test.go b/benchmarks_test.go index 284750d..3a2a1fc 100644 --- a/benchmarks_test.go +++ b/benchmarks_test.go @@ -32,11 +32,6 @@ func BenchmarkFieldDiveFailure(b *testing.B) { func BenchmarkFieldCustomTypeSuccess(b *testing.B) { - // customTypes := map[reflect.Type]CustomTypeFunc{} - // customTypes[reflect.TypeOf((*sql.Valuer)(nil))] = ValidateValuerType - // customTypes[reflect.TypeOf(valuer{})] = ValidateValuerType - - validate := New(Config{TagName: "validate"}) validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{ @@ -50,11 +45,7 @@ func BenchmarkFieldCustomTypeSuccess(b *testing.B) { func BenchmarkFieldCustomTypeFailure(b *testing.B) { - // customTypes := map[reflect.Type]CustomTypeFunc{} - // customTypes[reflect.TypeOf((*sql.Valuer)(nil))] = ValidateValuerType - // customTypes[reflect.TypeOf(valuer{})] = ValidateValuerType - - validate := New(Config{TagName: "validate"}) + // validate := New(Config{TagName: "validate"}) validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{} @@ -78,11 +69,6 @@ func BenchmarkFieldOrTagFailure(b *testing.B) { func BenchmarkStructSimpleCustomTypeSuccess(b *testing.B) { - // customTypes := map[reflect.Type]CustomTypeFunc{} - // customTypes[reflect.TypeOf((*sql.Valuer)(nil))] = ValidateValuerType - // customTypes[reflect.TypeOf(valuer{})] = ValidateValuerType - - validate := New(Config{TagName: "validate"}) validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{ @@ -103,11 +89,6 @@ func BenchmarkStructSimpleCustomTypeSuccess(b *testing.B) { func BenchmarkStructSimpleCustomTypeFailure(b *testing.B) { - // customTypes := map[reflect.Type]CustomTypeFunc{} - // customTypes[reflect.TypeOf((*sql.Valuer)(nil))] = ValidateValuerType - // customTypes[reflect.TypeOf(valuer{})] = ValidateValuerType - - validate := New(Config{TagName: "validate"}) validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{} diff --git a/examples_test.go b/examples_test.go index 8605168..2ebf8b3 100644 --- a/examples_test.go +++ b/examples_test.go @@ -3,14 +3,12 @@ package validator_test import ( "fmt" - "gopkg.in/bluesuncorp/validator.v7" + // "gopkg.in/bluesuncorp/validator.v7" + "../validator" ) func ExampleValidate_new() { - config := validator.Config{ - TagName: "validate", - ValidationFuncs: validator.BakedInValidators, - } + config := validator.Config{TagName: "validate"} validator.New(config) } @@ -19,16 +17,13 @@ func ExampleValidate_field() { // This should be stored somewhere globally var validate *validator.Validate - config := validator.Config{ - TagName: "validate", - ValidationFuncs: validator.BakedInValidators, - } + config := validator.Config{TagName: "validate"} validate = validator.New(config) i := 0 errs := validate.Field(i, "gt=1,lte=10") - err := errs[""] + err := errs.(validator.ValidationErrors)[""] fmt.Println(err.Field) fmt.Println(err.Tag) fmt.Println(err.Kind) // NOTE: Kind and Type can be different i.e. time Kind=struct and Type=time.Time @@ -48,10 +43,7 @@ func ExampleValidate_struct() { // This should be stored somewhere globally var validate *validator.Validate - config := validator.Config{ - TagName: "validate", - ValidationFuncs: validator.BakedInValidators, - } + config := validator.Config{TagName: "validate"} validate = validator.New(config) @@ -81,7 +73,7 @@ func ExampleValidate_struct() { } errs := validate.Struct(user) - for _, v := range errs { + for _, v := range errs.(validator.ValidationErrors) { fmt.Println(v.Field) // Phone fmt.Println(v.Tag) // required //... and so forth diff --git a/util.go b/util.go index 372b964..404bb78 100644 --- a/util.go +++ b/util.go @@ -53,8 +53,8 @@ func (v *Validate) extractType(current reflect.Value) (reflect.Value, reflect.Ki default: - if v.config.hasCustomFuncs { - if fn, ok := v.config.customTypeFuncs[current.Type()]; ok { + if v.hasCustomFuncs { + if fn, ok := v.customTypeFuncs[current.Type()]; ok { return v.extractType(reflect.ValueOf(fn(current))) } } @@ -248,9 +248,9 @@ func (v *Validate) parseTagsRecursive(cTag *cachedTag, tag, fieldName, alias str for _, t := range strings.Split(tag, tagSeparator) { - if v.config.hasAliasValidators { + if v.hasAliasValidators { // check map for alias and process new tags, otherwise process as usual - if tagsVal, ok := v.config.aliasValidators[t]; ok { + if tagsVal, ok := v.aliasValidators[t]; ok { leave := v.parseTagsRecursive(cTag, tagsVal, fieldName, t, true) diff --git a/validator.go b/validator.go index 04af642..eb5b7d6 100644 --- a/validator.go +++ b/validator.go @@ -40,9 +40,8 @@ const ( var ( timeType = reflect.TypeOf(time.Time{}) timePtrType = reflect.TypeOf(&time.Time{}) - errsPool = &sync.Pool{New: newValidationErrors} - tagsCache = &tagCacheMap{m: map[string]*cachedTag{}} emptyStructPtr = new(struct{}) + errsPool = &sync.Pool{New: newValidationErrors} ) // returns new ValidationErrors to the pool @@ -83,18 +82,19 @@ func (s *tagCacheMap) Set(key string, value *cachedTag) { // Validate contains the validator settings passed in using the Config struct type Validate struct { - config Config -} - -// Config contains the options that a Validator instance will use. -// It is passed to the New() function -type Config struct { - TagName string + config Config validationFuncs map[string]Func customTypeFuncs map[reflect.Type]CustomTypeFunc aliasValidators map[string]string hasCustomFuncs bool hasAliasValidators bool + tagsCache *tagCacheMap +} + +// Config contains the options that a Validator instance will use. +// It is passed to the New() function +type Config struct { + TagName string } // CustomTypeFunc allows for overriding or adding custom field type handler functions @@ -149,20 +149,20 @@ func New(config Config) *Validate { // if config.CustomTypeFuncs != nil && len(config.CustomTypeFuncs) > 0 { // config.hasCustomFuncs = true // } - v := &Validate{config: config} + v := &Validate{config: config, tagsCache: &tagCacheMap{m: map[string]*cachedTag{}}} - if len(v.config.aliasValidators) == 0 { - // must copy validators for separate validations to be used in each - v.config.aliasValidators = map[string]string{} - for k, val := range BakedInAliasValidators { + if len(v.aliasValidators) == 0 { + // must copy validators for separate validations to be used in each validator instance + v.aliasValidators = map[string]string{} + for k, val := range bakedInAliasValidators { v.RegisterAliasValidation(k, val) } } - if len(v.config.validationFuncs) == 0 { - // must copy validators for separate validations to be used in each - v.config.validationFuncs = map[string]Func{} - for k, val := range BakedInValidators { + if len(v.validationFuncs) == 0 { + // must copy validators for separate validations to be used in each instance + v.validationFuncs = map[string]Func{} + for k, val := range bakedInValidators { v.RegisterValidation(k, val) } } @@ -189,7 +189,7 @@ func (v *Validate) RegisterValidation(key string, f Func) error { panic(fmt.Sprintf(restrictedTagErr, key)) } - v.config.validationFuncs[key] = f + v.validationFuncs[key] = f return nil } @@ -197,15 +197,15 @@ func (v *Validate) RegisterValidation(key string, f Func) error { // RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) { - if v.config.customTypeFuncs == nil { - v.config.customTypeFuncs = map[reflect.Type]CustomTypeFunc{} + if v.customTypeFuncs == nil { + v.customTypeFuncs = map[reflect.Type]CustomTypeFunc{} } for _, t := range types { - v.config.customTypeFuncs[reflect.TypeOf(t)] = fn + v.customTypeFuncs[reflect.TypeOf(t)] = fn } - v.config.hasCustomFuncs = true + v.hasCustomFuncs = true } // RegisterAliasValidation registers a mapping of a single validationstag that @@ -216,28 +216,21 @@ func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{ // will be the actual tag within the alias that failed. func (v *Validate) RegisterAliasValidation(alias, tags string) { - // if len(v.config.aliasValidators) == 0 { - // // must copy validators for separate validations to be used in each - // v.config.aliasValidators = map[string]string{} - // for k, val := range BakedInAliasValidators { - // v.config.aliasValidators[k] = val - // } - // } - _, ok := restrictedTags[alias] if ok || strings.ContainsAny(alias, restrictedTagChars) { panic(fmt.Sprintf(restrictedAliasErr, alias)) } - v.config.aliasValidators[alias] = tags - v.config.hasAliasValidators = true + v.aliasValidators[alias] = tags + v.hasAliasValidators = true } -// Field validates a single field using tag style validation and returns ValidationErrors +// Field validates a single field using tag style validation and returns nil or ValidationErrors as type error. +// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors. // NOTE: it returns ValidationErrors instead of a single FieldError because this can also // validate Array, Slice and maps fields which may contain more than one error -func (v *Validate) Field(field interface{}, tag string) ValidationErrors { +func (v *Validate) Field(field interface{}, tag string) error { errs := errsPool.Get().(ValidationErrors) fieldVal := reflect.ValueOf(field) @@ -252,10 +245,11 @@ func (v *Validate) Field(field interface{}, tag string) ValidationErrors { return errs } -// FieldWithValue validates a single field, against another fields value using tag style validation and returns ValidationErrors +// FieldWithValue validates a single field, against another fields value using tag style validation and returns nil or ValidationErrors. +// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors. // NOTE: it returns ValidationErrors instead of a single FieldError because this can also // validate Array, Slice and maps fields which may contain more than one error -func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string) ValidationErrors { +func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string) error { errs := errsPool.Get().(ValidationErrors) topVal := reflect.ValueOf(val) @@ -272,10 +266,9 @@ func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string // StructPartial validates the fields passed in only, ignoring all others. // Fields may be provided in a namespaced fashion relative to the struct provided -// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name -// NOTE: This is normally not needed, however in some specific cases such as: tied to a -// legacy data structure, it will be useful -func (v *Validate) StructPartial(current interface{}, fields ...string) ValidationErrors { +// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name and returns nil or ValidationErrors as error +// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors. +func (v *Validate) StructPartial(current interface{}, fields ...string) error { sv, _ := v.extractType(reflect.ValueOf(current)) name := sv.Type().Name() @@ -330,10 +323,9 @@ func (v *Validate) StructPartial(current interface{}, fields ...string) Validati // StructExcept validates all fields except the ones passed in. // Fields may be provided in a namespaced fashion relative to the struct provided -// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name -// NOTE: This is normally not needed, however in some specific cases such as: tied to a -// legacy data structure, it will be useful -func (v *Validate) StructExcept(current interface{}, fields ...string) ValidationErrors { +// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name and returns nil or ValidationErrors as error +// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors. +func (v *Validate) StructExcept(current interface{}, fields ...string) error { sv, _ := v.extractType(reflect.ValueOf(current)) name := sv.Type().Name() @@ -356,7 +348,9 @@ func (v *Validate) StructExcept(current interface{}, fields ...string) Validatio } // Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified. -func (v *Validate) Struct(current interface{}) ValidationErrors { +// it returns nil or ValidationErrors as error. +// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors. +func (v *Validate) Struct(current interface{}) error { errs := errsPool.Get().(ValidationErrors) sv := reflect.ValueOf(current) @@ -420,11 +414,11 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect. return } - cTag, isCached := tagsCache.Get(tag) + cTag, isCached := v.tagsCache.Get(tag) if !isCached { cTag = v.parseTags(tag, name) - tagsCache.Set(tag, cTag) + v.tagsCache.Set(tag, cTag) } current, kind := v.extractType(current) @@ -561,7 +555,7 @@ func (v *Validate) validateField(topStruct reflect.Value, currentStruct reflect. for _, val := range valTag.tagVals { - valFunc, ok = v.config.validationFuncs[val[0]] + valFunc, ok = v.validationFuncs[val[0]] if !ok { panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, name))) } @@ -596,7 +590,7 @@ func (v *Validate) validateField(topStruct reflect.Value, currentStruct reflect. return true } - valFunc, ok = v.config.validationFuncs[valTag.tagVals[0][0]] + valFunc, ok = v.validationFuncs[valTag.tagVals[0][0]] if !ok { panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, name))) } diff --git a/validator_test.go b/validator_test.go index af898f9..117d7e0 100644 --- a/validator_test.go +++ b/validator_test.go @@ -113,7 +113,9 @@ type TestSlice struct { var validate = New(Config{TagName: "validate"}) -func AssertError(t *testing.T, errs ValidationErrors, key, field, expectedTag string) { +func AssertError(t *testing.T, err error, key, field, expectedTag string) { + + errs := err.(ValidationErrors) val, ok := errs[key] EqualSkip(t, 2, ok, true) @@ -242,7 +244,7 @@ func TestAliasTags(t *testing.T) { errs = validate.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Color", "Color", "iscolor") - Equal(t, errs["Test.Color"].ActualTag, "hexcolor|rgb|rgba|hsl|hsla") + Equal(t, errs.(ValidationErrors)["Test.Color"].ActualTag, "hexcolor|rgb|rgba|hsl|hsla") validate.RegisterAliasValidation("req", "required,dive,iscolor") arr := []string{"val1", "#fff", "#000"} @@ -397,12 +399,12 @@ func TestStructPartial(t *testing.T) { // 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), 1) + 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), 1) + Equal(t, len(errs.(ValidationErrors)), 1) // Unset second slice member concurrently to test dive behavior: tPartial.SubSlice[1].Test = "" @@ -417,13 +419,13 @@ func TestStructPartial(t *testing.T) { AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required") errs = validate.StructExcept(tPartial, p1...) - Equal(t, len(errs), 2) + 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), 1) + 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 @@ -439,7 +441,7 @@ func TestStructPartial(t *testing.T) { // testing for missing item by exception, yes it dives and fails errs = validate.StructExcept(tPartial, p1...) NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required") errs = validate.StructExcept(tPartial, p2...) @@ -1303,7 +1305,7 @@ func TestSQLValue2Validation(t *testing.T) { errs = validate.Struct(c) NotEqual(t, errs, nil) - Equal(t, len(errs), 2) + Equal(t, len(errs.(ValidationErrors)), 2) AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "MadeUp", "required") AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "gt") } @@ -1362,7 +1364,7 @@ func TestSQLValueValidation(t *testing.T) { errs = validate.Struct(c) NotEqual(t, errs, nil) - Equal(t, len(errs), 2) + Equal(t, len(errs.(ValidationErrors)), 2) AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "MadeUp", "required") AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "gt") } @@ -1393,7 +1395,7 @@ func TestMACValidation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d mac failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "mac" { t.Fatalf("Index: %d mac failed Error: %s", i, errs) } @@ -1431,7 +1433,7 @@ func TestIPValidation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d ip failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "ip" { t.Fatalf("Index: %d ip failed Error: %s", i, errs) } @@ -1469,7 +1471,7 @@ func TestIPv6Validation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "ipv6" { t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs) } @@ -1507,7 +1509,7 @@ func TestIPv4Validation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "ipv4" { t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs) } @@ -1664,7 +1666,7 @@ func TestInterfaceErrValidation(t *testing.T) { errs = validate.Struct(s) NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "ExternalCMD.Data", "Data", "required") type ExternalCMD2 struct { @@ -1681,7 +1683,7 @@ func TestInterfaceErrValidation(t *testing.T) { errs = validate.Struct(s2) NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "ExternalCMD2.Data", "Data", "len") s3 := &ExternalCMD2{ @@ -1692,7 +1694,7 @@ func TestInterfaceErrValidation(t *testing.T) { errs = validate.Struct(s3) NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "ExternalCMD2.Data", "Data", "len") type Inner struct { @@ -1711,7 +1713,7 @@ func TestInterfaceErrValidation(t *testing.T) { errs = validate.Struct(s4) NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "ExternalCMD.Data.Name", "Name", "required") type TestMapStructPtr struct { @@ -1726,7 +1728,7 @@ func TestInterfaceErrValidation(t *testing.T) { errs = validate.Struct(msp) NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "TestMapStructPtr.Errs[3]", "Errs[3]", "len") type TestMultiDimensionalStructs struct { @@ -1744,7 +1746,7 @@ func TestInterfaceErrValidation(t *testing.T) { errs = validate.Struct(tms) NotEqual(t, errs, nil) - Equal(t, len(errs), 4) + 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") @@ -1766,7 +1768,7 @@ func TestInterfaceErrValidation(t *testing.T) { errs = validate.Struct(tmsp2) NotEqual(t, errs, nil) - Equal(t, len(errs), 6) + 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") @@ -1778,24 +1780,24 @@ func TestInterfaceErrValidation(t *testing.T) { errs = validate.Field(m, "len=3,dive,len=2") NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "[3]", "[3]", "len") errs = validate.Field(m, "len=2,dive,required") NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "", "", "len") arr := []interface{}{"ok", "", "ok"} errs = validate.Field(arr, "len=3,dive,len=2") NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "[1]", "[1]", "len") errs = validate.Field(arr, "len=2,dive,required") NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "", "", "len") type MyStruct struct { @@ -1822,12 +1824,12 @@ func TestMapDiveValidation(t *testing.T) { errs = validate.Field(m, "len=3,dive,required") NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "[3]", "[3]", "required") errs = validate.Field(m, "len=2,dive,required") NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "", "", "len") type Inner struct { @@ -1846,7 +1848,7 @@ func TestMapDiveValidation(t *testing.T) { errs = validate.Struct(ms) NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "TestMapStruct.Errs[3].Name", "Name", "required") // for full test coverage @@ -1867,7 +1869,7 @@ func TestMapDiveValidation(t *testing.T) { errs = validate.Struct(mt) NotEqual(t, errs, nil) - Equal(t, len(errs), 2) + Equal(t, len(errs.(ValidationErrors)), 2) AssertError(t, errs, "TestMapTimeStruct.Errs[3]", "Errs[3]", "required") AssertError(t, errs, "TestMapTimeStruct.Errs[4]", "Errs[4]", "required") @@ -1883,7 +1885,7 @@ func TestMapDiveValidation(t *testing.T) { errs = validate.Struct(msp) NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "TestMapStructPtr.Errs[3]", "Errs[3]", "required") type TestMapStructPtr2 struct { @@ -1906,12 +1908,12 @@ func TestArrayDiveValidation(t *testing.T) { errs := validate.Field(arr, "len=3,dive,required") NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "[1]", "[1]", "required") errs = validate.Field(arr, "len=2,dive,required") NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "", "", "len") type BadDive struct { @@ -1934,7 +1936,7 @@ func TestArrayDiveValidation(t *testing.T) { errs = validate.Struct(test) NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "Test.Errs[1]", "Errs[1]", "required") test = &Test{ @@ -1943,7 +1945,7 @@ func TestArrayDiveValidation(t *testing.T) { errs = validate.Struct(test) NotEqual(t, errs, nil) - Equal(t, len(errs), 1) + Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "Test.Errs[2]", "Errs[2]", "required") type TestMultiDimensional struct { @@ -1961,7 +1963,7 @@ func TestArrayDiveValidation(t *testing.T) { errs = validate.Struct(tm) NotEqual(t, errs, nil) - Equal(t, len(errs), 4) + 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") @@ -1986,7 +1988,7 @@ func TestArrayDiveValidation(t *testing.T) { errs = validate.Struct(tms) NotEqual(t, errs, nil) - Equal(t, len(errs), 4) + 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") @@ -2008,7 +2010,7 @@ func TestArrayDiveValidation(t *testing.T) { errs = validate.Struct(tmsp) NotEqual(t, errs, nil) - Equal(t, len(errs), 5) + 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") @@ -2035,7 +2037,7 @@ func TestArrayDiveValidation(t *testing.T) { errs = validate.Struct(tmsp2) NotEqual(t, errs, nil) - Equal(t, len(errs), 6) + 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") @@ -2059,7 +2061,7 @@ func TestArrayDiveValidation(t *testing.T) { errs = validate.Struct(tmsp3) NotEqual(t, errs, nil) - Equal(t, len(errs), 5) + 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") @@ -2086,7 +2088,7 @@ func TestArrayDiveValidation(t *testing.T) { errs = validate.Struct(tmtp3) NotEqual(t, errs, nil) - Equal(t, len(errs), 3) + 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") @@ -2111,7 +2113,7 @@ func TestArrayDiveValidation(t *testing.T) { errs = validate.Struct(tmtp) NotEqual(t, errs, nil) - Equal(t, len(errs), 3) + 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") @@ -2234,7 +2236,7 @@ func TestSSNValidation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d SSN failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "ssn" { t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) } @@ -2268,7 +2270,7 @@ func TestLongitudeValidation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d Longitude failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "longitude" { t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) } @@ -2302,7 +2304,7 @@ func TestLatitudeValidation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "latitude" { t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) } @@ -2342,7 +2344,7 @@ func TestDataURIValidation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d DataURI failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "datauri" { t.Fatalf("Index: %d DataURI failed Error: %s", i, errs) } @@ -2380,7 +2382,7 @@ func TestMultibyteValidation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "multibyte" { t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs) } @@ -2419,7 +2421,7 @@ func TestPrintableASCIIValidation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "printascii" { t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs) } @@ -2457,7 +2459,7 @@ func TestASCIIValidation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d ASCII failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "ascii" { t.Fatalf("Index: %d ASCII failed Error: %s", i, errs) } @@ -2492,7 +2494,7 @@ func TestUUID5Validation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "uuid5" { t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs) } @@ -2526,7 +2528,7 @@ func TestUUID4Validation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "uuid4" { t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs) } @@ -2559,7 +2561,7 @@ func TestUUID3Validation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "uuid3" { t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs) } @@ -2595,7 +2597,7 @@ func TestUUIDValidation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUID failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "uuid" { t.Fatalf("Index: %d UUID failed Error: %s", i, errs) } @@ -2633,7 +2635,7 @@ func TestISBNValidation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d ISBN failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "isbn" { t.Fatalf("Index: %d ISBN failed Error: %s", i, errs) } @@ -2670,7 +2672,7 @@ func TestISBN13Validation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "isbn13" { t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs) } @@ -2708,7 +2710,7 @@ func TestISBN10Validation(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "isbn10" { t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs) } @@ -4177,7 +4179,7 @@ func TestUrl(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d URL failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "url" { t.Fatalf("Index: %d URL failed Error: %s", i, errs) } @@ -4241,7 +4243,7 @@ func TestUri(t *testing.T) { if IsEqual(errs, nil) { t.Fatalf("Index: %d URI failed Error: %s", i, errs) } else { - val := errs[""] + val := errs.(ValidationErrors)[""] if val.Tag != "uri" { t.Fatalf("Index: %d URI failed Error: %s", i, errs) } @@ -4707,7 +4709,7 @@ func TestStructStringValidation(t *testing.T) { // Assert Top Level NotEqual(t, errs, nil) - Equal(t, len(errs), 13) + Equal(t, len(errs.(ValidationErrors)), 13) // Assert Fields AssertError(t, errs, "TestString.Required", "Required", "required") @@ -4762,7 +4764,7 @@ func TestStructInt32Validation(t *testing.T) { // Assert Top Level NotEqual(t, errs, nil) - Equal(t, len(errs), 10) + Equal(t, len(errs.(ValidationErrors)), 10) // Assert Fields AssertError(t, errs, "TestInt32.Required", "Required", "required") @@ -4804,7 +4806,7 @@ func TestStructUint64Validation(t *testing.T) { // Assert Top Level NotEqual(t, errs, nil) - Equal(t, len(errs), 6) + Equal(t, len(errs.(ValidationErrors)), 6) // Assert Fields AssertError(t, errs, "TestUint64.Required", "Required", "required") @@ -4842,7 +4844,7 @@ func TestStructFloat64Validation(t *testing.T) { // Assert Top Level NotEqual(t, errs, nil) - Equal(t, len(errs), 6) + Equal(t, len(errs.(ValidationErrors)), 6) // Assert Fields AssertError(t, errs, "TestFloat64.Required", "Required", "required") @@ -4878,7 +4880,7 @@ func TestStructSliceValidation(t *testing.T) { errs = validate.Struct(tFail) NotEqual(t, errs, nil) - Equal(t, len(errs), 6) + Equal(t, len(errs.(ValidationErrors)), 6) // Assert Field Errors AssertError(t, errs, "TestSlice.Required", "Required", "required")