diff --git a/.travis.yml b/.travis.yml index 8ab4aed..389db22 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,14 +7,14 @@ on_failure: always go: - - 1.2 - 1.3 - 1.4 - tip - -before_install: - - go get github.com/axw/gocov/gocov + +script: + - go get golang.org/x/tools/cmd/cover - go get github.com/mattn/goveralls - - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi -script: - - $HOME/gopath/bin/goveralls -service=travis-ci + - go test -v -covermode=count -coverprofile=cover.out + +after_success: + - goveralls -coverprofile=cover.out -service=travis-ci -repotoken I6M8FiXZzErImgwMotJ7fwFlHOX8Hqdq1 \ No newline at end of file diff --git a/benchmarks_test.go b/benchmarks_test.go index 2517209..ee836c2 100644 --- a/benchmarks_test.go +++ b/benchmarks_test.go @@ -24,23 +24,23 @@ } } -// func BenchmarkTemplateParallelSimple(b *testing.B) { +func BenchmarkTemplateParallelSimple(b *testing.B) { -// type Foo struct { -// StringValue string `validate:"min=5,max=10"` -// IntValue int `validate:"min=5,max=10"` -// } + type Foo struct { + StringValue string `validate:"min=5,max=10"` + IntValue int `validate:"min=5,max=10"` + } -// validFoo := &Foo{StringValue: "Foobar", IntValue: 7} -// invalidFoo := &Foo{StringValue: "Fo", IntValue: 3} + validFoo := &Foo{StringValue: "Foobar", IntValue: 7} + invalidFoo := &Foo{StringValue: "Fo", IntValue: 3} -// b.RunParallel(func(pb *testing.PB) { -// for pb.Next() { -// validate.Struct(validFoo) -// validate.Struct(invalidFoo) -// } -// }) -// } + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + validate.Struct(validFoo) + validate.Struct(invalidFoo) + } + }) +} func BenchmarkValidateStructLarge(b *testing.B) { @@ -101,63 +101,63 @@ } } -// func BenchmarkTemplateParallelLarge(b *testing.B) { +func BenchmarkTemplateParallelLarge(b *testing.B) { -// tFail := &TestString{ -// Required: "", -// Len: "", -// Min: "", -// Max: "12345678901", -// MinMax: "", -// Lt: "0123456789", -// Lte: "01234567890", -// Gt: "1", -// Gte: "1", -// OmitEmpty: "12345678901", -// Sub: &SubTest{ -// Test: "", -// }, -// Anonymous: struct { -// A string `validate:"required"` -// }{ -// A: "", -// }, -// Iface: &Impl{ -// F: "12", -// }, -// } + tFail := &TestString{ + Required: "", + Len: "", + Min: "", + Max: "12345678901", + MinMax: "", + Lt: "0123456789", + Lte: "01234567890", + Gt: "1", + Gte: "1", + OmitEmpty: "12345678901", + Sub: &SubTest{ + Test: "", + }, + Anonymous: struct { + A string `validate:"required"` + }{ + A: "", + }, + Iface: &Impl{ + F: "12", + }, + } -// tSuccess := &TestString{ -// Required: "Required", -// Len: "length==10", -// Min: "min=1", -// Max: "1234567890", -// MinMax: "12345", -// Lt: "012345678", -// Lte: "0123456789", -// Gt: "01234567890", -// Gte: "0123456789", -// OmitEmpty: "", -// Sub: &SubTest{ -// Test: "1", -// }, -// SubIgnore: &SubTest{ -// Test: "", -// }, -// Anonymous: struct { -// A string `validate:"required"` -// }{ -// A: "1", -// }, -// Iface: &Impl{ -// F: "123", -// }, -// } + tSuccess := &TestString{ + Required: "Required", + Len: "length==10", + Min: "min=1", + Max: "1234567890", + MinMax: "12345", + Lt: "012345678", + Lte: "0123456789", + Gt: "01234567890", + Gte: "0123456789", + OmitEmpty: "", + Sub: &SubTest{ + Test: "1", + }, + SubIgnore: &SubTest{ + Test: "", + }, + Anonymous: struct { + A string `validate:"required"` + }{ + A: "1", + }, + Iface: &Impl{ + F: "123", + }, + } -// b.RunParallel(func(pb *testing.PB) { -// for pb.Next() { -// validate.Struct(tSuccess) -// validate.Struct(tFail) -// } -// }) -// } + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + validate.Struct(tSuccess) + validate.Struct(tFail) + } + }) +} diff --git a/validator.go b/validator.go index 64f0f85..b2ccb95 100644 --- a/validator.go +++ b/validator.go @@ -37,43 +37,13 @@ mapIndexFieldName = "%s[%v]" ) -var structPool *pool - -// Pool holds a channelStructErrors. -type pool struct { - pool chan *StructErrors -} - -// NewPool creates a new pool of Clients. -func newPool(max int) *pool { - return &pool{ - pool: make(chan *StructErrors, max), - } -} - -// Borrow a StructErrors from the pool. -func (p *pool) Borrow() *StructErrors { - var c *StructErrors - - select { - case c = <-p.pool: - default: - c = &StructErrors{ - Errors: map[string]*FieldError{}, - StructErrors: map[string]*StructErrors{}, - } - } - - return c -} - -// Return returns a StructErrors to the pool. -func (p *pool) Return(c *StructErrors) { - - select { - case p.pool <- c: - default: - // let it go, let it go... +var structPool *sync.Pool + +// returns new *StructErrors to the pool +func newStructErrors() interface{} { + return &StructErrors{ + Errors: map[string]*FieldError{}, + StructErrors: map[string]*StructErrors{}, } } @@ -357,7 +327,7 @@ // New creates a new Validate instance for use. func New(tagName string, funcs map[string]Func) *Validate { - structPool = newPool(10) + structPool = &sync.Pool{New: newStructErrors} return &Validate{ tagName: tagName, @@ -377,9 +347,8 @@ // nearly all cases. only increase if you have a deeply nested struct structure. // NOTE: this method is not thread-safe // NOTE: this is only here to keep compatibility with v5, in v6 the method will be removed -// and the max pool size will be passed into the New function func (v *Validate) SetMaxStructPoolSize(max int) { - structPool = newPool(max) + structPool = &sync.Pool{New: newStructErrors} } // AddFunction adds a validation Func to a Validate's map of validators denoted by the key @@ -440,7 +409,7 @@ cs = &cachedStruct{name: structName, children: numFields} } - validationErrors := structPool.Borrow() + validationErrors := structPool.Get().(*StructErrors) validationErrors.Struct = structName for i := 0; i < numFields; i++ { @@ -617,7 +586,7 @@ structCache.Set(structType, cs) if len(validationErrors.Errors) == 0 && len(validationErrors.StructErrors) == 0 { - structPool.Return(validationErrors) + structPool.Put(validationErrors) return nil }