Merge pull request #42 from bluesuncorp/v5

merge latest changes from v5
pull/58/head
Dean Karn 10 years ago
commit 40c38f9931
  1. 2
      README.md
  2. 125
      baked_in.go
  3. 24
      doc.go
  4. 2
      validator.go
  5. 232
      validator_test.go

@ -1,6 +1,6 @@
Package validator
================
[![Build Status](https://travis-ci.org/bluesuncorp/validator.svg?branch=v5.0.2)](https://travis-ci.org/bluesuncorp/validator)
[![Build Status](https://travis-ci.org/bluesuncorp/validator.svg?branch=v5.1)](https://travis-ci.org/bluesuncorp/validator)
[![GoDoc](https://godoc.org/gopkg.in/bluesuncorp/validator.v5?status.svg)](https://godoc.org/gopkg.in/bluesuncorp/validator.v5)
Package validator implements value validations for structs and individual fields based on tags.

@ -16,10 +16,14 @@ var BakedInValidators = map[string]Func{
"len": hasLengthOf,
"min": hasMinOf,
"max": hasMaxOf,
"eq": isEq,
"ne": isNe,
"lt": isLt,
"lte": isLte,
"gt": isGt,
"gte": isGte,
"eqfield": isEqField,
"nefield": isNeField,
"gtefield": isGteField,
"gtfield": isGtField,
"ltefield": isLteField,
@ -40,6 +44,127 @@ var BakedInValidators = map[string]Func{
"base64": isBase64,
}
func isNeField(top interface{}, current interface{}, field interface{}, param string) bool {
return !isEqField(top, current, field, param)
}
func isNe(top interface{}, current interface{}, field interface{}, param string) bool {
return !isEq(top, current, field, param)
}
func isEqField(top interface{}, current interface{}, field interface{}, param string) bool {
if current == nil {
panic("struct not passed for cross validation")
}
currentVal := reflect.ValueOf(current)
if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
currentVal = reflect.ValueOf(currentVal.Elem().Interface())
}
var currentFielVal reflect.Value
switch currentVal.Kind() {
case reflect.Struct:
if currentVal.Type() == reflect.TypeOf(time.Time{}) {
currentFielVal = currentVal
break
}
f := currentVal.FieldByName(param)
if f.Kind() == reflect.Invalid {
panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
}
currentFielVal = f
default:
currentFielVal = currentVal
}
if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
}
fv := reflect.ValueOf(field)
switch fv.Kind() {
case reflect.String:
return fv.String() == currentFielVal.String()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return fv.Int() == currentFielVal.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return fv.Uint() == currentFielVal.Uint()
case reflect.Float32, reflect.Float64:
return fv.Float() == currentFielVal.Float()
case reflect.Slice, reflect.Map, reflect.Array:
return int64(fv.Len()) == int64(currentFielVal.Len())
case reflect.Struct:
if fv.Type() == reflect.TypeOf(time.Time{}) {
if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
panic("Bad Top Level field type")
}
t := currentFielVal.Interface().(time.Time)
fieldTime := field.(time.Time)
return fieldTime.Equal(t)
}
}
panic(fmt.Sprintf("Bad field type %T", field))
}
func isEq(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
switch st.Kind() {
case reflect.String:
return st.String() == param
case reflect.Slice, reflect.Map, reflect.Array:
p := asInt(param)
return int64(st.Len()) == p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p := asInt(param)
return st.Int() == p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p := asUint(param)
return st.Uint() == p
case reflect.Float32, reflect.Float64:
p := asFloat(param)
return st.Float() == p
}
panic(fmt.Sprintf("Bad field type %T", field))
}
func isBase64(top interface{}, current interface{}, field interface{}, param string) bool {
return matchesRegex(base64Regex, field)
}

@ -192,6 +192,16 @@ Here is a list of the current built in validators:
the string length is at least that number of characters. For slices,
arrays, and maps, validates the number of items. (Usage: min=10)
eq
For strings & numbers, eq will ensure that the value is
equal to the parameter given. For slices, arrays, and maps,
validates the number of items. (Usage: eq=10)
ne
For strings & numbers, eq will ensure that the value is not
equal to the parameter given. For slices, arrays, and maps,
validates the number of items. (Usage: eq=10)
gt
For numbers, this will ensure that the value is greater than the
parameter given. For strings, it checks that the string length
@ -221,6 +231,20 @@ Here is a list of the current built in validators:
For time.Time ensures the time value is less than or equal to time.Now.UTC()
(Usage: lte)
eqfield
This will validate the field value against another fields value either within
a struct or passed in field.
usage examples are for validation of a password and confirm password:
Validation on Password field using validate.Struct Usage(eqfield=ConfirmPassword)
Validating by field validate.FieldWithValue(password, confirmpassword, "eqfield")
nefield
This will validate the field value against another fields value either within
a struct or passed in field.
usage examples are for ensuring two colors are not the same:
Validation on Color field using validate.Struct Usage(nefield=Color2)
Validating by field validate.FieldWithValue(color1, color2, "nefield")
gtfield
Only valid for Numbers and time.Time types, this will validate the field value
against another fields value either within a struct or passed in field.

@ -200,7 +200,7 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
}
// if no validation and not a struct (which may containt fields for validation)
if tag == "" && valueField.Kind() != reflect.Struct && valueField.Kind() != reflect.Interface {
if tag == "" && ((valueField.Kind() != reflect.Struct && valueField.Kind() != reflect.Interface) || valueField.Type() == reflect.TypeOf(time.Time{})) {
continue
}

@ -142,6 +142,238 @@ func isEqualFunc(val interface{}, current interface{}, field interface{}, param
return current.(string) == field.(string)
}
func (ms *MySuite) TestIsNeFieldValidation(c *C) {
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
err := validate.FieldWithValue(s, s2, "nefield")
c.Assert(err, IsNil)
err = validate.FieldWithValue(i2, i, "nefield")
c.Assert(err, IsNil)
err = validate.FieldWithValue(j2, j, "nefield")
c.Assert(err, IsNil)
err = validate.FieldWithValue(k2, k, "nefield")
c.Assert(err, IsNil)
err = validate.FieldWithValue(arr2, arr, "nefield")
c.Assert(err, IsNil)
err = validate.FieldWithValue(now2, now, "nefield")
c.Assert(err, NotNil)
err = validate.FieldWithValue(arr3, arr, "nefield")
c.Assert(err, NotNil)
type Test struct {
Start *time.Time `validate:"nefield=End"`
End *time.Time
}
sv := &Test{
Start: &now,
End: &now,
}
errs := validate.Struct(sv)
c.Assert(errs, NotNil)
now3 := time.Now().UTC()
sv = &Test{
Start: &now,
End: &now3,
}
errs = validate.Struct(sv)
c.Assert(errs, IsNil)
channel := make(chan string)
c.Assert(func() { validate.FieldWithValue(nil, 1, "nefield") }, PanicMatches, "struct not passed for cross validation")
c.Assert(func() { validate.FieldWithValue(5, channel, "nefield") }, PanicMatches, "Bad field type chan string")
c.Assert(func() { validate.FieldWithValue(5, now, "nefield") }, PanicMatches, "Bad Top Level field type")
type Test2 struct {
Start *time.Time `validate:"nefield=NonExistantField"`
End *time.Time
}
sv2 := &Test2{
Start: &now,
End: &now,
}
c.Assert(func() { validate.Struct(sv2) }, PanicMatches, "Field \"NonExistantField\" not found in struct")
}
func (ms *MySuite) TestIsNeValidation(c *C) {
var j uint64
var k float64
s := "abcdef"
i := 3
j = 2
k = 1.5434
arr := []string{"test"}
now := time.Now().UTC()
err := validate.Field(s, "ne=abcd")
c.Assert(err, IsNil)
err = validate.Field(i, "ne=1")
c.Assert(err, IsNil)
err = validate.Field(j, "ne=1")
c.Assert(err, IsNil)
err = validate.Field(k, "ne=1.543")
c.Assert(err, IsNil)
err = validate.Field(arr, "ne=2")
c.Assert(err, IsNil)
err = validate.Field(arr, "ne=1")
c.Assert(err, NotNil)
c.Assert(func() { validate.Field(now, "ne=now") }, PanicMatches, "Bad field type time.Time")
}
func (ms *MySuite) TestIsEqFieldValidation(c *C) {
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
err := validate.FieldWithValue(s, s2, "eqfield")
c.Assert(err, IsNil)
err = validate.FieldWithValue(i2, i, "eqfield")
c.Assert(err, IsNil)
err = validate.FieldWithValue(j2, j, "eqfield")
c.Assert(err, IsNil)
err = validate.FieldWithValue(k2, k, "eqfield")
c.Assert(err, IsNil)
err = validate.FieldWithValue(arr2, arr, "eqfield")
c.Assert(err, IsNil)
err = validate.FieldWithValue(now2, now, "eqfield")
c.Assert(err, IsNil)
err = validate.FieldWithValue(arr3, arr, "eqfield")
c.Assert(err, NotNil)
type Test struct {
Start *time.Time `validate:"eqfield=End"`
End *time.Time
}
sv := &Test{
Start: &now,
End: &now,
}
errs := validate.Struct(sv)
c.Assert(errs, IsNil)
now3 := time.Now().UTC()
sv = &Test{
Start: &now,
End: &now3,
}
errs = validate.Struct(sv)
c.Assert(errs, NotNil)
channel := make(chan string)
c.Assert(func() { validate.FieldWithValue(nil, 1, "eqfield") }, PanicMatches, "struct not passed for cross validation")
c.Assert(func() { validate.FieldWithValue(5, channel, "eqfield") }, PanicMatches, "Bad field type chan string")
c.Assert(func() { validate.FieldWithValue(5, now, "eqfield") }, PanicMatches, "Bad Top Level field type")
type Test2 struct {
Start *time.Time `validate:"eqfield=NonExistantField"`
End *time.Time
}
sv2 := &Test2{
Start: &now,
End: &now,
}
c.Assert(func() { validate.Struct(sv2) }, PanicMatches, "Field \"NonExistantField\" not found in struct")
}
func (ms *MySuite) TestIsEqValidation(c *C) {
var j uint64
var k float64
s := "abcd"
i := 1
j = 1
k = 1.543
arr := []string{"test"}
now := time.Now().UTC()
err := validate.Field(s, "eq=abcd")
c.Assert(err, IsNil)
err = validate.Field(i, "eq=1")
c.Assert(err, IsNil)
err = validate.Field(j, "eq=1")
c.Assert(err, IsNil)
err = validate.Field(k, "eq=1.543")
c.Assert(err, IsNil)
err = validate.Field(arr, "eq=1")
c.Assert(err, IsNil)
err = validate.Field(arr, "eq=2")
c.Assert(err, NotNil)
c.Assert(func() { validate.Field(now, "eq=now") }, PanicMatches, "Bad field type time.Time")
}
func (ms *MySuite) TestBase64Validation(c *C) {
s := "dW5pY29ybg=="

Loading…
Cancel
Save