From 3ca5c65a991b34fd23d73354a3144e4de9b88cd4 Mon Sep 17 00:00:00 2001 From: Dominik Wojciechowski Date: Wed, 3 Jul 2024 09:49:20 +0200 Subject: [PATCH] Change to allow multiple errors be returned from single field when option "WithMultipleErrorsReturned" is set. --- options.go | 10 +++++ validator.go | 16 ++++++-- validator_instance.go | 1 + validator_test.go | 95 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 4 deletions(-) diff --git a/options.go b/options.go index 86a0db21..3ddd284e 100644 --- a/options.go +++ b/options.go @@ -24,3 +24,13 @@ func WithPrivateFieldValidation() Option { v.privateFieldValidation = true } } + +// WithMultipleErrorsReturned enables multi error return from a single struct field. +// +// By opting into this feature you are acknowledging that you are aware of the risks and accept any current or future +// consequences of using this feature. +func WithMultipleErrorsReturned() Option { + return func(v *Validate) { + v.multipleErrorsReturned = true + } +} diff --git a/validator.go b/validator.go index 901e7b50..6935e17d 100644 --- a/validator.go +++ b/validator.go @@ -138,7 +138,9 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr kind: kind, }, ) - return + if !v.Validator().multipleErrorsReturned { + return + } } v.str1 = string(append(ns, cf.altName...)) @@ -163,7 +165,9 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr typ: current.Type(), }, ) - return + if !v.Validator().multipleErrorsReturned { + return + } } } @@ -439,7 +443,9 @@ OUTER: ) } - return + if !v.Validator().multipleErrorsReturned { + return + } } ct = ct.next @@ -478,7 +484,9 @@ OUTER: }, ) - return + if !v.Validator().multipleErrorsReturned { + return + } } ct = ct.next } diff --git a/validator_instance.go b/validator_instance.go index d9f148db..c761bc99 100644 --- a/validator_instance.go +++ b/validator_instance.go @@ -95,6 +95,7 @@ type Validate struct { hasTagNameFunc bool requiredStructEnabled bool privateFieldValidation bool + multipleErrorsReturned bool } // New returns a new instance of 'validate' with sane defaults. diff --git a/validator_test.go b/validator_test.go index 0f96b777..bb3a9999 100644 --- a/validator_test.go +++ b/validator_test.go @@ -14001,3 +14001,98 @@ func TestPrivateFieldsStruct(t *testing.T) { Equal(t, len(errs), tc.errorNum) } } + +func TestMultipleErrorsOption(t *testing.T) { + type tc struct { + stct interface{} + errorNum int + } + + tcs := []tc{ + { + stct: &struct { + F1 int8 `validate:"eq=10,gte=10"` + F2 int16 `validate:"eq=10,gte=10"` + F3 int32 `validate:"eq=10,gte=10"` + F4 int64 `validate:"eq=10,gte=10"` + }{}, + errorNum: 8, + }, + { + stct: &struct { + F1 uint8 `validate:"eq=10,gte=10"` + F2 uint16 `validate:"eq=10,gte=10"` + F3 uint32 `validate:"eq=10,gte=10"` + F4 uint64 `validate:"eq=10,gte=10"` + }{}, + errorNum: 8, + }, + { + stct: &struct { + F1 string `validate:"eq=10,gte=10"` + F2 string `validate:"eq=10,gte=10"` + }{}, + errorNum: 4, + }, + { + stct: &struct { + F1 float32 `validate:"eq=10,gte=10"` + F2 float64 `validate:"eq=10,gte=10"` + }{}, + errorNum: 4, + }, + { + stct: struct { + F1 int8 `validate:"eq=10,gte=10"` + F2 int16 `validate:"eq=10,gte=10"` + F3 int32 `validate:"eq=10,gte=10"` + F4 int64 `validate:"eq=10,gte=10"` + }{}, + errorNum: 8, + }, + { + stct: struct { + F1 uint8 `validate:"eq=10,gte=10"` + F2 uint16 `validate:"eq=10,gte=10"` + F3 uint32 `validate:"eq=10,gte=10"` + F4 uint64 `validate:"eq=10,gte=10"` + }{}, + errorNum: 8, + }, + { + stct: struct { + F1 float32 `validate:"eq=10,gte=10"` + F2 float64 `validate:"eq=10,gte=10"` + }{}, + errorNum: 4, + }, + { + stct: struct { + F1 int `validate:"eq=10,gte=10"` + F2 struct { + F3 int `validate:"eq=10,gte=10"` + } + }{}, + errorNum: 4, + }, + { + stct: &struct { + F1 int `validate:"eq=10,gte=10"` + F2 struct { + F3 int `validate:"eq=10,gte=10"` + } + }{}, + errorNum: 4, + }, + } + + validate := New(WithMultipleErrorsReturned()) + + for _, tc := range tcs { + err := validate.Struct(tc.stct) + NotEqual(t, err, nil) + + errs := err.(ValidationErrors) + Equal(t, len(errs), tc.errorNum) + } +}