Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,9 @@ How to Contribute
There will always be a development branch for each version i.e. `v1-development`. In order to contribute,
please make your pull requests against those branches.

If the changes being proposed or requested are breaking changes, please create an issue, for discussion
or create a pull request against the highest development branch for example this package has a
v1 and v1-development branch however, there will also be a v2-development brach even though v2 doesn't exist yet.
If the changes being proposed or requested are breaking changes, please create an issue, for discussion
or create a pull request against the highest development branch for example this package has a
v1 and v1-development branch however, there will also be a v2-development branch even though v2 doesn't exist yet.

I strongly encourage everyone whom creates a custom validation function to contribute them and
help make this package even better.
Expand Down
26 changes: 21 additions & 5 deletions validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ func New(config Config) *Validate {
// NOTE: if the key already exists, the previous validation function will be replaced.
// NOTE: this method is not thread-safe
func (v *Validate) RegisterValidation(key string, f Func) error {

if v == nil {
panic("Validate.RegisterValidation called with nil receiver")
}
if len(key) == 0 {
return errors.New("Function Key cannot be empty")
}
Expand All @@ -162,6 +164,9 @@ func (v *Validate) RegisterValidation(key string, f Func) error {

// RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types
func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) {
if v == nil {
panic("Validate.RegisterCustomTypeFunc called with nil receiver")
}

if v.config.CustomTypeFuncs == nil {
v.config.CustomTypeFuncs = map[reflect.Type]CustomTypeFunc{}
Expand All @@ -178,7 +183,9 @@ func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{
// NOTE: it returns ValidationErrors instead of a single FieldError because this can also
// validate Array, Slice and maps fields which may contain more than one error
func (v *Validate) Field(field interface{}, tag string) ValidationErrors {

if v == nil {
panic("Validate.Field called with nil receiver")
}
errs := errsPool.Get().(ValidationErrors)
fieldVal := reflect.ValueOf(field)

Expand All @@ -196,6 +203,9 @@ func (v *Validate) Field(field interface{}, tag string) ValidationErrors {
// NOTE: it returns ValidationErrors instead of a single FieldError because this can also
// validate Array, Slice and maps fields which may contain more than one error
func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string) ValidationErrors {
if v == nil {
panic("Validate.FieldWithValue called with nil receiver")
}

errs := errsPool.Get().(ValidationErrors)
topVal := reflect.ValueOf(val)
Expand All @@ -216,7 +226,9 @@ func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string
// 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 {

if v == nil {
panic("Validate.StructPartial called with nil receiver")
}
sv, _ := v.extractType(reflect.ValueOf(current))
name := sv.Type().Name()
m := map[string]*struct{}{}
Expand Down Expand Up @@ -274,7 +286,9 @@ func (v *Validate) StructPartial(current interface{}, fields ...string) Validati
// 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 {

if v == nil {
panic("Validate.StructExcept called with nil receiver")
}
sv, _ := v.extractType(reflect.ValueOf(current))
name := sv.Type().Name()
m := map[string]*struct{}{}
Expand All @@ -297,7 +311,9 @@ func (v *Validate) StructExcept(current interface{}, fields ...string) Validatio

// Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified.
func (v *Validate) Struct(current interface{}) ValidationErrors {

if v == nil {
panic("Validate.Struct called with nil receiver")
}
errs := errsPool.Get().(ValidationErrors)
sv := reflect.ValueOf(current)

Expand Down
25 changes: 25 additions & 0 deletions validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,31 @@ type TestPartial struct {
}
}

func TestNilValidator(t *testing.T) {

type TestStruct struct {
Test string `validate:"required"`
}

ts := TestStruct{}

var val *Validate

fn := func(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {

return current.String() == field.String()
}

PanicMatches(t, func() { val.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) }, "Validate.RegisterCustomTypeFunc called with nil receiver")
PanicMatches(t, func() { val.RegisterValidation("something", fn) }, "Validate.RegisterValidation called with nil receiver")
PanicMatches(t, func() { val.Field(ts.Test, "required") }, "Validate.Field called with nil receiver")
PanicMatches(t, func() { val.FieldWithValue("test", ts.Test, "required") }, "Validate.FieldWithValue called with nil receiver")
PanicMatches(t, func() { val.Struct(ts) }, "Validate.Struct called with nil receiver")
PanicMatches(t, func() { val.StructExcept(ts, "Test") }, "Validate.StructExcept called with nil receiver")
PanicMatches(t, func() { val.StructPartial(ts, "Test") }, "Validate.StructPartial called with nil receiver")

}

func TestStructPartial(t *testing.T) {

p1 := []string{
Expand Down