Updates + Benchmarks

update documentation.
add benchmarks for StructPartial, dive tag, cross field and cross struct cross field.
pull/161/head
joeybloggs 9 years ago
parent 4f46e02133
commit 883731a774
  1. 194
      benchmarks_test.go
  2. 4
      validator.go

@ -4,6 +4,7 @@ import (
sql "database/sql/driver" sql "database/sql/driver"
"reflect" "reflect"
"testing" "testing"
"time"
) )
func BenchmarkFieldSuccess(b *testing.B) { func BenchmarkFieldSuccess(b *testing.B) {
@ -18,6 +19,18 @@ func BenchmarkFieldFailure(b *testing.B) {
} }
} }
func BenchmarkFieldDiveSuccess(b *testing.B) {
for n := 0; n < b.N; n++ {
validate.Field([]string{"val1", "val2", "val3"}, "required,dive,required")
}
}
func BenchmarkFieldDiveFailure(b *testing.B) {
for n := 0; n < b.N; n++ {
validate.Field([]string{"val1", "", "val3"}, "required,dive,required")
}
}
func BenchmarkFieldCustomTypeSuccess(b *testing.B) { func BenchmarkFieldCustomTypeSuccess(b *testing.B) {
customTypes := map[reflect.Type]CustomTypeFunc{} customTypes := map[reflect.Type]CustomTypeFunc{}
@ -62,35 +75,31 @@ func BenchmarkFieldOrTagFailure(b *testing.B) {
} }
} }
func BenchmarkStructSimpleSuccess(b *testing.B) { func BenchmarkStructSimpleCustomTypeSuccess(b *testing.B) {
type Foo struct { customTypes := map[reflect.Type]CustomTypeFunc{}
StringValue string `validate:"min=5,max=10"` customTypes[reflect.TypeOf((*sql.Valuer)(nil))] = ValidateValuerType
IntValue int `validate:"min=5,max=10"` customTypes[reflect.TypeOf(valuer{})] = ValidateValuerType
}
validFoo := &Foo{StringValue: "Foobar", IntValue: 7} validate := New(Config{TagName: "validate", ValidationFuncs: BakedInValidators, CustomTypeFuncs: customTypes})
for n := 0; n < b.N; n++ { val := valuer{
validate.Struct(validFoo) Name: "1",
}
} }
func BenchmarkStructSimpleFailure(b *testing.B) {
type Foo struct { type Foo struct {
StringValue string `validate:"min=5,max=10"` Valuer valuer `validate:"len=1"`
IntValue int `validate:"min=5,max=10"` IntValue int `validate:"min=5,max=10"`
} }
invalidFoo := &Foo{StringValue: "Fo", IntValue: 3} validFoo := &Foo{Valuer: val, IntValue: 7}
for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {
validate.Struct(invalidFoo) validate.Struct(validFoo)
} }
} }
func BenchmarkStructSimpleCustomTypeSuccess(b *testing.B) { func BenchmarkStructSimpleCustomTypeFailure(b *testing.B) {
customTypes := map[reflect.Type]CustomTypeFunc{} customTypes := map[reflect.Type]CustomTypeFunc{}
customTypes[reflect.TypeOf((*sql.Valuer)(nil))] = ValidateValuerType customTypes[reflect.TypeOf((*sql.Valuer)(nil))] = ValidateValuerType
@ -98,44 +107,175 @@ func BenchmarkStructSimpleCustomTypeSuccess(b *testing.B) {
validate := New(Config{TagName: "validate", ValidationFuncs: BakedInValidators, CustomTypeFuncs: customTypes}) validate := New(Config{TagName: "validate", ValidationFuncs: BakedInValidators, CustomTypeFuncs: customTypes})
val := valuer{ val := valuer{}
Name: "1",
}
type Foo struct { type Foo struct {
Valuer valuer `validate:"len=1"` Valuer valuer `validate:"len=1"`
IntValue int `validate:"min=5,max=10"` IntValue int `validate:"min=5,max=10"`
} }
validFoo := &Foo{Valuer: val, IntValue: 7} validFoo := &Foo{Valuer: val, IntValue: 3}
for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {
validate.Struct(validFoo) validate.Struct(validFoo)
} }
} }
func BenchmarkStructSimpleCustomTypeFailure(b *testing.B) { func BenchmarkStructPartialSuccess(b *testing.B) {
customTypes := map[reflect.Type]CustomTypeFunc{} type Test struct {
customTypes[reflect.TypeOf((*sql.Valuer)(nil))] = ValidateValuerType Name string `validate:"required"`
customTypes[reflect.TypeOf(valuer{})] = ValidateValuerType NickName string `validate:"required"`
}
validate := New(Config{TagName: "validate", ValidationFuncs: BakedInValidators, CustomTypeFuncs: customTypes}) test := &Test{
Name: "Joey Bloggs",
}
val := valuer{} for n := 0; n < b.N; n++ {
validate.StructPartial(test, "Name")
}
}
func BenchmarkStructPartialFailure(b *testing.B) {
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
}
test := &Test{
Name: "Joey Bloggs",
}
for n := 0; n < b.N; n++ {
validate.StructPartial(test, "NickName")
}
}
func BenchmarkStructSimpleCrossFieldSuccess(b *testing.B) {
type Test struct {
Start time.Time
End time.Time `validate:"gtfield=Start"`
}
now := time.Now().UTC()
then := now.Add(time.Hour * 5)
test := &Test{
Start: now,
End: then,
}
for n := 0; n < b.N; n++ {
validate.Struct(test)
}
}
func BenchmarkStructSimpleCrossFieldFailure(b *testing.B) {
type Test struct {
Start time.Time
End time.Time `validate:"gtfield=Start"`
}
now := time.Now().UTC()
then := now.Add(time.Hour * -5)
test := &Test{
Start: now,
End: then,
}
for n := 0; n < b.N; n++ {
validate.Struct(test)
}
}
func BenchmarkStructSimpleCrossStructCrossFieldSuccess(b *testing.B) {
type Inner struct {
Start time.Time
}
type Outer struct {
Inner *Inner
CreatedAt time.Time `validate:"eqcsfield=Inner.Start"`
}
now := time.Now().UTC()
inner := &Inner{
Start: now,
}
outer := &Outer{
Inner: inner,
CreatedAt: now,
}
for n := 0; n < b.N; n++ {
validate.Struct(outer)
}
}
func BenchmarkStructSimpleCrossStructCrossFieldFailure(b *testing.B) {
type Inner struct {
Start time.Time
}
type Outer struct {
Inner *Inner
CreatedAt time.Time `validate:"eqcsfield=Inner.Start"`
}
now := time.Now().UTC()
then := now.Add(time.Hour * 5)
inner := &Inner{
Start: then,
}
outer := &Outer{
Inner: inner,
CreatedAt: now,
}
for n := 0; n < b.N; n++ {
validate.Struct(outer)
}
}
func BenchmarkStructSimpleSuccess(b *testing.B) {
type Foo struct { type Foo struct {
Valuer valuer `validate:"len=1"` StringValue string `validate:"min=5,max=10"`
IntValue int `validate:"min=5,max=10"` IntValue int `validate:"min=5,max=10"`
} }
validFoo := &Foo{Valuer: val, IntValue: 3} validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {
validate.Struct(validFoo) validate.Struct(validFoo)
} }
} }
func BenchmarkStructSimpleFailure(b *testing.B) {
type Foo struct {
StringValue string `validate:"min=5,max=10"`
IntValue int `validate:"min=5,max=10"`
}
invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
for n := 0; n < b.N; n++ {
validate.Struct(invalidFoo)
}
}
func BenchmarkStructSimpleSuccessParallel(b *testing.B) { func BenchmarkStructSimpleSuccessParallel(b *testing.B) {
type Foo struct { type Foo struct {

@ -213,6 +213,8 @@ func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string
// StructPartial validates the fields passed in only, ignoring all others. // StructPartial validates the fields passed in only, ignoring all others.
// Fields may be provided in a namespaced fashion relative to the struct provided // Fields may be provided in a namespaced fashion relative to the struct provided
// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name // i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
// NOTE: This is normally not needed, however in some specific cases such as: tied to a
// legacy data structure, it will be useful
func (v *Validate) StructPartial(current interface{}, fields ...string) ValidationErrors { func (v *Validate) StructPartial(current interface{}, fields ...string) ValidationErrors {
sv, _ := v.extractType(reflect.ValueOf(current)) sv, _ := v.extractType(reflect.ValueOf(current))
@ -269,6 +271,8 @@ func (v *Validate) StructPartial(current interface{}, fields ...string) Validati
// StructExcept validates all fields except the ones passed in. // StructExcept validates all fields except the ones passed in.
// Fields may be provided in a namespaced fashion relative to the struct provided // Fields may be provided in a namespaced fashion relative to the struct provided
// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name // i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
// NOTE: This is normally not needed, however in some specific cases such as: tied to a
// legacy data structure, it will be useful
func (v *Validate) StructExcept(current interface{}, fields ...string) ValidationErrors { func (v *Validate) StructExcept(current interface{}, fields ...string) ValidationErrors {
sv, _ := v.extractType(reflect.ValueOf(current)) sv, _ := v.extractType(reflect.ValueOf(current))

Loading…
Cancel
Save