Skip to content

Commit

Permalink
Invoke all custom validators (fixes #116)
Browse files Browse the repository at this point in the history
  • Loading branch information
annismckenzie committed May 3, 2016
1 parent 59d9d8a commit 13f9f00
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 12 deletions.
27 changes: 17 additions & 10 deletions validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -700,23 +700,30 @@ func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value) (bool, e
}

options := parseTag(tag)
for i := range options {
tagOpt := options[i]
tagOptions := strings.Split(tagOpt, "~")
if ok := isValidTag(tagOptions[0]); !ok {
var customTypeErrors Errors
var customTypeValidatorsExist bool
for _, tagOpt := range options {
tagOpts := strings.Split(tagOpt, "~")
if ok := isValidTag(tagOpts[0]); !ok {
continue
}
if validatefunc, ok := CustomTypeTagMap[tagOptions[0]]; ok {
options = append(options[:i], options[i+1:]...) // we found our custom validator, so remove it from the options
if validatefunc, ok := CustomTypeTagMap[tagOpts[0]]; ok {
customTypeValidatorsExist = true
if result := validatefunc(v.Interface(), o.Interface()); !result {
if len(tagOptions) == 2 {
return false, Error{t.Name, fmt.Errorf(tagOptions[1]), true}
if len(tagOpts) == 2 {
customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf(tagOpts[1]), CustomErrorMessageExists: true})
continue
}
return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), tagOptions[0]), false}
customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), tagOpts[0]), CustomErrorMessageExists: false})
}
return true, nil
}
}
if customTypeValidatorsExist {
if len(customTypeErrors.Errors()) > 0 {
return false, customTypeErrors
}
return true, nil
}

if isEmptyValue(v) {
// an empty value is not validated, check only required
Expand Down
17 changes: 15 additions & 2 deletions validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1924,11 +1924,14 @@ func TestFieldsRequiredByDefaultButExemptOrOptionalStruct(t *testing.T) {
type CustomByteArray [6]byte

type StructWithCustomByteArray struct {
ID CustomByteArray `valid:"customByteArrayValidator"`
Email string `valid:"email"`
ID CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"`
Email string `valid:"email"`
CustomMinLength int `valid:"-"`
}

func TestStructWithCustomByteArray(t *testing.T) {
t.Parallel()

// add our custom byte array validator that fails when the byte array is pristine (all zeroes)
CustomTypeTagMap["customByteArrayValidator"] = CustomTypeValidator(func(i interface{}, o interface{}) bool {
switch v := o.(type) {
Expand All @@ -1952,6 +1955,13 @@ func TestStructWithCustomByteArray(t *testing.T) {
}
return false
})
CustomTypeTagMap["customMinLengthValidator"] = CustomTypeValidator(func(i interface{}, o interface{}) bool {
switch v := o.(type) {
case StructWithCustomByteArray:
return len(v.ID) >= v.CustomMinLength
}
return false
})
testCustomByteArray := CustomByteArray{'1', '2', '3', '4', '5', '6'}
var tests = []struct {
param StructWithCustomByteArray
Expand All @@ -1960,7 +1970,9 @@ func TestStructWithCustomByteArray(t *testing.T) {
{StructWithCustomByteArray{}, false},
{StructWithCustomByteArray{Email: "[email protected]"}, false},
{StructWithCustomByteArray{ID: testCustomByteArray, Email: "[email protected]"}, true},
{StructWithCustomByteArray{ID: testCustomByteArray, Email: "[email protected]", CustomMinLength: 7}, false},
}
SetFieldsRequiredByDefault(true)
for _, test := range tests {
actual, err := ValidateStruct(test.param)
if actual != test.expected {
Expand All @@ -1970,6 +1982,7 @@ func TestStructWithCustomByteArray(t *testing.T) {
}
}
}
SetFieldsRequiredByDefault(false)
}

func TestValidateNegationStruct(t *testing.T) {
Expand Down

0 comments on commit 13f9f00

Please sign in to comment.