Merge branch 'issue-#1' into v1-development

pull/16/head
Dean Karn 10 years ago
commit 53ffdb7742
  1. 116
      baked_in.go
  2. 21
      doc.go
  3. 40
      validator_test.go

@ -13,6 +13,10 @@ var BakedInValidators = map[string]ValidationFunc{
"len": length, "len": length,
"min": min, "min": min,
"max": max, "max": max,
"lt": lt,
"lte": lte,
"gt": gt,
"gte": gte,
"alpha": alpha, "alpha": alpha,
"alphanum": alphanum, "alphanum": alphanum,
"numeric": numeric, "numeric": numeric,
@ -183,6 +187,78 @@ func required(field interface{}, param string) bool {
} }
} }
func gte(field interface{}, param string) bool {
st := reflect.ValueOf(field)
switch st.Kind() {
case reflect.String:
p := asInt(param)
return int64(len(st.String())) >= p
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
default:
panic(fmt.Sprintf("Bad field type for Input Param %s for %s\n", param, field))
}
}
func gt(field interface{}, param string) bool {
st := reflect.ValueOf(field)
switch st.Kind() {
case reflect.String:
p := asInt(param)
return int64(len(st.String())) > p
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
default:
panic(fmt.Sprintf("Bad field type for Input Param %s for %s\n", param, 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
// value. For strings it tests the number of characters whereas // value. For strings it tests the number of characters whereas
// for maps and slices it tests the number of items. // for maps and slices it tests the number of items.
@ -228,6 +304,11 @@ func length(field interface{}, param string) bool {
// and slices it tests the number of items. // and slices it tests the number of items.
func min(field interface{}, param string) bool { func min(field interface{}, param string) bool {
return gte(field, param)
}
func lte(field interface{}, param string) bool {
st := reflect.ValueOf(field) st := reflect.ValueOf(field)
switch st.Kind() { switch st.Kind() {
@ -235,38 +316,34 @@ func min(field interface{}, param string) bool {
case reflect.String: case reflect.String:
p := asInt(param) p := asInt(param)
return int64(len(st.String())) >= p return int64(len(st.String())) <= p
case reflect.Slice, reflect.Map, reflect.Array: case reflect.Slice, reflect.Map, reflect.Array:
p := asInt(param) p := asInt(param)
return int64(st.Len()) >= p return int64(st.Len()) <= p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p := asInt(param) p := asInt(param)
return st.Int() >= p return st.Int() <= p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p := asUint(param) p := asUint(param)
return st.Uint() >= p return st.Uint() <= p
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
p := asFloat(param) p := asFloat(param)
return st.Float() >= p return st.Float() <= p
default: default:
panic(fmt.Sprintf("Bad field type for Input Param %s for %s\n", param, field)) panic(fmt.Sprintf("Bad field type for Input Param %s for %s\n", param, field))
} }
} }
// max tests whether a variable value is lesser than a given func lt(field interface{}, param string) bool {
// value. For numbers, it's a simple lesser-than test; for
// strings it tests the number of characters whereas for maps
// and slices it tests the number of items.
func max(field interface{}, param string) bool {
st := reflect.ValueOf(field) st := reflect.ValueOf(field)
@ -275,33 +352,42 @@ func max(field interface{}, param string) bool {
case reflect.String: case reflect.String:
p := asInt(param) p := asInt(param)
return int64(len(st.String())) <= p return int64(len(st.String())) < p
case reflect.Slice, reflect.Map, reflect.Array: case reflect.Slice, reflect.Map, reflect.Array:
p := asInt(param) p := asInt(param)
return int64(st.Len()) <= p return int64(st.Len()) < p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p := asInt(param) p := asInt(param)
return st.Int() <= p return st.Int() < p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p := asUint(param) p := asUint(param)
return st.Uint() <= p return st.Uint() < p
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
p := asFloat(param) p := asFloat(param)
return st.Float() <= p return st.Float() < p
default: default:
panic(fmt.Sprintf("Bad field type for Input Param %s for %s\n", param, field)) panic(fmt.Sprintf("Bad field type for Input Param %s for %s\n", param, field))
} }
} }
// max tests whether a variable value is lesser than a given
// value. For numbers, it's a simple lesser-than test; for
// strings it tests the number of characters whereas for maps
// and slices it tests the number of items.
func max(field interface{}, param string) bool {
return lte(field, param)
}
// asInt retuns the parameter as a int64 // asInt retuns the parameter as a int64
// or panics if it can't convert // or panics if it can't convert
func asInt(param string) int64 { func asInt(param string) int64 {

@ -163,6 +163,27 @@ Here is a list of the current built in validators:
the string length is at least that number of characters. For slices, the string length is at least that number of characters. For slices,
arrays, and maps, validates the number of items. (Usage: min=10) arrays, and maps, validates the number of items. (Usage: min=10)
gt
For numbers, this will ensure that the value is greater than the
parameter given. For strings, it checks that the string length
is greater than that number of characters. For slices, arrays
and maps it validates the number of items. (Usage: gt=10)
gte
Same as 'min' above. Kept both to make terminology with 'len' easier
(Usage: gte=10)
lt
For numbers, this will ensure that the value is
less than the parameter given. For strings, it checks
that the string length is less than that number of characters.
For slices, arrays, and maps it validates the number of items.
(Usage: lt=10)
lte
Same as 'max' above. Kept both to make terminology with 'len' easier
(Usage: lte=10)
alpha alpha
This validates that a strings value contains alpha characters only This validates that a strings value contains alpha characters only
(Usage: alpha) (Usage: alpha)

@ -34,6 +34,10 @@ type TestString struct {
Min string `validate:"min=1"` Min string `validate:"min=1"`
Max string `validate:"max=10"` Max string `validate:"max=10"`
MinMax string `validate:"min=1,max=10"` MinMax string `validate:"min=1,max=10"`
Lt string `validate:"lt=10"`
Lte string `validate:"lte=10"`
Gt string `validate:"gt=10"`
Gte string `validate:"gte=10"`
OmitEmpty string `validate:"omitempty,min=1,max=10"` OmitEmpty string `validate:"omitempty,min=1,max=10"`
Sub *SubTest Sub *SubTest
SubIgnore *SubTest `validate:"-"` SubIgnore *SubTest `validate:"-"`
@ -49,6 +53,10 @@ type TestInt32 struct {
Min int `validate:"min=1"` Min int `validate:"min=1"`
Max int `validate:"max=10"` Max int `validate:"max=10"`
MinMax int `validate:"min=1,max=10"` MinMax int `validate:"min=1,max=10"`
Lt int `validate:"lt=10"`
Lte int `validate:"lte=10"`
Gt int `validate:"gt=10"`
Gte int `validate:"gte=10"`
OmitEmpty int `validate:"omitempty,min=1,max=10"` OmitEmpty int `validate:"omitempty,min=1,max=10"`
} }
@ -425,6 +433,10 @@ func (ms *MySuite) TestFlattening(c *C) {
Min: "min=1", Min: "min=1",
Max: "1234567890", Max: "1234567890",
MinMax: "12345", MinMax: "12345",
Lt: "012345678",
Lte: "0123456789",
Gt: "01234567890",
Gte: "0123456789",
OmitEmpty: "", OmitEmpty: "",
Sub: &SubTest{ Sub: &SubTest{
Test: "1", Test: "1",
@ -472,6 +484,8 @@ func (ms *MySuite) TestFlattening(c *C) {
// Assert Fields // Assert Fields
AssertMapFieldError(err2, "Len", "len", c) AssertMapFieldError(err2, "Len", "len", c)
AssertMapFieldError(err2, "Gt", "gt", c)
AssertMapFieldError(err2, "Gte", "gte", c)
// Assert Struct Field // Assert Struct Field
AssertMapFieldError(err2, "Sub.Test", "required", c) AssertMapFieldError(err2, "Sub.Test", "required", c)
@ -491,6 +505,10 @@ func (ms *MySuite) TestStructStringValidation(c *C) {
Min: "min=1", Min: "min=1",
Max: "1234567890", Max: "1234567890",
MinMax: "12345", MinMax: "12345",
Lt: "012345678",
Lte: "0123456789",
Gt: "01234567890",
Gte: "0123456789",
OmitEmpty: "", OmitEmpty: "",
Sub: &SubTest{ Sub: &SubTest{
Test: "1", Test: "1",
@ -517,6 +535,10 @@ func (ms *MySuite) TestStructStringValidation(c *C) {
Min: "", Min: "",
Max: "12345678901", Max: "12345678901",
MinMax: "", MinMax: "",
Lt: "0123456789",
Lte: "01234567890",
Gt: "1",
Gte: "1",
OmitEmpty: "12345678901", OmitEmpty: "12345678901",
Sub: &SubTest{ Sub: &SubTest{
Test: "", Test: "",
@ -536,7 +558,7 @@ func (ms *MySuite) TestStructStringValidation(c *C) {
// Assert Top Level // Assert Top Level
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Struct, Equals, "TestString") c.Assert(err.Struct, Equals, "TestString")
c.Assert(len(err.Errors), Equals, 6) c.Assert(len(err.Errors), Equals, 10)
c.Assert(len(err.StructErrors), Equals, 3) c.Assert(len(err.StructErrors), Equals, 3)
// Assert Fields // Assert Fields
@ -545,6 +567,8 @@ func (ms *MySuite) TestStructStringValidation(c *C) {
AssertFieldError(err, "Min", "min", c) AssertFieldError(err, "Min", "min", c)
AssertFieldError(err, "Max", "max", c) AssertFieldError(err, "Max", "max", c)
AssertFieldError(err, "MinMax", "min", c) AssertFieldError(err, "MinMax", "min", c)
AssertFieldError(err, "Gt", "gt", c)
AssertFieldError(err, "Gte", "gte", c)
AssertFieldError(err, "OmitEmpty", "max", c) AssertFieldError(err, "OmitEmpty", "max", c)
// Assert Anonymous embedded struct // Assert Anonymous embedded struct
@ -566,6 +590,10 @@ func (ms *MySuite) TestStructInt32Validation(c *C) {
Min: 1, Min: 1,
Max: 10, Max: 10,
MinMax: 5, MinMax: 5,
Lt: 9,
Lte: 10,
Gt: 11,
Gte: 10,
OmitEmpty: 0, OmitEmpty: 0,
} }
@ -578,6 +606,10 @@ func (ms *MySuite) TestStructInt32Validation(c *C) {
Min: -1, Min: -1,
Max: 11, Max: 11,
MinMax: -1, MinMax: -1,
Lt: 10,
Lte: 11,
Gt: 10,
Gte: 9,
OmitEmpty: 11, OmitEmpty: 11,
} }
@ -586,7 +618,7 @@ func (ms *MySuite) TestStructInt32Validation(c *C) {
// Assert Top Level // Assert Top Level
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Struct, Equals, "TestInt32") c.Assert(err.Struct, Equals, "TestInt32")
c.Assert(len(err.Errors), Equals, 6) c.Assert(len(err.Errors), Equals, 10)
c.Assert(len(err.StructErrors), Equals, 0) c.Assert(len(err.StructErrors), Equals, 0)
// Assert Fields // Assert Fields
@ -595,6 +627,10 @@ func (ms *MySuite) TestStructInt32Validation(c *C) {
AssertFieldError(err, "Min", "min", c) AssertFieldError(err, "Min", "min", c)
AssertFieldError(err, "Max", "max", c) AssertFieldError(err, "Max", "max", c)
AssertFieldError(err, "MinMax", "min", c) AssertFieldError(err, "MinMax", "min", c)
AssertFieldError(err, "Lt", "lt", c)
AssertFieldError(err, "Lte", "lte", c)
AssertFieldError(err, "Gt", "gt", c)
AssertFieldError(err, "Gte", "gte", c)
AssertFieldError(err, "OmitEmpty", "max", c) AssertFieldError(err, "OmitEmpty", "max", c)
} }

Loading…
Cancel
Save