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

pull/16/head
Dean Karn 10 years ago
commit 3637fdec01
  1. 24
      doc.go
  2. 33
      validator.go
  3. 71
      validator_test.go

@ -0,0 +1,24 @@
// Package validator implements value validations
//
// The MIT License (MIT)
//
// Copyright (c) 2015 Dean Karn
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package validator

@ -31,7 +31,7 @@ type FieldValidationError struct {
// This is intended for use in development + debugging and not intended to be a production error message. // This is intended for use in development + debugging and not intended to be a production error message.
// it also allows FieldValidationError to be used as an Error interface // it also allows FieldValidationError to be used as an Error interface
func (e FieldValidationError) Error() string { func (e *FieldValidationError) Error() string {
return fmt.Sprintf(validationFieldErrMsg, e.Field, e.ErrorTag) return fmt.Sprintf(validationFieldErrMsg, e.Field, e.ErrorTag)
} }
@ -48,7 +48,7 @@ type StructValidationErrors struct {
// This is intended for use in development + debugging and not intended to be a production error message. // This is intended for use in development + debugging and not intended to be a production error message.
// it also allows StructValidationErrors to be used as an Error interface // it also allows StructValidationErrors to be used as an Error interface
func (e StructValidationErrors) Error() string { func (e *StructValidationErrors) Error() string {
s := fmt.Sprintf(validationStructErrMsg, e.Struct) s := fmt.Sprintf(validationStructErrMsg, e.Struct)
@ -63,6 +63,35 @@ func (e StructValidationErrors) Error() string {
return fmt.Sprintf("%s\n\n", s) return fmt.Sprintf("%s\n\n", s)
} }
// Flatten flattens the StructValidationErrors hierarchical sctructure into a flat namespace style field name
// for those that want/need it
func (e *StructValidationErrors) Flatten() map[string]*FieldValidationError {
if e == nil {
return nil
}
errs := map[string]*FieldValidationError{}
for _, f := range e.Errors {
errs[f.Field] = f
}
for key, val := range e.StructErrors {
otherErrs := val.Flatten()
for _, f2 := range otherErrs {
f2.Field = fmt.Sprintf("%s.%s", key, f2.Field)
errs[f2.Field] = f2
}
}
return errs
}
// ValidationFunc that accepts the value of a field and parameter for use in validation (parameter not always used or needed) // ValidationFunc that accepts the value of a field and parameter for use in validation (parameter not always used or needed)
type ValidationFunc func(v interface{}, param string) bool type ValidationFunc func(v interface{}, param string) bool

@ -87,6 +87,72 @@ func AssertFieldError(s *validator.StructValidationErrors, field string, expecte
c.Assert(val.ErrorTag, Equals, expectedTag) c.Assert(val.ErrorTag, Equals, expectedTag)
} }
func AssertMapFieldError(s map[string]*validator.FieldValidationError, field string, expectedTag string, c *C) {
val, ok := s[field]
c.Assert(ok, Equals, true)
c.Assert(val, NotNil)
c.Assert(val.Field, Equals, field)
c.Assert(val.ErrorTag, Equals, expectedTag)
}
func (ms *MySuite) TestFlattening(c *C) {
tSuccess := &TestString{
Required: "Required",
Len: "length==10",
Min: "min=1",
Max: "1234567890",
MinMax: "12345",
OmitEmpty: "",
Sub: &SubTest{
Test: "1",
},
SubIgnore: &SubTest{
Test: "",
},
Anonymous: struct {
A string `validate:"required"`
}{
A: "1",
},
}
err1 := validator.ValidateStruct(tSuccess).Flatten()
c.Assert(err1, IsNil)
tFail := &TestString{
Required: "",
Len: "",
Min: "",
Max: "12345678901",
MinMax: "",
OmitEmpty: "12345678901",
Sub: &SubTest{
Test: "",
},
Anonymous: struct {
A string `validate:"required"`
}{
A: "",
},
}
err2 := validator.ValidateStruct(tFail).Flatten()
// Assert Top Level
c.Assert(err2, NotNil)
// Assert Fields
AssertMapFieldError(err2, "Len", "len", c)
// Assert Struct Field
AssertMapFieldError(err2, "Sub.Test", "required", c)
// Assert Anonymous Struct Field
AssertMapFieldError(err2, "Anonymous.A", "required", c)
}
func (ms *MySuite) TestStructStringValidation(c *C) { func (ms *MySuite) TestStructStringValidation(c *C) {
tSuccess := &TestString{ tSuccess := &TestString{
@ -132,6 +198,7 @@ func (ms *MySuite) TestStructStringValidation(c *C) {
err = validator.ValidateStruct(tFail) err = validator.ValidateStruct(tFail)
// Assert Top Level // Assert Top Level
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, 6)
c.Assert(len(err.StructErrors), Equals, 2) c.Assert(len(err.StructErrors), Equals, 2)
@ -181,6 +248,7 @@ func (ms *MySuite) TestStructInt32Validation(c *C) {
err = validator.ValidateStruct(tFail) err = validator.ValidateStruct(tFail)
// Assert Top Level // Assert Top Level
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, 6)
c.Assert(len(err.StructErrors), Equals, 0) c.Assert(len(err.StructErrors), Equals, 0)
@ -220,6 +288,7 @@ func (ms *MySuite) TestStructUint64Validation(c *C) {
err = validator.ValidateStruct(tFail) err = validator.ValidateStruct(tFail)
// Assert Top Level // Assert Top Level
c.Assert(err, NotNil)
c.Assert(err.Struct, Equals, "TestUint64") c.Assert(err.Struct, Equals, "TestUint64")
c.Assert(len(err.Errors), Equals, 6) c.Assert(len(err.Errors), Equals, 6)
c.Assert(len(err.StructErrors), Equals, 0) c.Assert(len(err.StructErrors), Equals, 0)
@ -259,6 +328,7 @@ func (ms *MySuite) TestStructFloat64Validation(c *C) {
err = validator.ValidateStruct(tFail) err = validator.ValidateStruct(tFail)
// Assert Top Level // Assert Top Level
c.Assert(err, NotNil)
c.Assert(err.Struct, Equals, "TestFloat64") c.Assert(err.Struct, Equals, "TestFloat64")
c.Assert(len(err.Errors), Equals, 6) c.Assert(len(err.Errors), Equals, 6)
c.Assert(len(err.StructErrors), Equals, 0) c.Assert(len(err.StructErrors), Equals, 0)
@ -298,6 +368,7 @@ func (ms *MySuite) TestStructSliceValidation(c *C) {
err = validator.ValidateStruct(tFail) err = validator.ValidateStruct(tFail)
// Assert Top Level // Assert Top Level
c.Assert(err, NotNil)
c.Assert(err.Struct, Equals, "TestSlice") c.Assert(err.Struct, Equals, "TestSlice")
c.Assert(len(err.Errors), Equals, 6) c.Assert(len(err.Errors), Equals, 6)
c.Assert(len(err.StructErrors), Equals, 0) c.Assert(len(err.StructErrors), Equals, 0)

Loading…
Cancel
Save