Merge branch 'v2-development' into v2

Conflicts:
	validator.go
pull/16/head
Dean Karn 10 years ago
commit 250bdade04
  1. 100
      baked_in.go
  2. 86
      validator.go
  3. 119
      validator_test.go

@ -5,6 +5,7 @@ import (
"net/url" "net/url"
"reflect" "reflect"
"strconv" "strconv"
"time"
) )
// BakedInValidators is the map of ValidationFunc used internally // BakedInValidators is the map of ValidationFunc used internally
@ -43,9 +44,9 @@ func isURI(val interface{}, field interface{}, param string) bool {
_, err := url.ParseRequestURI(field.(string)) _, err := url.ParseRequestURI(field.(string))
return err == nil return err == nil
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isURL(val interface{}, field interface{}, param string) bool { func isURL(val interface{}, field interface{}, param string) bool {
@ -66,10 +67,9 @@ func isURL(val interface{}, field interface{}, param string) bool {
} }
return err == nil return err == nil
}
default:
panic(fmt.Sprintf("Bad field type %T", field)) panic(fmt.Sprintf("Bad field type %T", field))
}
} }
func isEmail(val interface{}, field interface{}, param string) bool { func isEmail(val interface{}, field interface{}, param string) bool {
@ -80,9 +80,9 @@ func isEmail(val interface{}, field interface{}, param string) bool {
case reflect.String: case reflect.String:
return emailRegex.MatchString(field.(string)) return emailRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isHsla(val interface{}, field interface{}, param string) bool { func isHsla(val interface{}, field interface{}, param string) bool {
@ -93,9 +93,9 @@ func isHsla(val interface{}, field interface{}, param string) bool {
case reflect.String: case reflect.String:
return hslaRegex.MatchString(field.(string)) return hslaRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isHsl(val interface{}, field interface{}, param string) bool { func isHsl(val interface{}, field interface{}, param string) bool {
@ -106,9 +106,9 @@ func isHsl(val interface{}, field interface{}, param string) bool {
case reflect.String: case reflect.String:
return hslRegex.MatchString(field.(string)) return hslRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isRgba(val interface{}, field interface{}, param string) bool { func isRgba(val interface{}, field interface{}, param string) bool {
@ -119,9 +119,9 @@ func isRgba(val interface{}, field interface{}, param string) bool {
case reflect.String: case reflect.String:
return rgbaRegex.MatchString(field.(string)) return rgbaRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isRgb(val interface{}, field interface{}, param string) bool { func isRgb(val interface{}, field interface{}, param string) bool {
@ -132,9 +132,9 @@ func isRgb(val interface{}, field interface{}, param string) bool {
case reflect.String: case reflect.String:
return rgbRegex.MatchString(field.(string)) return rgbRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isHexcolor(val interface{}, field interface{}, param string) bool { func isHexcolor(val interface{}, field interface{}, param string) bool {
@ -145,9 +145,9 @@ func isHexcolor(val interface{}, field interface{}, param string) bool {
case reflect.String: case reflect.String:
return hexcolorRegex.MatchString(field.(string)) return hexcolorRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isHexadecimal(val interface{}, field interface{}, param string) bool { func isHexadecimal(val interface{}, field interface{}, param string) bool {
@ -158,9 +158,9 @@ func isHexadecimal(val interface{}, field interface{}, param string) bool {
case reflect.String: case reflect.String:
return hexadecimalRegex.MatchString(field.(string)) return hexadecimalRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isNumber(val interface{}, field interface{}, param string) bool { func isNumber(val interface{}, field interface{}, param string) bool {
@ -171,9 +171,9 @@ func isNumber(val interface{}, field interface{}, param string) bool {
case reflect.String: case reflect.String:
return numberRegex.MatchString(field.(string)) return numberRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isNumeric(val interface{}, field interface{}, param string) bool { func isNumeric(val interface{}, field interface{}, param string) bool {
@ -184,9 +184,9 @@ func isNumeric(val interface{}, field interface{}, param string) bool {
case reflect.String: case reflect.String:
return numericRegex.MatchString(field.(string)) return numericRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isAlphanum(val interface{}, field interface{}, param string) bool { func isAlphanum(val interface{}, field interface{}, param string) bool {
@ -197,9 +197,9 @@ func isAlphanum(val interface{}, field interface{}, param string) bool {
case reflect.String: case reflect.String:
return alphaNumericRegex.MatchString(field.(string)) return alphaNumericRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isAlpha(val interface{}, field interface{}, param string) bool { func isAlpha(val interface{}, field interface{}, param string) bool {
@ -210,9 +210,9 @@ func isAlpha(val interface{}, field interface{}, param string) bool {
case reflect.String: case reflect.String:
return alphaRegex.MatchString(field.(string)) return alphaRegex.MatchString(field.(string))
default:
panic(fmt.Sprintf("Bad field type %T", field))
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
func hasValue(val interface{}, field interface{}, param string) bool { func hasValue(val interface{}, field interface{}, param string) bool {
@ -260,9 +260,18 @@ func isGte(val interface{}, field interface{}, param string) bool {
return st.Float() >= p return st.Float() >= p
default: case reflect.Struct:
panic(fmt.Sprintf("Bad field type %T", field))
if st.Type() == reflect.TypeOf(field) {
now := time.Now().UTC()
t := field.(time.Time)
return t.After(now) || t.Equal(now)
} }
}
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isGt(val interface{}, field interface{}, param string) bool { func isGt(val interface{}, field interface{}, param string) bool {
@ -295,10 +304,15 @@ func isGt(val interface{}, field interface{}, param string) bool {
p := asFloat(param) p := asFloat(param)
return st.Float() > p return st.Float() > p
case reflect.Struct:
default: if st.Type() == reflect.TypeOf(field) {
panic(fmt.Sprintf("Bad field type %T", field))
return field.(time.Time).After(time.Now().UTC())
}
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
// length tests whether a variable's length is equal to a given // length tests whether a variable's length is equal to a given
@ -334,10 +348,9 @@ func hasLengthOf(val interface{}, field interface{}, param string) bool {
p := asFloat(param) p := asFloat(param)
return st.Float() == p return st.Float() == p
}
default:
panic(fmt.Sprintf("Bad field type %T", field)) panic(fmt.Sprintf("Bad field type %T", field))
}
} }
// min tests whether a variable value is larger or equal to a given // min tests whether a variable value is larger or equal to a given
@ -380,9 +393,18 @@ func isLte(val interface{}, field interface{}, param string) bool {
return st.Float() <= p return st.Float() <= p
default: case reflect.Struct:
panic(fmt.Sprintf("Bad field type %T", field))
if st.Type() == reflect.TypeOf(field) {
now := time.Now().UTC()
t := field.(time.Time)
return t.Before(now) || t.Equal(now)
} }
}
panic(fmt.Sprintf("Bad field type %T", field))
} }
func isLt(val interface{}, field interface{}, param string) bool { func isLt(val interface{}, field interface{}, param string) bool {
@ -416,9 +438,15 @@ func isLt(val interface{}, field interface{}, param string) bool {
return st.Float() < p return st.Float() < p
default: case reflect.Struct:
panic(fmt.Sprintf("Bad field type %T", field))
if st.Type() == reflect.TypeOf(field) {
return field.(time.Time).Before(time.Now().UTC())
}
} }
panic(fmt.Sprintf("Bad field type %T", field))
} }
// max tests whether a variable value is lesser than a given // max tests whether a variable value is lesser than a given

@ -13,6 +13,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"strings" "strings"
"time"
"unicode" "unicode"
) )
@ -174,75 +175,6 @@ func (v *Validator) ValidateStruct(s interface{}) *StructValidationErrors {
} }
return v.validateStructRecursive(s, s) return v.validateStructRecursive(s, s)
// structValue := reflect.ValueOf(s)
// structType := reflect.TypeOf(s)
// structName := structType.Name()
// validationErrors := &StructValidationErrors{
// Struct: structName,
// Errors: map[string]*FieldValidationError{},
// StructErrors: map[string]*StructValidationErrors{},
// }
// if structValue.Kind() == reflect.Ptr && !structValue.IsNil() {
// return v.ValidateStruct(structValue.Elem().Interface())
// }
// if structValue.Kind() != reflect.Struct && structValue.Kind() != reflect.Interface {
// panic("interface passed for validation is not a struct")
// }
// var numFields = structValue.NumField()
// for i := 0; i < numFields; i++ {
// valueField := structValue.Field(i)
// typeField := structType.Field(i)
// if valueField.Kind() == reflect.Ptr && !valueField.IsNil() {
// valueField = valueField.Elem()
// }
// tag := typeField.Tag.Get(v.tagName)
// if tag == "-" {
// continue
// }
// // if no validation and not a struct (which may containt fields for validation)
// if tag == "" && valueField.Kind() != reflect.Struct && valueField.Kind() != reflect.Interface {
// continue
// }
// switch valueField.Kind() {
// case reflect.Struct, reflect.Interface:
// if !unicode.IsUpper(rune(typeField.Name[0])) {
// continue
// }
// if structErrors := v.ValidateStruct(valueField.Interface()); structErrors != nil {
// validationErrors.StructErrors[typeField.Name] = structErrors
// // free up memory map no longer needed
// structErrors = nil
// }
// default:
// if fieldError := v.validateFieldByNameAndTag(valueField.Interface(), typeField.Name, tag); fieldError != nil {
// validationErrors.Errors[fieldError.Field] = fieldError
// // free up memory reference
// fieldError = nil
// }
// }
// }
// if len(validationErrors.Errors) == 0 && len(validationErrors.StructErrors) == 0 {
// return nil
// }
// return validationErrors
} }
// validateStructRecursive validates a struct recursivly and passes the top level struct around for use in validator functions and returns a struct containing the errors // validateStructRecursive validates a struct recursivly and passes the top level struct around for use in validator functions and returns a struct containing the errors
@ -296,11 +228,22 @@ func (v *Validator) validateStructRecursive(top interface{}, s interface{}) *Str
continue continue
} }
if structErrors := v.validateStructRecursive(top, valueField.Interface()); structErrors != nil { if valueField.Type() == reflect.TypeOf(time.Time{}) {
if fieldError := v.validateFieldByNameAndTagAndValue(top, valueField.Interface(), typeField.Name, tag); fieldError != nil {
validationErrors.Errors[fieldError.Field] = fieldError
// free up memory reference
fieldError = nil
}
} else {
if structErrors := v.ValidateStruct(valueField.Interface()); structErrors != nil {
validationErrors.StructErrors[typeField.Name] = structErrors validationErrors.StructErrors[typeField.Name] = structErrors
// free up memory map no longer needed // free up memory map no longer needed
structErrors = nil structErrors = nil
} }
}
default: default:
@ -363,8 +306,11 @@ func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, f interfa
switch valueField.Kind() { switch valueField.Kind() {
case reflect.Struct, reflect.Interface, reflect.Invalid: case reflect.Struct, reflect.Interface, reflect.Invalid:
if valueField.Type() != reflect.TypeOf(time.Time{}) {
panic("Invalid field passed to ValidateFieldWithTag") panic("Invalid field passed to ValidateFieldWithTag")
} }
}
var valErr *FieldValidationError var valErr *FieldValidationError
var err error var err error

@ -3,6 +3,7 @@ package validator_test
import ( import (
"fmt" "fmt"
"testing" "testing"
"time"
"github.com/joeybloggs/go-validate-yourself" "github.com/joeybloggs/go-validate-yourself"
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
@ -242,12 +243,70 @@ func (ms *MySuite) TestIsGt(c *C) {
i := true i := true
c.Assert(func() { validator.ValidateFieldByTag(i, "gt") }, PanicMatches, "Bad field type bool") c.Assert(func() { validator.ValidateFieldByTag(i, "gt") }, PanicMatches, "Bad field type bool")
t := time.Now().UTC()
t = t.Add(time.Hour * 24)
err = validator.ValidateFieldByTag(t, "gt")
c.Assert(err, IsNil)
t2 := time.Now().UTC()
err = validator.ValidateFieldByTag(t2, "gt")
c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "gt")
type Test struct {
Now *time.Time `validate:"gt"`
}
s := &Test{
Now: &t,
}
errs := validator.ValidateStruct(s)
c.Assert(errs, IsNil)
s = &Test{
Now: &t2,
}
errs = validator.ValidateStruct(s)
c.Assert(errs, NotNil)
} }
func (ms *MySuite) TestIsGte(c *C) { func (ms *MySuite) TestIsGte(c *C) {
i := true i := true
c.Assert(func() { validator.ValidateFieldByTag(i, "gte") }, PanicMatches, "Bad field type bool") c.Assert(func() { validator.ValidateFieldByTag(i, "gte") }, PanicMatches, "Bad field type bool")
t := time.Now().UTC()
t = t.Add(time.Hour * 24)
err := validator.ValidateFieldByTag(t, "gte")
c.Assert(err, IsNil)
t2 := time.Now().UTC()
err = validator.ValidateFieldByTag(t2, "gte")
c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "gte")
type Test struct {
Now *time.Time `validate:"gte"`
}
s := &Test{
Now: &t,
}
errs := validator.ValidateStruct(s)
c.Assert(errs, IsNil)
s = &Test{
Now: &t2,
}
errs = validator.ValidateStruct(s)
c.Assert(errs, NotNil)
} }
func (ms *MySuite) TestIsLt(c *C) { func (ms *MySuite) TestIsLt(c *C) {
@ -266,12 +325,72 @@ func (ms *MySuite) TestIsLt(c *C) {
i := true i := true
c.Assert(func() { validator.ValidateFieldByTag(i, "lt") }, PanicMatches, "Bad field type bool") c.Assert(func() { validator.ValidateFieldByTag(i, "lt") }, PanicMatches, "Bad field type bool")
t := time.Now().UTC()
err = validator.ValidateFieldByTag(t, "lt")
c.Assert(err, IsNil)
t2 := time.Now().UTC()
t2 = t2.Add(time.Hour * 24)
err = validator.ValidateFieldByTag(t2, "lt")
c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "lt")
type Test struct {
Now *time.Time `validate:"lt"`
}
s := &Test{
Now: &t,
}
errs := validator.ValidateStruct(s)
c.Assert(errs, IsNil)
s = &Test{
Now: &t2,
}
errs = validator.ValidateStruct(s)
c.Assert(errs, NotNil)
} }
func (ms *MySuite) TestIsLte(c *C) { func (ms *MySuite) TestIsLte(c *C) {
i := true i := true
c.Assert(func() { validator.ValidateFieldByTag(i, "lte") }, PanicMatches, "Bad field type bool") c.Assert(func() { validator.ValidateFieldByTag(i, "lte") }, PanicMatches, "Bad field type bool")
t := time.Now().UTC()
err := validator.ValidateFieldByTag(t, "lte")
c.Assert(err, IsNil)
t2 := time.Now().UTC()
t2 = t2.Add(time.Hour * 24)
err = validator.ValidateFieldByTag(t2, "lte")
c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "lte")
type Test struct {
Now *time.Time `validate:"lte"`
}
s := &Test{
Now: &t,
}
errs := validator.ValidateStruct(s)
c.Assert(errs, IsNil)
s = &Test{
Now: &t2,
}
errs = validator.ValidateStruct(s)
c.Assert(errs, NotNil)
} }
func (ms *MySuite) TestUrl(c *C) { func (ms *MySuite) TestUrl(c *C) {

Loading…
Cancel
Save