From 5b14fca011ed8b7dea7cc69c77eeaa69af086439 Mon Sep 17 00:00:00 2001 From: andreas Date: Fri, 2 Nov 2018 22:17:07 +0800 Subject: [PATCH 1/3] Returns error when passing pointer to RegisterStructValidation --- validator_instance.go | 16 +++++++++++++--- validator_test.go | 10 ++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/validator_instance.go b/validator_instance.go index 08638ae..10b9da2 100644 --- a/validator_instance.go +++ b/validator_instance.go @@ -189,26 +189,36 @@ func (v *Validate) RegisterAlias(alias, tags string) { // RegisterStructValidation registers a StructLevelFunc against a number of types. // +// It returns error when type being passed is a pointer. // NOTE: // - this method is not thread-safe it is intended that these all be registered prior to any validation -func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) { - v.RegisterStructValidationCtx(wrapStructLevelFunc(fn), types...) +func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) error { + return v.RegisterStructValidationCtx(wrapStructLevelFunc(fn), types...) } // RegisterStructValidationCtx registers a StructLevelFuncCtx against a number of types and allows passing // of contextual validation information via context.Context. // +// It returns error when type being passed is a pointer. // NOTE: // - this method is not thread-safe it is intended that these all be registered prior to any validation -func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...interface{}) { +func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...interface{}) error { if v.structLevelFuncs == nil { v.structLevelFuncs = make(map[reflect.Type]StructLevelFuncCtx) } + for _, t := range types { + if reflect.ValueOf(t).Kind() == reflect.Ptr { + return fmt.Errorf("error") + } + } + for _, t := range types { v.structLevelFuncs[reflect.TypeOf(t)] = fn } + + return nil } // RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types diff --git a/validator_test.go b/validator_test.go index 2efabc5..3d6692c 100644 --- a/validator_test.go +++ b/validator_test.go @@ -8149,3 +8149,13 @@ func TestKeyOrs(t *testing.T) { AssertDeepError(t, errs, "Test2.Test1[badtestkey]", "Test2.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "okkey", "eq=testkey|eq=testkeyok") AssertDeepError(t, errs, "Test2.Test1[badtestkey]", "Test2.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") } + +func TestStructLevelValidationsPointerPassing(t *testing.T) { + v1 := New() + err1 := v1.RegisterStructValidation(StructValidationTestStruct, &TestStruct{}) + NotEqual(t, err1, nil) + + v2 := New() + err2 := v2.RegisterStructValidation(StructValidationTestStruct, TestStruct{}) + Equal(t, err2, nil) +} From 9eeca291366572aeb158efd75a7435d1e8b05588 Mon Sep 17 00:00:00 2001 From: andreas Date: Sat, 3 Nov 2018 06:52:33 +0800 Subject: [PATCH 2/3] detail error message on RegisterStructValidationCtx finding pointer arg --- validator_instance.go | 4 +++- validator_test.go | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/validator_instance.go b/validator_instance.go index 10b9da2..29a22ba 100644 --- a/validator_instance.go +++ b/validator_instance.go @@ -210,7 +210,9 @@ func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...i for _, t := range types { if reflect.ValueOf(t).Kind() == reflect.Ptr { - return fmt.Errorf("error") + return fmt.Errorf( + "Type must be a non-pointer, %s is a pointer", + reflect.TypeOf(t)) } } diff --git a/validator_test.go b/validator_test.go index 3d6692c..5763cc7 100644 --- a/validator_test.go +++ b/validator_test.go @@ -8154,6 +8154,8 @@ func TestStructLevelValidationsPointerPassing(t *testing.T) { v1 := New() err1 := v1.RegisterStructValidation(StructValidationTestStruct, &TestStruct{}) NotEqual(t, err1, nil) + Equal(t, err1.Error(), + "Type must be a non-pointer, *validator.TestStruct is a pointer") v2 := New() err2 := v2.RegisterStructValidation(StructValidationTestStruct, TestStruct{}) From 8ed00e2e122ca07de1a5489b8f0b451fa9010af1 Mon Sep 17 00:00:00 2001 From: andreas Date: Sat, 3 Nov 2018 09:36:56 +0800 Subject: [PATCH 3/3] Change behavior instead of error, we Indirect it to get the non-pointer value --- validator_instance.go | 19 ++++++------------- validator_test.go | 15 ++++++++------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/validator_instance.go b/validator_instance.go index 29a22ba..fc9db5a 100644 --- a/validator_instance.go +++ b/validator_instance.go @@ -189,38 +189,31 @@ func (v *Validate) RegisterAlias(alias, tags string) { // RegisterStructValidation registers a StructLevelFunc against a number of types. // -// It returns error when type being passed is a pointer. // NOTE: // - this method is not thread-safe it is intended that these all be registered prior to any validation -func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) error { - return v.RegisterStructValidationCtx(wrapStructLevelFunc(fn), types...) +func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) { + v.RegisterStructValidationCtx(wrapStructLevelFunc(fn), types...) } // RegisterStructValidationCtx registers a StructLevelFuncCtx against a number of types and allows passing // of contextual validation information via context.Context. // -// It returns error when type being passed is a pointer. // NOTE: // - this method is not thread-safe it is intended that these all be registered prior to any validation -func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...interface{}) error { +func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...interface{}) { if v.structLevelFuncs == nil { v.structLevelFuncs = make(map[reflect.Type]StructLevelFuncCtx) } for _, t := range types { - if reflect.ValueOf(t).Kind() == reflect.Ptr { - return fmt.Errorf( - "Type must be a non-pointer, %s is a pointer", - reflect.TypeOf(t)) + tv := reflect.ValueOf(t) + if tv.Kind() == reflect.Ptr { + t = reflect.Indirect(tv).Interface() } - } - for _, t := range types { v.structLevelFuncs[reflect.TypeOf(t)] = fn } - - return nil } // RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types diff --git a/validator_test.go b/validator_test.go index 5763cc7..3a4b8f0 100644 --- a/validator_test.go +++ b/validator_test.go @@ -8152,12 +8152,13 @@ func TestKeyOrs(t *testing.T) { func TestStructLevelValidationsPointerPassing(t *testing.T) { v1 := New() - err1 := v1.RegisterStructValidation(StructValidationTestStruct, &TestStruct{}) - NotEqual(t, err1, nil) - Equal(t, err1.Error(), - "Type must be a non-pointer, *validator.TestStruct is a pointer") + v1.RegisterStructValidation(StructValidationTestStruct, &TestStruct{}) - v2 := New() - err2 := v2.RegisterStructValidation(StructValidationTestStruct, TestStruct{}) - Equal(t, err2, nil) + tst := &TestStruct{ + String: "good value", + } + + errs := v1.Struct(tst) + NotEqual(t, errs, nil) + AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct") }