From e882184fe2272e7df73d65a71f198c8efedb6321 Mon Sep 17 00:00:00 2001 From: Dean Karn Date: Tue, 10 Mar 2015 15:07:00 -0400 Subject: [PATCH] issue-#11 update gt, gte, lt and let to handle dates compared to time.Now().UTC() --- baked_in.go | 104 +++++++++++++++++++++++++--------------- validator.go | 25 ++++++++-- validator_test.go | 119 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+), 43 deletions(-) diff --git a/baked_in.go b/baked_in.go index 72ea682..11a7375 100644 --- a/baked_in.go +++ b/baked_in.go @@ -5,6 +5,7 @@ import ( "net/url" "reflect" "strconv" + "time" ) // BakedInValidators is the map of ValidationFunc used internally @@ -43,9 +44,9 @@ func isURI(field interface{}, param string) bool { _, err := url.ParseRequestURI(field.(string)) return err == nil - default: - panic(fmt.Sprintf("Bad field type %T", field)) } + + panic(fmt.Sprintf("Bad field type %T", field)) } func isURL(field interface{}, param string) bool { @@ -66,10 +67,9 @@ func isURL(field interface{}, param string) bool { } return err == nil - - default: - panic(fmt.Sprintf("Bad field type %T", field)) } + + panic(fmt.Sprintf("Bad field type %T", field)) } func isEmail(field interface{}, param string) bool { @@ -80,9 +80,9 @@ func isEmail(field interface{}, param string) bool { case reflect.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(field interface{}, param string) bool { @@ -93,9 +93,9 @@ func isHsla(field interface{}, param string) bool { case reflect.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(field interface{}, param string) bool { @@ -106,9 +106,9 @@ func isHsl(field interface{}, param string) bool { case reflect.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(field interface{}, param string) bool { @@ -119,9 +119,9 @@ func isRgba(field interface{}, param string) bool { case reflect.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(field interface{}, param string) bool { @@ -132,9 +132,9 @@ func isRgb(field interface{}, param string) bool { case reflect.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(field interface{}, param string) bool { @@ -145,9 +145,9 @@ func isHexcolor(field interface{}, param string) bool { case reflect.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(field interface{}, param string) bool { @@ -158,9 +158,9 @@ func isHexadecimal(field interface{}, param string) bool { case reflect.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(field interface{}, param string) bool { @@ -171,9 +171,9 @@ func isNumber(field interface{}, param string) bool { case reflect.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(field interface{}, param string) bool { @@ -184,9 +184,9 @@ func isNumeric(field interface{}, param string) bool { case reflect.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(field interface{}, param string) bool { @@ -197,9 +197,9 @@ func isAlphanum(field interface{}, param string) bool { case reflect.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(field interface{}, param string) bool { @@ -210,9 +210,9 @@ func isAlpha(field interface{}, param string) bool { case reflect.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(field interface{}, param string) bool { @@ -260,9 +260,18 @@ func isGte(field interface{}, param string) bool { return st.Float() >= p - default: - panic(fmt.Sprintf("Bad field type %T", field)) + case reflect.Struct: + + 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(field interface{}, param string) bool { @@ -295,10 +304,15 @@ func isGt(field interface{}, param string) bool { p := asFloat(param) return st.Float() > p + case reflect.Struct: - default: - panic(fmt.Sprintf("Bad field type %T", field)) + if st.Type() == reflect.TypeOf(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 @@ -334,10 +348,9 @@ func hasLengthOf(field interface{}, param string) bool { p := asFloat(param) 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 @@ -380,9 +393,18 @@ func isLte(field interface{}, param string) bool { return st.Float() <= p - default: - panic(fmt.Sprintf("Bad field type %T", field)) + case reflect.Struct: + + 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(field interface{}, param string) bool { @@ -416,9 +438,15 @@ func isLt(field interface{}, param string) bool { return st.Float() < p - default: - panic(fmt.Sprintf("Bad field type %T", field)) + case reflect.Struct: + + 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 diff --git a/validator.go b/validator.go index 4ffea06..c7b7a89 100644 --- a/validator.go +++ b/validator.go @@ -13,6 +13,7 @@ import ( "fmt" "reflect" "strings" + "time" "unicode" ) @@ -215,10 +216,21 @@ func (v *Validator) ValidateStruct(s interface{}) *StructValidationErrors { continue } - if structErrors := v.ValidateStruct(valueField.Interface()); structErrors != nil { - validationErrors.StructErrors[typeField.Name] = structErrors - // free up memory map no longer needed - structErrors = nil + if valueField.Type() == reflect.TypeOf(time.Time{}) { + + if fieldError := v.validateFieldByNameAndTag(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 + // free up memory map no longer needed + structErrors = nil + } } default: @@ -270,7 +282,10 @@ func (v *Validator) validateFieldByNameAndTag(f interface{}, name string, tag st switch valueField.Kind() { case reflect.Struct, reflect.Interface, reflect.Invalid: - panic("Invalid field passed to ValidateFieldWithTag") + + if valueField.Type() != reflect.TypeOf(time.Time{}) { + panic("Invalid field passed to ValidateFieldWithTag") + } } var valErr *FieldValidationError diff --git a/validator_test.go b/validator_test.go index 72d39fb..56f7f97 100644 --- a/validator_test.go +++ b/validator_test.go @@ -3,6 +3,7 @@ package validator_test import ( "fmt" "testing" + "time" "github.com/joeybloggs/go-validate-yourself" . "gopkg.in/check.v1" @@ -218,12 +219,70 @@ func (ms *MySuite) TestIsGt(c *C) { i := true 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) { i := true 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) { @@ -242,12 +301,72 @@ func (ms *MySuite) TestIsLt(c *C) { i := true 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) { i := true 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) {