From dfeee984caeb9dc2d2f3ef32c05458841b1b512b Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Tue, 24 May 2022 09:22:23 -0400 Subject: [PATCH 01/25] Add VSCode to .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 846a894..237b4c0 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,7 @@ report.json # Images *.png + +# VSCode +*.code-workspace +.vscode/* From 7f8bad05fae5a3a80a0fb0af1178ee841179dbd4 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 25 May 2022 12:31:57 -0400 Subject: [PATCH 02/25] Initial WRP Validation Framework ## Overview related to #25, #78, xmidt-org/scytale#88, xmidt-org/talaria#153 s.t. we want a validation mechanism that is configurable by the application & verifies the spec. ### tl;rd This pr introduces the initial validation framework, where applications supply validators (satisfying the `Validator interface`) to `NewMsgTypeValidator` and then used to verify the spec.
Explanation Apps supply validators satisfying: ```go // Validator is a WRP validator that allows access to the Validate function. type Validator interface { Validate(m Message) error } ``` and listing which validators are used on known and unknown msg types (where unknown msg types are handled by `defaultValidator`): ```go var alwaysValidMsg ValidatorFunc = func(msg Message) error { return nil } msgv, err := NewMsgTypeValidator( // Validates known msg types m: map[MessageType]Validators{SimpleEventMessageType: {alwaysValidMsg}}, // Validates unknown msg types defaultValidator: alwaysValidMsg) err = msgv.Validate(Message{Type: SimpleEventMessageType}) // Known msg type err == nil // True err = msgv.Validate(Message{Type: CreateMessageType}) // Unknown msg type, uses defaultValidator err == nil // True ``` if a default validator is not provided, all unknown msg type will **fail** by default ```go var alwaysValidMsg ValidatorFunc = func(msg Message) error { return nil } msgv, err := NewMsgTypeValidator( // Omitted defaultValidator m: map[MessageType]Validators{SimpleEventMessageType: {alwaysInvalidMsg()}}) err = msgv.Validate(Message{Type: CreateMessageType}) err != nil // True ```
Type of Change(s) - Non-breaking Enhancement - All new and existing tests passed.
Module Unit Testing: [PASSING]
PR Affecting Unit Testing: validator_test.go [PASSING] ```console Running tool: /usr/local/bin/go test -timeout 30s -run ^(TestHelperValidators|TestMsgTypeValidator)$ github.com/xmidt-org/wrp-go/v3 === RUN TestHelperValidators === RUN TestHelperValidators/alwaysInvalidMsg --- PASS: TestHelperValidators (0.00s) --- PASS: TestHelperValidators/alwaysInvalidMsg (0.00s) === RUN TestMsgTypeValidator === RUN TestMsgTypeValidator/MsgTypeValidator_validate === RUN TestMsgTypeValidator/MsgTypeValidator_validate/known_message_type === RUN TestMsgTypeValidator/MsgTypeValidator_validate/unknown_message_type_with_provided_default_Validator === RUN TestMsgTypeValidator/MsgTypeValidator_validate/known_message_type_with_a_failing_Validator === RUN TestMsgTypeValidator/MsgTypeValidator_validate/unknown_message_type_without_provided_default_Validator === RUN TestMsgTypeValidator/MsgTypeValidator_factory === RUN TestMsgTypeValidator/MsgTypeValidator_factory/with_provided_default_Validator === RUN TestMsgTypeValidator/MsgTypeValidator_factory/without_provided_default_Validator === RUN TestMsgTypeValidator/MsgTypeValidator_factory/empty_list_of_message_type_Validators === RUN TestMsgTypeValidator/MsgTypeValidator_factory/empty_value_'m'_map[MessageType]Validators --- PASS: TestMsgTypeValidator (0.00s) --- PASS: TestMsgTypeValidator/MsgTypeValidator_validate (0.00s) --- PASS: TestMsgTypeValidator/MsgTypeValidator_validate/known_message_type (0.00s) --- PASS: TestMsgTypeValidator/MsgTypeValidator_validate/unknown_message_type_with_provided_default_Validator (0.00s) --- PASS: TestMsgTypeValidator/MsgTypeValidator_validate/known_message_type_with_a_failing_Validator (0.00s) --- PASS: TestMsgTypeValidator/MsgTypeValidator_validate/unknown_message_type_without_provided_default_Validator (0.00s) --- PASS: TestMsgTypeValidator/MsgTypeValidator_factory (0.00s) --- PASS: TestMsgTypeValidator/MsgTypeValidator_factory/with_provided_default_Validator (0.00s) --- PASS: TestMsgTypeValidator/MsgTypeValidator_factory/without_provided_default_Validator (0.00s) --- PASS: TestMsgTypeValidator/MsgTypeValidator_factory/empty_list_of_message_type_Validators (0.00s) --- PASS: TestMsgTypeValidator/MsgTypeValidator_factory/empty_value_'m'_map[MessageType]Validators (0.00s) PASS ok github.com/xmidt-org/wrp-go/v3 0.303s > Test run finished at 5/25/2022, 11:39:22 AM < ```
--- header_wrp.go | 6 +- validator.go | 93 ++++++++++++++++++++++ validator_test.go | 199 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 293 insertions(+), 5 deletions(-) create mode 100644 validator.go create mode 100644 validator_test.go diff --git a/header_wrp.go b/header_wrp.go index 26feeaf..4123652 100644 --- a/header_wrp.go +++ b/header_wrp.go @@ -17,10 +17,6 @@ package wrp -import ( - "errors" -) - // Constant HTTP header strings representing WRP fields const ( MsgTypeHeader = "X-Midt-Msg-Type" @@ -34,7 +30,7 @@ const ( SourceHeader = "X-Midt-Source" ) -var ErrInvalidMsgType = errors.New("Invalid Message Type") +// var ErrInvalidMsgType = errors.New("Invalid Message Type") // Map string to MessageType int /* diff --git a/validator.go b/validator.go new file mode 100644 index 0000000..dcdf91d --- /dev/null +++ b/validator.go @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2022 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package wrp + +import ( + "errors" + "fmt" +) + +var ( + ErrInvalidMsgTypeValidator = errors.New("invalid WRP message type validator") + ErrInvalidMsgType = errors.New("invalid WRP message type") +) + +// Validator is a WRP validator that allows access to the Validate function. +type Validator interface { + Validate(m Message) error +} + +// Validators is a WRP validator that ensures messages are valid based on +// message type and each validator in the list. +type Validators []Validator + +// ValidatorFunc is a WRP validator that takes messages and validates them +// against functions. +type ValidatorFunc func(Message) error + +// Validate executes its own ValidatorFunc receiver and returns the result. +func (vf ValidatorFunc) Validate(m Message) error { + return vf(m) +} + +// MsgTypeValidator is a WRP validator that validates based on message type +// or using the defaultValidator if message type is unknown +type MsgTypeValidator struct { + m map[MessageType]Validators + defaultValidator Validator +} + +// Validate validates messages based on message type or using the defaultValidator +// if message type is unknown +func (m MsgTypeValidator) Validate(msg Message) error { + vs, ok := m.m[msg.MessageType()] + if !ok { + return m.defaultValidator.Validate(msg) + } + + for _, v := range vs { + err := v.Validate(msg) + if err != nil { + return err + } + } + + return nil +} + +// NewMsgTypeValidator returns a MsgTypeValidator +func NewMsgTypeValidator(m map[MessageType]Validators, defaultValidator Validator) (MsgTypeValidator, error) { + if m == nil { + return MsgTypeValidator{}, fmt.Errorf("%w: %v", ErrInvalidMsgTypeValidator, m) + } + if defaultValidator == nil { + defaultValidator = alwaysInvalidMsg() + } + + return MsgTypeValidator{ + m: m, + defaultValidator: defaultValidator, + }, nil +} + +// AlwaysInvalid doesn't validate anything about the message and always returns an error. +func alwaysInvalidMsg() ValidatorFunc { + return func(m Message) error { + return fmt.Errorf("%w: %v", ErrInvalidMsgType, m.MessageType().String()) + } +} diff --git a/validator_test.go b/validator_test.go new file mode 100644 index 0000000..8be4dde --- /dev/null +++ b/validator_test.go @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2022 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package wrp + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func testMsgTypeValidatorValidate(t *testing.T) { + type Test struct { + m map[MessageType]Validators + defaultValidator Validator + msg Message + } + + var alwaysValidMsg ValidatorFunc = func(msg Message) error { return nil } + tests := []struct { + description string + value Test + expectedErr error + }{ + // Success case + { + description: "known message type with successful Validators", + value: Test{ + m: map[MessageType]Validators{ + SimpleEventMessageType: {alwaysValidMsg}, + }, + msg: Message{Type: SimpleEventMessageType}, + }, + }, + { + description: "unknown message type with provided default Validator", + value: Test{ + m: map[MessageType]Validators{ + SimpleEventMessageType: {alwaysValidMsg}, + }, + defaultValidator: alwaysValidMsg, + msg: Message{Type: CreateMessageType}, + }, + }, + // Failure case + { + description: "known message type with failing Validators", + value: Test{ + m: map[MessageType]Validators{ + SimpleEventMessageType: {alwaysInvalidMsg()}, + }, + msg: Message{Type: SimpleEventMessageType}, + }, + expectedErr: ErrInvalidMsgType, + }, + { + description: "unknown message type without provided default Validator", + value: Test{ + m: map[MessageType]Validators{ + SimpleEventMessageType: {alwaysValidMsg}, + }, + msg: Message{Type: CreateMessageType}, + }, + expectedErr: ErrInvalidMsgType, + }, + } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + msgv, err := NewMsgTypeValidator(tc.value.m, tc.value.defaultValidator) + assert.NotNil(msgv) + assert.Nil(err) + err = msgv.Validate(tc.value.msg) + if tc.expectedErr != nil { + assert.ErrorIs(err, tc.expectedErr) + return + } + + assert.Nil(err) + }) + } +} + +func testNewMsgTypeValidator(t *testing.T) { + type Test struct { + m map[MessageType]Validators + defaultValidator Validator + } + + var alwaysValidMsg ValidatorFunc = func(msg Message) error { return nil } + tests := []struct { + description string + value Test + expectedErr error + }{ + // Success case + { + description: "with provided default Validator", + value: Test{ + m: map[MessageType]Validators{ + SimpleEventMessageType: {alwaysValidMsg}, + }, + defaultValidator: alwaysValidMsg, + }, + expectedErr: nil, + }, + { + description: "without provided default Validator", + value: Test{ + m: map[MessageType]Validators{ + SimpleEventMessageType: {alwaysValidMsg}, + }, + }, + expectedErr: nil, + }, + { + description: "empty list of message type Validators", + value: Test{ + m: map[MessageType]Validators{ + SimpleEventMessageType: {}, + }, + defaultValidator: alwaysValidMsg, + }, + expectedErr: nil, + }, + // Failure case + { + description: "missing message type Validators", + value: Test{}, + expectedErr: ErrInvalidMsgTypeValidator, + }, + } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + msgv, err := NewMsgTypeValidator(tc.value.m, tc.value.defaultValidator) + assert.NotNil(msgv) + if tc.expectedErr != nil { + assert.ErrorIs(err, tc.expectedErr) + return + } + + assert.Nil(err) + }) + } +} + +func testAlwaysInvalidMsg(t *testing.T) { + assert := assert.New(t) + msg := Message{} + v := alwaysInvalidMsg() + + assert.NotNil(v) + err := v(msg) + + assert.NotNil(err) + assert.ErrorIs(err, ErrInvalidMsgType) + +} + +func TestHelperValidators(t *testing.T) { + tests := []struct { + name string + test func(*testing.T) + }{ + {"alwaysInvalidMsg", testAlwaysInvalidMsg}, + } + + for _, tc := range tests { + t.Run(tc.name, tc.test) + } +} + +func TestMsgTypeValidator(t *testing.T) { + tests := []struct { + name string + test func(*testing.T) + }{ + {"MsgTypeValidator validate", testMsgTypeValidatorValidate}, + {"MsgTypeValidator factory", testNewMsgTypeValidator}, + } + + for _, tc := range tests { + t.Run(tc.name, tc.test) + } +} From 9319c121345d7acfdc5877f1363be8f0e33088da Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 25 May 2022 12:34:52 -0400 Subject: [PATCH 03/25] formatting --- validator.go | 1 + 1 file changed, 1 insertion(+) diff --git a/validator.go b/validator.go index dcdf91d..a246349 100644 --- a/validator.go +++ b/validator.go @@ -75,6 +75,7 @@ func NewMsgTypeValidator(m map[MessageType]Validators, defaultValidator Validato if m == nil { return MsgTypeValidator{}, fmt.Errorf("%w: %v", ErrInvalidMsgTypeValidator, m) } + if defaultValidator == nil { defaultValidator = alwaysInvalidMsg() } From 209ffdb017b8dd7c2a32bcad6dca902f5154551a Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 25 May 2022 12:35:43 -0400 Subject: [PATCH 04/25] formatting --- validator_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/validator_test.go b/validator_test.go index 8be4dde..5dfa55c 100644 --- a/validator_test.go +++ b/validator_test.go @@ -14,6 +14,7 @@ * limitations under the License. * */ + package wrp import ( From ddd0acfa21f22e88f80df56b92e6f545d3bde1f3 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 25 May 2022 12:42:17 -0400 Subject: [PATCH 05/25] convert alwaysInvalidMsg to literal func simplifies the usage of alwaysInvalidMsg --- validator.go | 14 ++++++-------- validator_test.go | 7 ++----- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/validator.go b/validator.go index a246349..ee422a4 100644 --- a/validator.go +++ b/validator.go @@ -27,6 +27,11 @@ var ( ErrInvalidMsgType = errors.New("invalid WRP message type") ) +// AlwaysInvalid doesn't validate anything about the message and always returns an error. +var alwaysInvalidMsg ValidatorFunc = func(m Message) error { + return fmt.Errorf("%w: %v", ErrInvalidMsgType, m.MessageType().String()) +} + // Validator is a WRP validator that allows access to the Validate function. type Validator interface { Validate(m Message) error @@ -77,7 +82,7 @@ func NewMsgTypeValidator(m map[MessageType]Validators, defaultValidator Validato } if defaultValidator == nil { - defaultValidator = alwaysInvalidMsg() + defaultValidator = alwaysInvalidMsg } return MsgTypeValidator{ @@ -85,10 +90,3 @@ func NewMsgTypeValidator(m map[MessageType]Validators, defaultValidator Validato defaultValidator: defaultValidator, }, nil } - -// AlwaysInvalid doesn't validate anything about the message and always returns an error. -func alwaysInvalidMsg() ValidatorFunc { - return func(m Message) error { - return fmt.Errorf("%w: %v", ErrInvalidMsgType, m.MessageType().String()) - } -} diff --git a/validator_test.go b/validator_test.go index 5dfa55c..5de9d3c 100644 --- a/validator_test.go +++ b/validator_test.go @@ -61,7 +61,7 @@ func testMsgTypeValidatorValidate(t *testing.T) { description: "known message type with failing Validators", value: Test{ m: map[MessageType]Validators{ - SimpleEventMessageType: {alwaysInvalidMsg()}, + SimpleEventMessageType: {alwaysInvalidMsg}, }, msg: Message{Type: SimpleEventMessageType}, }, @@ -162,10 +162,7 @@ func testNewMsgTypeValidator(t *testing.T) { func testAlwaysInvalidMsg(t *testing.T) { assert := assert.New(t) msg := Message{} - v := alwaysInvalidMsg() - - assert.NotNil(v) - err := v(msg) + err := alwaysInvalidMsg(msg) assert.NotNil(err) assert.ErrorIs(err, ErrInvalidMsgType) From a2a4093ee52b9a90d65e1b5645ff006ca08c1000 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 25 May 2022 12:46:29 -0400 Subject: [PATCH 06/25] Formating and exported alwaysInvalidMsg --- validator.go | 10 +++++----- validator_test.go | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/validator.go b/validator.go index ee422a4..d40dca4 100644 --- a/validator.go +++ b/validator.go @@ -28,7 +28,7 @@ var ( ) // AlwaysInvalid doesn't validate anything about the message and always returns an error. -var alwaysInvalidMsg ValidatorFunc = func(m Message) error { +var AlwaysInvalidMsg ValidatorFunc = func(m Message) error { return fmt.Errorf("%w: %v", ErrInvalidMsgType, m.MessageType().String()) } @@ -51,14 +51,14 @@ func (vf ValidatorFunc) Validate(m Message) error { } // MsgTypeValidator is a WRP validator that validates based on message type -// or using the defaultValidator if message type is unknown +// or using the defaultValidator if message type is unknown. type MsgTypeValidator struct { m map[MessageType]Validators defaultValidator Validator } // Validate validates messages based on message type or using the defaultValidator -// if message type is unknown +// if message type is unknown. func (m MsgTypeValidator) Validate(msg Message) error { vs, ok := m.m[msg.MessageType()] if !ok { @@ -75,14 +75,14 @@ func (m MsgTypeValidator) Validate(msg Message) error { return nil } -// NewMsgTypeValidator returns a MsgTypeValidator +// NewMsgTypeValidator is a MsgTypeValidator factory. func NewMsgTypeValidator(m map[MessageType]Validators, defaultValidator Validator) (MsgTypeValidator, error) { if m == nil { return MsgTypeValidator{}, fmt.Errorf("%w: %v", ErrInvalidMsgTypeValidator, m) } if defaultValidator == nil { - defaultValidator = alwaysInvalidMsg + defaultValidator = AlwaysInvalidMsg } return MsgTypeValidator{ diff --git a/validator_test.go b/validator_test.go index 5de9d3c..5fb5bc0 100644 --- a/validator_test.go +++ b/validator_test.go @@ -61,7 +61,7 @@ func testMsgTypeValidatorValidate(t *testing.T) { description: "known message type with failing Validators", value: Test{ m: map[MessageType]Validators{ - SimpleEventMessageType: {alwaysInvalidMsg}, + SimpleEventMessageType: {AlwaysInvalidMsg}, }, msg: Message{Type: SimpleEventMessageType}, }, @@ -162,7 +162,7 @@ func testNewMsgTypeValidator(t *testing.T) { func testAlwaysInvalidMsg(t *testing.T) { assert := assert.New(t) msg := Message{} - err := alwaysInvalidMsg(msg) + err := AlwaysInvalidMsg(msg) assert.NotNil(err) assert.ErrorIs(err, ErrInvalidMsgType) @@ -174,7 +174,7 @@ func TestHelperValidators(t *testing.T) { name string test func(*testing.T) }{ - {"alwaysInvalidMsg", testAlwaysInvalidMsg}, + {"AlwaysInvalidMsg", testAlwaysInvalidMsg}, } for _, tc := range tests { From f5a2e90f47dcee1c789b90e3108705bb38988231 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 25 May 2022 13:15:22 -0400 Subject: [PATCH 07/25] Decouple error from api Return `ErrInvalidMsgTypeValidator` and `ErrInvalidMsgType` without additional details. We can add those error details downstream later --- validator.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/validator.go b/validator.go index d40dca4..997e575 100644 --- a/validator.go +++ b/validator.go @@ -19,7 +19,6 @@ package wrp import ( "errors" - "fmt" ) var ( @@ -29,7 +28,7 @@ var ( // AlwaysInvalid doesn't validate anything about the message and always returns an error. var AlwaysInvalidMsg ValidatorFunc = func(m Message) error { - return fmt.Errorf("%w: %v", ErrInvalidMsgType, m.MessageType().String()) + return ErrInvalidMsgType } // Validator is a WRP validator that allows access to the Validate function. @@ -78,7 +77,7 @@ func (m MsgTypeValidator) Validate(msg Message) error { // NewMsgTypeValidator is a MsgTypeValidator factory. func NewMsgTypeValidator(m map[MessageType]Validators, defaultValidator Validator) (MsgTypeValidator, error) { if m == nil { - return MsgTypeValidator{}, fmt.Errorf("%w: %v", ErrInvalidMsgTypeValidator, m) + return MsgTypeValidator{}, ErrInvalidMsgTypeValidator } if defaultValidator == nil { From eb5bf9b47b938e5662ac073c46c422de2900e784 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 25 May 2022 20:42:12 -0400 Subject: [PATCH 08/25] Updates based on PR review Thx @kristinapathak for the feedback! :beers: --- header_wrp.go | 2 - validator.go | 54 ++++++++++++++++----------- validator_test.go | 95 ++++++++++++++++++++++++++++------------------- 3 files changed, 90 insertions(+), 61 deletions(-) diff --git a/header_wrp.go b/header_wrp.go index 4123652..eada008 100644 --- a/header_wrp.go +++ b/header_wrp.go @@ -30,8 +30,6 @@ const ( SourceHeader = "X-Midt-Source" ) -// var ErrInvalidMsgType = errors.New("Invalid Message Type") - // Map string to MessageType int /* func StringToMessageType(str string) MessageType { diff --git a/validator.go b/validator.go index 997e575..f770ab2 100644 --- a/validator.go +++ b/validator.go @@ -22,12 +22,12 @@ import ( ) var ( - ErrInvalidMsgTypeValidator = errors.New("invalid WRP message type validator") - ErrInvalidMsgType = errors.New("invalid WRP message type") + ErrInvalidTypeValidator = errors.New("invalid WRP message type validator") + ErrInvalidMsgType = errors.New("invalid WRP message type") ) // AlwaysInvalid doesn't validate anything about the message and always returns an error. -var AlwaysInvalidMsg ValidatorFunc = func(m Message) error { +var AlwaysInvalid ValidatorFunc = func(m Message) error { return ErrInvalidMsgType } @@ -40,6 +40,19 @@ type Validator interface { // message type and each validator in the list. type Validators []Validator +// Validate runs messages through each validator in the validators list. +// It returns as soon as the message is considered invalid, otherwise returns nil if valid. +func (vs Validators) Validate(m Message) error { + for _, v := range vs { + err := v.Validate(m) + if err != nil { + return err + } + } + + return nil +} + // ValidatorFunc is a WRP validator that takes messages and validates them // against functions. type ValidatorFunc func(Message) error @@ -49,42 +62,41 @@ func (vf ValidatorFunc) Validate(m Message) error { return vf(m) } -// MsgTypeValidator is a WRP validator that validates based on message type +// TypeValidator is a WRP validator that validates based on message type // or using the defaultValidator if message type is unknown. -type MsgTypeValidator struct { +type TypeValidator struct { m map[MessageType]Validators defaultValidator Validator } // Validate validates messages based on message type or using the defaultValidator // if message type is unknown. -func (m MsgTypeValidator) Validate(msg Message) error { - vs, ok := m.m[msg.MessageType()] - if !ok { +func (m TypeValidator) Validate(msg Message) error { + vs := m.m[msg.MessageType()] + if vs == nil { return m.defaultValidator.Validate(msg) } - for _, v := range vs { - err := v.Validate(msg) - if err != nil { - return err - } - } - - return nil + return vs.Validate(msg) } -// NewMsgTypeValidator is a MsgTypeValidator factory. -func NewMsgTypeValidator(m map[MessageType]Validators, defaultValidator Validator) (MsgTypeValidator, error) { +// NewTypeValidator is a TypeValidator factory. +func NewTypeValidator(m map[MessageType]Validators, defaultValidator Validator) (TypeValidator, error) { if m == nil { - return MsgTypeValidator{}, ErrInvalidMsgTypeValidator + return TypeValidator{}, ErrInvalidTypeValidator + } + + for _, v := range m { + if v == nil || len(v) == 0 { + return TypeValidator{}, ErrInvalidTypeValidator + } } if defaultValidator == nil { - defaultValidator = AlwaysInvalidMsg + defaultValidator = AlwaysInvalid } - return MsgTypeValidator{ + return TypeValidator{ m: m, defaultValidator: defaultValidator, }, nil diff --git a/validator_test.go b/validator_test.go index 5fb5bc0..8e88061 100644 --- a/validator_test.go +++ b/validator_test.go @@ -21,16 +21,17 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -func testMsgTypeValidatorValidate(t *testing.T) { +func testTypeValidatorValidate(t *testing.T) { type Test struct { m map[MessageType]Validators defaultValidator Validator msg Message } - var alwaysValidMsg ValidatorFunc = func(msg Message) error { return nil } + var alwaysValid ValidatorFunc = func(msg Message) error { return nil } tests := []struct { description string value Test @@ -38,70 +39,81 @@ func testMsgTypeValidatorValidate(t *testing.T) { }{ // Success case { - description: "known message type with successful Validators", + description: "Found success", value: Test{ m: map[MessageType]Validators{ - SimpleEventMessageType: {alwaysValidMsg}, + SimpleEventMessageType: {alwaysValid}, }, msg: Message{Type: SimpleEventMessageType}, }, }, { - description: "unknown message type with provided default Validator", + description: "Not found success", value: Test{ m: map[MessageType]Validators{ - SimpleEventMessageType: {alwaysValidMsg}, + SimpleEventMessageType: {AlwaysInvalid}, }, - defaultValidator: alwaysValidMsg, + defaultValidator: alwaysValid, + msg: Message{Type: CreateMessageType}, + }, + }, + { + description: "Never found success", + value: Test{ + m: map[MessageType]Validators{}, + defaultValidator: alwaysValid, msg: Message{Type: CreateMessageType}, }, }, // Failure case { - description: "known message type with failing Validators", + description: "Found error", value: Test{ m: map[MessageType]Validators{ - SimpleEventMessageType: {AlwaysInvalidMsg}, + SimpleEventMessageType: {AlwaysInvalid}, }, - msg: Message{Type: SimpleEventMessageType}, + defaultValidator: alwaysValid, + msg: Message{Type: SimpleEventMessageType}, }, expectedErr: ErrInvalidMsgType, }, { - description: "unknown message type without provided default Validator", + description: "Not Found error", value: Test{ m: map[MessageType]Validators{ - SimpleEventMessageType: {alwaysValidMsg}, + SimpleEventMessageType: {alwaysValid}, }, msg: Message{Type: CreateMessageType}, }, expectedErr: ErrInvalidMsgType, }, } + for _, tc := range tests { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) - msgv, err := NewMsgTypeValidator(tc.value.m, tc.value.defaultValidator) - assert.NotNil(msgv) - assert.Nil(err) + require := require.New(t) + msgv, err := NewTypeValidator(tc.value.m, tc.value.defaultValidator) + require.NotNil(msgv) + require.NoError(err) err = msgv.Validate(tc.value.msg) if tc.expectedErr != nil { assert.ErrorIs(err, tc.expectedErr) return } - assert.Nil(err) + assert.NoError(err) }) } } -func testNewMsgTypeValidator(t *testing.T) { +func testNewTypeValidator(t *testing.T) { type Test struct { m map[MessageType]Validators defaultValidator Validator } - var alwaysValidMsg ValidatorFunc = func(msg Message) error { return nil } + var alwaysValid ValidatorFunc = func(msg Message) error { return nil } tests := []struct { description string value Test @@ -109,62 +121,69 @@ func testNewMsgTypeValidator(t *testing.T) { }{ // Success case { - description: "with provided default Validator", + description: "Default Validator success", value: Test{ m: map[MessageType]Validators{ - SimpleEventMessageType: {alwaysValidMsg}, + SimpleEventMessageType: {alwaysValid}, }, - defaultValidator: alwaysValidMsg, + defaultValidator: alwaysValid, }, expectedErr: nil, }, { - description: "without provided default Validator", + description: "Omit map of Validator success", + value: Test{ + m: map[MessageType]Validators{}, + defaultValidator: alwaysValid, + }, + expectedErr: nil, + }, + { + description: "Omit default Validator success", value: Test{ m: map[MessageType]Validators{ - SimpleEventMessageType: {alwaysValidMsg}, + SimpleEventMessageType: {alwaysValid}, }, }, expectedErr: nil, }, + // Failure case { - description: "empty list of message type Validators", + description: "Empty list of Validators error", value: Test{ m: map[MessageType]Validators{ SimpleEventMessageType: {}, }, - defaultValidator: alwaysValidMsg, + defaultValidator: alwaysValid, }, - expectedErr: nil, + expectedErr: ErrInvalidTypeValidator, }, - // Failure case { - description: "missing message type Validators", + description: "Empty map of Validators error", value: Test{}, - expectedErr: ErrInvalidMsgTypeValidator, + expectedErr: ErrInvalidTypeValidator, }, } for _, tc := range tests { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) - msgv, err := NewMsgTypeValidator(tc.value.m, tc.value.defaultValidator) + msgv, err := NewTypeValidator(tc.value.m, tc.value.defaultValidator) assert.NotNil(msgv) if tc.expectedErr != nil { assert.ErrorIs(err, tc.expectedErr) return } - assert.Nil(err) + assert.NoError(err) }) } } -func testAlwaysInvalidMsg(t *testing.T) { +func testAlwaysInvalid(t *testing.T) { assert := assert.New(t) msg := Message{} - err := AlwaysInvalidMsg(msg) + err := AlwaysInvalid(msg) - assert.NotNil(err) assert.ErrorIs(err, ErrInvalidMsgType) } @@ -174,7 +193,7 @@ func TestHelperValidators(t *testing.T) { name string test func(*testing.T) }{ - {"AlwaysInvalidMsg", testAlwaysInvalidMsg}, + {"AlwaysInvalid", testAlwaysInvalid}, } for _, tc := range tests { @@ -182,13 +201,13 @@ func TestHelperValidators(t *testing.T) { } } -func TestMsgTypeValidator(t *testing.T) { +func TestTypeValidator(t *testing.T) { tests := []struct { name string test func(*testing.T) }{ - {"MsgTypeValidator validate", testMsgTypeValidatorValidate}, - {"MsgTypeValidator factory", testNewMsgTypeValidator}, + {"TypeValidator validate", testTypeValidatorValidate}, + {"TypeValidator factory", testNewTypeValidator}, } for _, tc := range tests { From afa08cb071f84a544801cede147dcbb51267e176 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 25 May 2022 21:09:25 -0400 Subject: [PATCH 09/25] removed duplicated test already covered by "Not found success" --- validator_test.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/validator_test.go b/validator_test.go index 8e88061..3f5108d 100644 --- a/validator_test.go +++ b/validator_test.go @@ -57,14 +57,6 @@ func testTypeValidatorValidate(t *testing.T) { msg: Message{Type: CreateMessageType}, }, }, - { - description: "Never found success", - value: Test{ - m: map[MessageType]Validators{}, - defaultValidator: alwaysValid, - msg: Message{Type: CreateMessageType}, - }, - }, // Failure case { description: "Found error", From 8cb0fa700dfab2460c6272fb7ad1e583f8b18385 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 25 May 2022 21:11:22 -0400 Subject: [PATCH 10/25] Fix type test name --- validator_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator_test.go b/validator_test.go index 3f5108d..ecc9521 100644 --- a/validator_test.go +++ b/validator_test.go @@ -123,7 +123,7 @@ func testNewTypeValidator(t *testing.T) { expectedErr: nil, }, { - description: "Omit map of Validator success", + description: "Empty map of Validator success", value: Test{ m: map[MessageType]Validators{}, defaultValidator: alwaysValid, From 10afaa2cdf3e41462e347fffd2b3f840e4861524 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 25 May 2022 21:11:48 -0400 Subject: [PATCH 11/25] Fix type test name --- validator_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator_test.go b/validator_test.go index ecc9521..31091dd 100644 --- a/validator_test.go +++ b/validator_test.go @@ -123,7 +123,7 @@ func testNewTypeValidator(t *testing.T) { expectedErr: nil, }, { - description: "Empty map of Validator success", + description: "Empty map of Validators success", value: Test{ m: map[MessageType]Validators{}, defaultValidator: alwaysValid, From 1923ec78abb83effc79a936f97022d1e85c08e42 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 25 May 2022 21:20:56 -0400 Subject: [PATCH 12/25] Add missing test/edge cases for Validators --- validator.go | 10 ++++++++-- validator_test.go | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/validator.go b/validator.go index f770ab2..618b09f 100644 --- a/validator.go +++ b/validator.go @@ -86,10 +86,16 @@ func NewTypeValidator(m map[MessageType]Validators, defaultValidator Validator) return TypeValidator{}, ErrInvalidTypeValidator } - for _, v := range m { - if v == nil || len(v) == 0 { + for _, vs := range m { + if vs == nil || len(vs) == 0 { return TypeValidator{}, ErrInvalidTypeValidator } + + for _, v := range vs { + if v == nil { + return TypeValidator{}, ErrInvalidTypeValidator + } + } } if defaultValidator == nil { diff --git a/validator_test.go b/validator_test.go index 31091dd..68c7215 100644 --- a/validator_test.go +++ b/validator_test.go @@ -150,6 +150,26 @@ func testNewTypeValidator(t *testing.T) { }, expectedErr: ErrInvalidTypeValidator, }, + { + description: "Nil Validators error", + value: Test{ + m: map[MessageType]Validators{ + SimpleEventMessageType: nil, + }, + defaultValidator: alwaysValid, + }, + expectedErr: ErrInvalidTypeValidator, + }, + { + description: "Nil list of Validators error", + value: Test{ + m: map[MessageType]Validators{ + SimpleEventMessageType: {nil}, + }, + defaultValidator: alwaysValid, + }, + expectedErr: ErrInvalidTypeValidator, + }, { description: "Empty map of Validators error", value: Test{}, From 98c4b4a1c050534d9120891cd2db428692615c20 Mon Sep 17 00:00:00 2001 From: ocabal200 Date: Thu, 26 May 2022 12:50:42 -0400 Subject: [PATCH 13/25] Updated defaultValidator to work as a variadic for multi-default support & added examples --- validator.go | 26 ++++++++++------- validator_test.go | 74 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 73 insertions(+), 27 deletions(-) diff --git a/validator.go b/validator.go index 618b09f..6736faf 100644 --- a/validator.go +++ b/validator.go @@ -63,25 +63,25 @@ func (vf ValidatorFunc) Validate(m Message) error { } // TypeValidator is a WRP validator that validates based on message type -// or using the defaultValidator if message type is unknown. +// or using the defaultValidators if message type is unknown. type TypeValidator struct { - m map[MessageType]Validators - defaultValidator Validator + m map[MessageType]Validators + defaultValidators Validators } -// Validate validates messages based on message type or using the defaultValidator +// Validate validates messages based on message type or using the defaultValidators // if message type is unknown. func (m TypeValidator) Validate(msg Message) error { vs := m.m[msg.MessageType()] if vs == nil { - return m.defaultValidator.Validate(msg) + return m.defaultValidators.Validate(msg) } return vs.Validate(msg) } // NewTypeValidator is a TypeValidator factory. -func NewTypeValidator(m map[MessageType]Validators, defaultValidator Validator) (TypeValidator, error) { +func NewTypeValidator(m map[MessageType]Validators, defaultValidators ...Validator) (TypeValidator, error) { if m == nil { return TypeValidator{}, ErrInvalidTypeValidator } @@ -98,12 +98,18 @@ func NewTypeValidator(m map[MessageType]Validators, defaultValidator Validator) } } - if defaultValidator == nil { - defaultValidator = AlwaysInvalid + if len(defaultValidators) == 0 { + defaultValidators = Validators{AlwaysInvalid} + } + + for _, v := range defaultValidators { + if v == nil { + return TypeValidator{}, ErrInvalidTypeValidator + } } return TypeValidator{ - m: m, - defaultValidator: defaultValidator, + m: m, + defaultValidators: defaultValidators, }, nil } diff --git a/validator_test.go b/validator_test.go index 68c7215..66e9e67 100644 --- a/validator_test.go +++ b/validator_test.go @@ -18,6 +18,7 @@ package wrp import ( + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -26,9 +27,9 @@ import ( func testTypeValidatorValidate(t *testing.T) { type Test struct { - m map[MessageType]Validators - defaultValidator Validator - msg Message + m map[MessageType]Validators + defaultValidators Validators + msg Message } var alwaysValid ValidatorFunc = func(msg Message) error { return nil } @@ -53,8 +54,8 @@ func testTypeValidatorValidate(t *testing.T) { m: map[MessageType]Validators{ SimpleEventMessageType: {AlwaysInvalid}, }, - defaultValidator: alwaysValid, - msg: Message{Type: CreateMessageType}, + defaultValidators: Validators{alwaysValid}, + msg: Message{Type: CreateMessageType}, }, }, // Failure case @@ -64,8 +65,8 @@ func testTypeValidatorValidate(t *testing.T) { m: map[MessageType]Validators{ SimpleEventMessageType: {AlwaysInvalid}, }, - defaultValidator: alwaysValid, - msg: Message{Type: SimpleEventMessageType}, + defaultValidators: Validators{alwaysValid}, + msg: Message{Type: SimpleEventMessageType}, }, expectedErr: ErrInvalidMsgType, }, @@ -85,7 +86,7 @@ func testTypeValidatorValidate(t *testing.T) { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) require := require.New(t) - msgv, err := NewTypeValidator(tc.value.m, tc.value.defaultValidator) + msgv, err := NewTypeValidator(tc.value.m, tc.value.defaultValidators...) require.NotNil(msgv) require.NoError(err) err = msgv.Validate(tc.value.msg) @@ -101,8 +102,8 @@ func testTypeValidatorValidate(t *testing.T) { func testNewTypeValidator(t *testing.T) { type Test struct { - m map[MessageType]Validators - defaultValidator Validator + m map[MessageType]Validators + defaultValidators Validators } var alwaysValid ValidatorFunc = func(msg Message) error { return nil } @@ -118,15 +119,15 @@ func testNewTypeValidator(t *testing.T) { m: map[MessageType]Validators{ SimpleEventMessageType: {alwaysValid}, }, - defaultValidator: alwaysValid, + defaultValidators: Validators{alwaysValid}, }, expectedErr: nil, }, { description: "Empty map of Validators success", value: Test{ - m: map[MessageType]Validators{}, - defaultValidator: alwaysValid, + m: map[MessageType]Validators{}, + defaultValidators: Validators{alwaysValid}, }, expectedErr: nil, }, @@ -146,7 +147,7 @@ func testNewTypeValidator(t *testing.T) { m: map[MessageType]Validators{ SimpleEventMessageType: {}, }, - defaultValidator: alwaysValid, + defaultValidators: Validators{alwaysValid}, }, expectedErr: ErrInvalidTypeValidator, }, @@ -156,7 +157,7 @@ func testNewTypeValidator(t *testing.T) { m: map[MessageType]Validators{ SimpleEventMessageType: nil, }, - defaultValidator: alwaysValid, + defaultValidators: Validators{alwaysValid}, }, expectedErr: ErrInvalidTypeValidator, }, @@ -166,7 +167,7 @@ func testNewTypeValidator(t *testing.T) { m: map[MessageType]Validators{ SimpleEventMessageType: {nil}, }, - defaultValidator: alwaysValid, + defaultValidators: Validators{alwaysValid}, }, expectedErr: ErrInvalidTypeValidator, }, @@ -179,7 +180,7 @@ func testNewTypeValidator(t *testing.T) { for _, tc := range tests { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) - msgv, err := NewTypeValidator(tc.value.m, tc.value.defaultValidator) + msgv, err := NewTypeValidator(tc.value.m, tc.value.defaultValidators...) assert.NotNil(msgv) if tc.expectedErr != nil { assert.ErrorIs(err, tc.expectedErr) @@ -226,3 +227,42 @@ func TestTypeValidator(t *testing.T) { t.Run(tc.name, tc.test) } } + +func ExampleNewTypeValidator() { + var alwaysValid ValidatorFunc = func(msg Message) error { return nil } + msgv, err := NewTypeValidator( + // Validates known msg types + map[MessageType]Validators{SimpleEventMessageType: {alwaysValid}}, + // Validates unknown msg types + AlwaysInvalid) + if err != nil { + return + } + err = msgv.Validate(Message{Type: SimpleEventMessageType}) // Found success + fmt.Println(err == nil) + // Output: true + +} + +func ExampleTypeValidator_Validate_found() { + var alwaysValid ValidatorFunc = func(msg Message) error { return nil } + msgv, err := NewTypeValidator( + // Validates known msg types + map[MessageType]Validators{SimpleEventMessageType: {alwaysValid}}, + // Validates unknown msg types + AlwaysInvalid) + err = msgv.Validate(Message{Type: SimpleEventMessageType}) // Found success + fmt.Println(err == nil) + // Output: true +} +func ExampleTypeValidator_Validate_notFound() { + var alwaysValid ValidatorFunc = func(msg Message) error { return nil } + msgv, err := NewTypeValidator( + // Validates known msg types + map[MessageType]Validators{SimpleEventMessageType: {alwaysValid}}, + // Validates unknown msg types + AlwaysInvalid) + err = msgv.Validate(Message{Type: CreateMessageType}) // Not Found error + fmt.Println(err == nil) + // Output: false +} From 319756825bf1961050dd1808406caac90fb291ee Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Thu, 26 May 2022 13:22:34 -0400 Subject: [PATCH 14/25] rename test var `name` to `description` --- validator_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/validator_test.go b/validator_test.go index 68c7215..fe376fd 100644 --- a/validator_test.go +++ b/validator_test.go @@ -202,27 +202,27 @@ func testAlwaysInvalid(t *testing.T) { func TestHelperValidators(t *testing.T) { tests := []struct { - name string - test func(*testing.T) + description string + test func(*testing.T) }{ {"AlwaysInvalid", testAlwaysInvalid}, } for _, tc := range tests { - t.Run(tc.name, tc.test) + t.Run(tc.description, tc.test) } } func TestTypeValidator(t *testing.T) { tests := []struct { - name string - test func(*testing.T) + description string + test func(*testing.T) }{ {"TypeValidator validate", testTypeValidatorValidate}, {"TypeValidator factory", testNewTypeValidator}, } for _, tc := range tests { - t.Run(tc.name, tc.test) + t.Run(tc.description, tc.test) } } From 793d6f40c94aed96b06b382e46dd83f69145e566 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Thu, 26 May 2022 13:32:47 -0400 Subject: [PATCH 15/25] Squash: examples, docs, multierr updates update examples Doc/var update Add test for `Nil default Validators` edge case update examples output doc update Updates based on PR review * exported alwaysValid * decoupled data structures leveraging `Validators` to `Validator` * added validateValidator Add multierr to Validator --- go.mod | 1 + go.sum | 4 ++ validator.go | 63 ++++++++++++++-------- validator_test.go | 133 ++++++++++++++++++++++------------------------ 4 files changed, 110 insertions(+), 91 deletions(-) diff --git a/go.mod b/go.mod index 1fd3bdd..393c95c 100644 --- a/go.mod +++ b/go.mod @@ -12,4 +12,5 @@ require ( github.com/ugorji/go/codec v1.2.6 github.com/xmidt-org/httpaux v0.3.0 github.com/xmidt-org/webpa-common v1.3.2 + go.uber.org/multierr v1.8.0 ) diff --git a/go.sum b/go.sum index a1d9119..8370579 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,10 @@ github.com/xmidt-org/httpaux v0.3.0 h1:JdV4QceiE8EMA1Qf5rnJzHdkIPzQV12ddARHLU8hr github.com/xmidt-org/httpaux v0.3.0/go.mod h1:mviIlg5fHGb3lAv3l0sbiwVG/q9rqvXaudEYxVrzXdE= github.com/xmidt-org/webpa-common v1.3.2 h1:dE1Fi+XVnkt3tMGMjH7/hN/UGcaQ/ukKriXuMDyCWnM= github.com/xmidt-org/webpa-common v1.3.2/go.mod h1:oCpKzOC+9h2vYHVzAU/06tDTQuBN4RZz+rhgIXptpOI= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= +go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/validator.go b/validator.go index 6736faf..f909660 100644 --- a/validator.go +++ b/validator.go @@ -19,6 +19,8 @@ package wrp import ( "errors" + + "go.uber.org/multierr" ) var ( @@ -27,9 +29,10 @@ var ( ) // AlwaysInvalid doesn't validate anything about the message and always returns an error. -var AlwaysInvalid ValidatorFunc = func(m Message) error { - return ErrInvalidMsgType -} +var AlwaysInvalid ValidatorFunc = func(m Message) error { return ErrInvalidMsgType } + +// AlwaysValid doesn't validate anything about the message and always returns nil. +var AlwaysValid ValidatorFunc = func(msg Message) error { return nil } // Validator is a WRP validator that allows access to the Validate function. type Validator interface { @@ -43,14 +46,12 @@ type Validators []Validator // Validate runs messages through each validator in the validators list. // It returns as soon as the message is considered invalid, otherwise returns nil if valid. func (vs Validators) Validate(m Message) error { + var err error for _, v := range vs { - err := v.Validate(m) - if err != nil { - return err - } + err = multierr.Append(err, v.Validate(m)) } - return nil + return err } // ValidatorFunc is a WRP validator that takes messages and validates them @@ -63,14 +64,14 @@ func (vf ValidatorFunc) Validate(m Message) error { } // TypeValidator is a WRP validator that validates based on message type -// or using the defaultValidators if message type is unknown. +// or using the defaultValidators if message type is unfound. type TypeValidator struct { - m map[MessageType]Validators + m map[MessageType]Validator defaultValidators Validators } // Validate validates messages based on message type or using the defaultValidators -// if message type is unknown. +// if message type is unfound. func (m TypeValidator) Validate(msg Message) error { vs := m.m[msg.MessageType()] if vs == nil { @@ -81,20 +82,14 @@ func (m TypeValidator) Validate(msg Message) error { } // NewTypeValidator is a TypeValidator factory. -func NewTypeValidator(m map[MessageType]Validators, defaultValidators ...Validator) (TypeValidator, error) { +func NewTypeValidator(m map[MessageType]Validator, defaultValidators ...Validator) (TypeValidator, error) { if m == nil { return TypeValidator{}, ErrInvalidTypeValidator } - for _, vs := range m { - if vs == nil || len(vs) == 0 { - return TypeValidator{}, ErrInvalidTypeValidator - } - - for _, v := range vs { - if v == nil { - return TypeValidator{}, ErrInvalidTypeValidator - } + for _, v := range m { + if err := validateValidator(v); err != nil { + return TypeValidator{}, err } } @@ -103,8 +98,8 @@ func NewTypeValidator(m map[MessageType]Validators, defaultValidators ...Validat } for _, v := range defaultValidators { - if v == nil { - return TypeValidator{}, ErrInvalidTypeValidator + if err := validateValidator(v); err != nil { + return TypeValidator{}, err } } @@ -113,3 +108,25 @@ func NewTypeValidator(m map[MessageType]Validators, defaultValidators ...Validat defaultValidators: defaultValidators, }, nil } + +// validateValidator validates a given Validator. +func validateValidator(v Validator) error { + switch vs := v.(type) { + case Validators: + if vs == nil || len(vs) == 0 { + return ErrInvalidTypeValidator + } + + for _, v := range vs { + if v == nil { + return ErrInvalidTypeValidator + } + } + case Validator, ValidatorFunc: + // catch nil Validator + default: + return ErrInvalidTypeValidator + } + + return nil +} diff --git a/validator_test.go b/validator_test.go index 11a41a9..64cf8c7 100644 --- a/validator_test.go +++ b/validator_test.go @@ -27,12 +27,11 @@ import ( func testTypeValidatorValidate(t *testing.T) { type Test struct { - m map[MessageType]Validators + m map[MessageType]Validator defaultValidators Validators msg Message } - var alwaysValid ValidatorFunc = func(msg Message) error { return nil } tests := []struct { description string value Test @@ -42,19 +41,19 @@ func testTypeValidatorValidate(t *testing.T) { { description: "Found success", value: Test{ - m: map[MessageType]Validators{ - SimpleEventMessageType: {alwaysValid}, + m: map[MessageType]Validator{ + SimpleEventMessageType: Validators{AlwaysValid}, }, msg: Message{Type: SimpleEventMessageType}, }, }, { - description: "Not found success", + description: "Unfound success", value: Test{ - m: map[MessageType]Validators{ - SimpleEventMessageType: {AlwaysInvalid}, + m: map[MessageType]Validator{ + SimpleEventMessageType: Validators{AlwaysInvalid}, }, - defaultValidators: Validators{alwaysValid}, + defaultValidators: Validators{AlwaysValid}, msg: Message{Type: CreateMessageType}, }, }, @@ -62,19 +61,19 @@ func testTypeValidatorValidate(t *testing.T) { { description: "Found error", value: Test{ - m: map[MessageType]Validators{ - SimpleEventMessageType: {AlwaysInvalid}, + m: map[MessageType]Validator{ + SimpleEventMessageType: Validators{AlwaysInvalid}, }, - defaultValidators: Validators{alwaysValid}, + defaultValidators: Validators{AlwaysValid}, msg: Message{Type: SimpleEventMessageType}, }, expectedErr: ErrInvalidMsgType, }, { - description: "Not Found error", + description: "Unfound error", value: Test{ - m: map[MessageType]Validators{ - SimpleEventMessageType: {alwaysValid}, + m: map[MessageType]Validator{ + SimpleEventMessageType: Validators{AlwaysValid}, }, msg: Message{Type: CreateMessageType}, }, @@ -102,11 +101,10 @@ func testTypeValidatorValidate(t *testing.T) { func testNewTypeValidator(t *testing.T) { type Test struct { - m map[MessageType]Validators + m map[MessageType]Validator defaultValidators Validators } - var alwaysValid ValidatorFunc = func(msg Message) error { return nil } tests := []struct { description string value Test @@ -114,69 +112,83 @@ func testNewTypeValidator(t *testing.T) { }{ // Success case { - description: "Default Validator success", + description: "Default Validators success", value: Test{ - m: map[MessageType]Validators{ - SimpleEventMessageType: {alwaysValid}, + m: map[MessageType]Validator{ + SimpleEventMessageType: AlwaysValid, }, - defaultValidators: Validators{alwaysValid}, + defaultValidators: Validators{AlwaysValid}, }, expectedErr: nil, }, { description: "Empty map of Validators success", value: Test{ - m: map[MessageType]Validators{}, - defaultValidators: Validators{alwaysValid}, + m: map[MessageType]Validator{}, + defaultValidators: Validators{AlwaysValid}, }, expectedErr: nil, }, { - description: "Omit default Validator success", + description: "Omit default Validators success", value: Test{ - m: map[MessageType]Validators{ - SimpleEventMessageType: {alwaysValid}, + m: map[MessageType]Validator{ + SimpleEventMessageType: Validators{AlwaysValid}, }, }, expectedErr: nil, }, // Failure case + { + description: "Nil list of default Validators error ", + value: Test{ + m: map[MessageType]Validator{ + SimpleEventMessageType: AlwaysValid, + }, + defaultValidators: Validators{nil}, + }, + expectedErr: ErrInvalidTypeValidator, + }, { description: "Empty list of Validators error", value: Test{ - m: map[MessageType]Validators{ - SimpleEventMessageType: {}, + m: map[MessageType]Validator{ + SimpleEventMessageType: Validators{}, }, - defaultValidators: Validators{alwaysValid}, + defaultValidators: Validators{AlwaysValid}, }, expectedErr: ErrInvalidTypeValidator, }, { - description: "Nil Validators error", + description: "Nil Validator error", value: Test{ - m: map[MessageType]Validators{ + m: map[MessageType]Validator{ SimpleEventMessageType: nil, }, - defaultValidators: Validators{alwaysValid}, + defaultValidators: Validators{AlwaysValid}, }, expectedErr: ErrInvalidTypeValidator, }, { description: "Nil list of Validators error", value: Test{ - m: map[MessageType]Validators{ - SimpleEventMessageType: {nil}, + m: map[MessageType]Validator{ + SimpleEventMessageType: Validators{nil}, }, - defaultValidators: Validators{alwaysValid}, + defaultValidators: Validators{AlwaysValid}, }, expectedErr: ErrInvalidTypeValidator, }, { - description: "Empty map of Validators error", - value: Test{}, + description: "Nil map of Validators error", + value: Test{ + m: nil, + defaultValidators: Validators{AlwaysValid}, + }, expectedErr: ErrInvalidTypeValidator, }, } + for _, tc := range tests { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) @@ -196,9 +208,7 @@ func testAlwaysInvalid(t *testing.T) { assert := assert.New(t) msg := Message{} err := AlwaysInvalid(msg) - assert.ErrorIs(err, ErrInvalidMsgType) - } func TestHelperValidators(t *testing.T) { @@ -229,40 +239,27 @@ func TestTypeValidator(t *testing.T) { } func ExampleNewTypeValidator() { - var alwaysValid ValidatorFunc = func(msg Message) error { return nil } msgv, err := NewTypeValidator( - // Validates known msg types - map[MessageType]Validators{SimpleEventMessageType: {alwaysValid}}, - // Validates unknown msg types + // Validates found msg types + map[MessageType]Validator{SimpleEventMessageType: Validators{AlwaysValid}}, + // Validates unfound msg types AlwaysInvalid) - if err != nil { - return - } - err = msgv.Validate(Message{Type: SimpleEventMessageType}) // Found success - fmt.Println(err == nil) - // Output: true - + fmt.Printf("%v %T", err == nil, msgv) + // Output: true wrp.TypeValidator } -func ExampleTypeValidator_Validate_found() { - var alwaysValid ValidatorFunc = func(msg Message) error { return nil } +func ExampleTypeValidator_Validate() { msgv, err := NewTypeValidator( - // Validates known msg types - map[MessageType]Validators{SimpleEventMessageType: {alwaysValid}}, - // Validates unknown msg types + // Validates found msg types + map[MessageType]Validator{SimpleEventMessageType: Validators{AlwaysValid}}, + // Validates unfound msg types AlwaysInvalid) - err = msgv.Validate(Message{Type: SimpleEventMessageType}) // Found success - fmt.Println(err == nil) - // Output: true -} -func ExampleTypeValidator_Validate_notFound() { - var alwaysValid ValidatorFunc = func(msg Message) error { return nil } - msgv, err := NewTypeValidator( - // Validates known msg types - map[MessageType]Validators{SimpleEventMessageType: {alwaysValid}}, - // Validates unknown msg types - AlwaysInvalid) - err = msgv.Validate(Message{Type: CreateMessageType}) // Not Found error - fmt.Println(err == nil) - // Output: false + if err != nil { + return + } + + foundErr := msgv.Validate(Message{Type: SimpleEventMessageType}) // Found success + unfoundErr := msgv.Validate(Message{Type: CreateMessageType}) // Unfound error + fmt.Println(foundErr == nil, unfoundErr == nil) + // Output: true false } From 22ca097194233f192a8dad0c268601277c0fad71 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Fri, 3 Jun 2022 08:10:28 -0400 Subject: [PATCH 16/25] formatting --- validator_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator_test.go b/validator_test.go index 64cf8c7..afe50c5 100644 --- a/validator_test.go +++ b/validator_test.go @@ -140,7 +140,7 @@ func testNewTypeValidator(t *testing.T) { }, // Failure case { - description: "Nil list of default Validators error ", + description: "Nil list of default Validators error", value: Test{ m: map[MessageType]Validator{ SimpleEventMessageType: AlwaysValid, From 5ff49e320c248034d8432c160d16b0db30736342 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Fri, 3 Jun 2022 16:15:54 -0400 Subject: [PATCH 17/25] Add missing test for `AlwaysValid` func --- validator_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/validator_test.go b/validator_test.go index afe50c5..14bc9b8 100644 --- a/validator_test.go +++ b/validator_test.go @@ -204,6 +204,13 @@ func testNewTypeValidator(t *testing.T) { } } +func testAlwaysValid(t *testing.T) { + assert := assert.New(t) + msg := Message{} + err := AlwaysValid(msg) + assert.NoError(err) +} + func testAlwaysInvalid(t *testing.T) { assert := assert.New(t) msg := Message{} @@ -217,6 +224,7 @@ func TestHelperValidators(t *testing.T) { test func(*testing.T) }{ {"AlwaysInvalid", testAlwaysInvalid}, + {"AlwaysValid", testAlwaysValid}, } for _, tc := range tests { From 1f1aa67f5e7c1da59f826631249af115eb820c08 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Tue, 7 Jun 2022 16:32:43 -0400 Subject: [PATCH 18/25] Updates based on PR feedback * converted remaining `Validators` to `Validator` * remove func `validateValidator` * move nil checks to `Validate` func * remove Test struct * add new unexported field to check if `TypeValidato` is valid * add func `IsBad` to TypeValidato to say whether `TypeValidato` is valid * update tests for testAlwaysInvalid and testAlwaysValid * update tests names for `TestTypeValidator` * add tests for `Validators` --- validator.go | 59 +++---- validator_test.go | 387 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 294 insertions(+), 152 deletions(-) diff --git a/validator.go b/validator.go index f909660..79c6a13 100644 --- a/validator.go +++ b/validator.go @@ -24,7 +24,8 @@ import ( ) var ( - ErrInvalidTypeValidator = errors.New("invalid WRP message type validator") + ErrInvalidTypeValidator = errors.New("invalid TypeValidator") + ErrInvalidValidator = errors.New("invalid WRP message type validator") ErrInvalidMsgType = errors.New("invalid WRP message type") ) @@ -48,7 +49,9 @@ type Validators []Validator func (vs Validators) Validate(m Message) error { var err error for _, v := range vs { - err = multierr.Append(err, v.Validate(m)) + if v != nil { + err = multierr.Append(err, v.Validate(m)) + } } return err @@ -67,12 +70,17 @@ func (vf ValidatorFunc) Validate(m Message) error { // or using the defaultValidators if message type is unfound. type TypeValidator struct { m map[MessageType]Validator - defaultValidators Validators + defaultValidators Validator + isbad bool } // Validate validates messages based on message type or using the defaultValidators // if message type is unfound. func (m TypeValidator) Validate(msg Message) error { + if m.isbad { + return ErrInvalidTypeValidator + } + vs := m.m[msg.MessageType()] if vs == nil { return m.defaultValidators.Validate(msg) @@ -81,52 +89,23 @@ func (m TypeValidator) Validate(msg Message) error { return vs.Validate(msg) } +// IsBad returns a boolean indicating whether the TypeValidator receiver is valid +func (m TypeValidator) IsBad() bool { + return m.isbad +} + // NewTypeValidator is a TypeValidator factory. func NewTypeValidator(m map[MessageType]Validator, defaultValidators ...Validator) (TypeValidator, error) { if m == nil { - return TypeValidator{}, ErrInvalidTypeValidator + return TypeValidator{isbad: true}, ErrInvalidValidator } - for _, v := range m { - if err := validateValidator(v); err != nil { - return TypeValidator{}, err - } - } - - if len(defaultValidators) == 0 { + if defaultValidators == nil { defaultValidators = Validators{AlwaysInvalid} } - for _, v := range defaultValidators { - if err := validateValidator(v); err != nil { - return TypeValidator{}, err - } - } - return TypeValidator{ m: m, - defaultValidators: defaultValidators, + defaultValidators: Validators(defaultValidators), }, nil } - -// validateValidator validates a given Validator. -func validateValidator(v Validator) error { - switch vs := v.(type) { - case Validators: - if vs == nil || len(vs) == 0 { - return ErrInvalidTypeValidator - } - - for _, v := range vs { - if v == nil { - return ErrInvalidTypeValidator - } - } - case Validator, ValidatorFunc: - // catch nil Validator - default: - return ErrInvalidTypeValidator - } - - return nil -} diff --git a/validator_test.go b/validator_test.go index 14bc9b8..70701d3 100644 --- a/validator_test.go +++ b/validator_test.go @@ -23,60 +23,88 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/multierr" ) func testTypeValidatorValidate(t *testing.T) { - type Test struct { + tests := []struct { + description string m map[MessageType]Validator - defaultValidators Validators + defaultValidators []Validator msg Message - } - - tests := []struct { - description string - value Test - expectedErr error + expectedErr error }{ // Success case { description: "Found success", - value: Test{ - m: map[MessageType]Validator{ - SimpleEventMessageType: Validators{AlwaysValid}, - }, - msg: Message{Type: SimpleEventMessageType}, + m: map[MessageType]Validator{ + SimpleEventMessageType: AlwaysValid, }, + msg: Message{Type: SimpleEventMessageType}, }, { description: "Unfound success", - value: Test{ - m: map[MessageType]Validator{ - SimpleEventMessageType: Validators{AlwaysInvalid}, - }, - defaultValidators: Validators{AlwaysValid}, - msg: Message{Type: CreateMessageType}, + m: map[MessageType]Validator{ + SimpleEventMessageType: AlwaysInvalid, }, + defaultValidators: []Validator{AlwaysValid}, + msg: Message{Type: CreateMessageType}, + }, + { + description: "Unfound success, nil list of default Validators", + m: map[MessageType]Validator{ + SimpleEventMessageType: AlwaysInvalid, + }, + defaultValidators: []Validator{nil}, + msg: Message{Type: CreateMessageType}, + }, + { + description: "Unfound success, empty map of default Validators", + m: map[MessageType]Validator{ + SimpleEventMessageType: AlwaysInvalid, + }, + defaultValidators: []Validator{}, + msg: Message{Type: CreateMessageType}, }, // Failure case { description: "Found error", - value: Test{ - m: map[MessageType]Validator{ - SimpleEventMessageType: Validators{AlwaysInvalid}, - }, - defaultValidators: Validators{AlwaysValid}, - msg: Message{Type: SimpleEventMessageType}, + m: map[MessageType]Validator{ + SimpleEventMessageType: AlwaysInvalid, }, + defaultValidators: []Validator{AlwaysValid}, + msg: Message{Type: SimpleEventMessageType}, + expectedErr: ErrInvalidMsgType, + }, + { + description: "Found error, nil Validator", + m: map[MessageType]Validator{ + SimpleEventMessageType: nil, + }, + msg: Message{Type: SimpleEventMessageType}, expectedErr: ErrInvalidMsgType, }, { description: "Unfound error", - value: Test{ - m: map[MessageType]Validator{ - SimpleEventMessageType: Validators{AlwaysValid}, - }, - msg: Message{Type: CreateMessageType}, + m: map[MessageType]Validator{ + SimpleEventMessageType: AlwaysValid, + }, + msg: Message{Type: CreateMessageType}, + expectedErr: ErrInvalidMsgType, + }, + { + description: "Unfound error, nil default Validators", + m: map[MessageType]Validator{ + SimpleEventMessageType: AlwaysInvalid, }, + defaultValidators: nil, + msg: Message{Type: CreateMessageType}, + expectedErr: ErrInvalidMsgType, + }, + { + description: "Unfound error, empty map of Validators", + m: map[MessageType]Validator{}, + msg: Message{Type: CreateMessageType}, expectedErr: ErrInvalidMsgType, }, } @@ -85,10 +113,11 @@ func testTypeValidatorValidate(t *testing.T) { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) require := require.New(t) - msgv, err := NewTypeValidator(tc.value.m, tc.value.defaultValidators...) - require.NotNil(msgv) + msgv, err := NewTypeValidator(tc.m, tc.defaultValidators...) require.NoError(err) - err = msgv.Validate(tc.value.msg) + require.NotNil(msgv) + require.False(msgv.IsBad()) + err = msgv.Validate(tc.msg) if tc.expectedErr != nil { assert.ErrorIs(err, tc.expectedErr) return @@ -99,103 +128,251 @@ func testTypeValidatorValidate(t *testing.T) { } } -func testNewTypeValidator(t *testing.T) { - type Test struct { +func testTypeValidatorFactory(t *testing.T) { + tests := []struct { + description string m map[MessageType]Validator - defaultValidators Validators + defaultValidators []Validator + expectedErr error + }{ + // Success case + { + description: "Default Validators success", + m: map[MessageType]Validator{ + SimpleEventMessageType: AlwaysValid, + }, + defaultValidators: []Validator{AlwaysValid}, + expectedErr: nil, + }, + { + description: "Omit default Validators success", + m: map[MessageType]Validator{ + SimpleEventMessageType: AlwaysValid, + }, + expectedErr: nil, + }, + // Failure case + { + description: "Nil map of Validators error", + m: nil, + defaultValidators: []Validator{AlwaysValid}, + expectedErr: ErrInvalidValidator, + }, } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + msgv, err := NewTypeValidator(tc.m, tc.defaultValidators...) + assert.NotNil(msgv) + if tc.expectedErr != nil { + assert.ErrorIs(err, tc.expectedErr) + assert.ErrorIs(msgv.Validate(Message{}), ErrInvalidTypeValidator) + assert.True(msgv.IsBad()) + return + } + + assert.NoError(err) + assert.False(msgv.IsBad()) + }) + } +} + +func testAlwaysValid(t *testing.T) { + var ( + expectedStatus int64 = 3471 + expectedRequestDeliveryResponse int64 = 34 + expectedIncludeSpans bool = true + ) tests := []struct { description string - value Test - expectedErr error + msg Message + expectedErr []error }{ // Success case { - description: "Default Validators success", - value: Test{ - m: map[MessageType]Validator{ - SimpleEventMessageType: AlwaysValid, - }, - defaultValidators: Validators{AlwaysValid}, + description: "Not UTF8 success", + msg: Message{ + Type: SimpleRequestResponseMessageType, + Source: "external.com", + // Not UFT8 Destination string + Destination: "mac:\xed\xbf\xbf", + TransactionUUID: "DEADBEEF", + ContentType: "ContentType", + Accept: "Accept", + Status: &expectedStatus, + RequestDeliveryResponse: &expectedRequestDeliveryResponse, + Headers: []string{"Header1", "Header2"}, + Metadata: map[string]string{"name": "value"}, + Spans: [][]string{{"1", "2"}, {"3"}}, + IncludeSpans: &expectedIncludeSpans, + Path: "/some/where/over/the/rainbow", + Payload: []byte{1, 2, 3, 4, 0xff, 0xce}, + ServiceName: "ServiceName", + URL: "someURL.com", + PartnerIDs: []string{"foo"}, + SessionID: "sessionID123", }, - expectedErr: nil, }, { - description: "Empty map of Validators success", - value: Test{ - m: map[MessageType]Validator{}, - defaultValidators: Validators{AlwaysValid}, + description: "Filled message success", + msg: Message{ + Type: SimpleRequestResponseMessageType, + Source: "external.com", + Destination: "mac:FFEEAADD44443333", + TransactionUUID: "DEADBEEF", + ContentType: "ContentType", + Accept: "Accept", + Status: &expectedStatus, + RequestDeliveryResponse: &expectedRequestDeliveryResponse, + Headers: []string{"Header1", "Header2"}, + Metadata: map[string]string{"name": "value"}, + Spans: [][]string{{"1", "2"}, {"3"}}, + IncludeSpans: &expectedIncludeSpans, + Path: "/some/where/over/the/rainbow", + Payload: []byte{1, 2, 3, 4, 0xff, 0xce}, + ServiceName: "ServiceName", + URL: "someURL.com", + PartnerIDs: []string{"foo"}, + SessionID: "sessionID123", }, - expectedErr: nil, }, { - description: "Omit default Validators success", - value: Test{ - m: map[MessageType]Validator{ - SimpleEventMessageType: Validators{AlwaysValid}, - }, + description: "Empty message success", + msg: Message{}, + }, + { + description: "Bad message type success", + msg: Message{ + Type: lastMessageType, + Source: "external.com", + Destination: "mac:FFEEAADD44443333", }, - expectedErr: nil, }, + } + + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + err := AlwaysValid.Validate(tc.msg) + assert.NoError(err) + }) + } +} + +func testAlwaysInvalid(t *testing.T) { + var ( + expectedStatus int64 = 3471 + expectedRequestDeliveryResponse int64 = 34 + expectedIncludeSpans bool = true + ) + tests := []struct { + description string + msg Message + expectedErr []error + }{ // Failure case { - description: "Nil list of default Validators error", - value: Test{ - m: map[MessageType]Validator{ - SimpleEventMessageType: AlwaysValid, - }, - defaultValidators: Validators{nil}, + description: "Not UTF8 error", + msg: Message{ + Type: SimpleRequestResponseMessageType, + Source: "external.com", + // Not UFT8 Destination string + Destination: "mac:\xed\xbf\xbf", + TransactionUUID: "DEADBEEF", + ContentType: "ContentType", + Accept: "Accept", + Status: &expectedStatus, + RequestDeliveryResponse: &expectedRequestDeliveryResponse, + Headers: []string{"Header1", "Header2"}, + Metadata: map[string]string{"name": "value"}, + Spans: [][]string{{"1", "2"}, {"3"}}, + IncludeSpans: &expectedIncludeSpans, + Path: "/some/where/over/the/rainbow", + Payload: []byte{1, 2, 3, 4, 0xff, 0xce}, + ServiceName: "ServiceName", + URL: "someURL.com", + PartnerIDs: []string{"foo"}, + SessionID: "sessionID123", }, - expectedErr: ErrInvalidTypeValidator, }, { - description: "Empty list of Validators error", - value: Test{ - m: map[MessageType]Validator{ - SimpleEventMessageType: Validators{}, - }, - defaultValidators: Validators{AlwaysValid}, + description: "Filled message error", + msg: Message{ + Type: SimpleRequestResponseMessageType, + Source: "external.com", + Destination: "mac:FFEEAADD44443333", + TransactionUUID: "DEADBEEF", + ContentType: "ContentType", + Accept: "Accept", + Status: &expectedStatus, + RequestDeliveryResponse: &expectedRequestDeliveryResponse, + Headers: []string{"Header1", "Header2"}, + Metadata: map[string]string{"name": "value"}, + Spans: [][]string{{"1", "2"}, {"3"}}, + IncludeSpans: &expectedIncludeSpans, + Path: "/some/where/over/the/rainbow", + Payload: []byte{1, 2, 3, 4, 0xff, 0xce}, + ServiceName: "ServiceName", + URL: "someURL.com", + PartnerIDs: []string{"foo"}, + SessionID: "sessionID123", }, - expectedErr: ErrInvalidTypeValidator, }, { - description: "Nil Validator error", - value: Test{ - m: map[MessageType]Validator{ - SimpleEventMessageType: nil, - }, - defaultValidators: Validators{AlwaysValid}, - }, - expectedErr: ErrInvalidTypeValidator, + description: "Empty message error", + msg: Message{}, }, { - description: "Nil list of Validators error", - value: Test{ - m: map[MessageType]Validator{ - SimpleEventMessageType: Validators{nil}, - }, - defaultValidators: Validators{AlwaysValid}, + description: "Bad message type error", + msg: Message{ + Type: lastMessageType, + Source: "external.com", + Destination: "mac:FFEEAADD44443333", }, - expectedErr: ErrInvalidTypeValidator, }, + } + + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + err := AlwaysInvalid.Validate(tc.msg) + assert.Error(err) + }) + } +} + +func TestValidators(t *testing.T) { + tests := []struct { + description string + vs Validators + msg Message + expectedErr []error + }{ + // Success case { - description: "Nil map of Validators error", - value: Test{ - m: nil, - defaultValidators: Validators{AlwaysValid}, - }, - expectedErr: ErrInvalidTypeValidator, + description: "Empty Validators success", + vs: Validators{}, + msg: Message{Type: SimpleEventMessageType}, + }, + // Failure case + { + description: "Mix Validators error", + vs: Validators{AlwaysValid, nil, AlwaysInvalid, Validators{AlwaysValid, nil, AlwaysInvalid}}, + msg: Message{Type: SimpleEventMessageType}, + expectedErr: []error{ErrInvalidMsgType, ErrInvalidMsgType}, }, } for _, tc := range tests { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) - msgv, err := NewTypeValidator(tc.value.m, tc.value.defaultValidators...) - assert.NotNil(msgv) + err := tc.vs.Validate(tc.msg) if tc.expectedErr != nil { - assert.ErrorIs(err, tc.expectedErr) + assert.Equal(multierr.Errors(err), tc.expectedErr) + for _, e := range tc.expectedErr { + assert.ErrorIs(err, e) + } return } @@ -204,20 +381,6 @@ func testNewTypeValidator(t *testing.T) { } } -func testAlwaysValid(t *testing.T) { - assert := assert.New(t) - msg := Message{} - err := AlwaysValid(msg) - assert.NoError(err) -} - -func testAlwaysInvalid(t *testing.T) { - assert := assert.New(t) - msg := Message{} - err := AlwaysInvalid(msg) - assert.ErrorIs(err, ErrInvalidMsgType) -} - func TestHelperValidators(t *testing.T) { tests := []struct { description string @@ -237,8 +400,8 @@ func TestTypeValidator(t *testing.T) { description string test func(*testing.T) }{ - {"TypeValidator validate", testTypeValidatorValidate}, - {"TypeValidator factory", testNewTypeValidator}, + {"Validate", testTypeValidatorValidate}, + {"Factory", testTypeValidatorFactory}, } for _, tc := range tests { @@ -249,7 +412,7 @@ func TestTypeValidator(t *testing.T) { func ExampleNewTypeValidator() { msgv, err := NewTypeValidator( // Validates found msg types - map[MessageType]Validator{SimpleEventMessageType: Validators{AlwaysValid}}, + map[MessageType]Validator{SimpleEventMessageType: AlwaysValid}, // Validates unfound msg types AlwaysInvalid) fmt.Printf("%v %T", err == nil, msgv) @@ -259,7 +422,7 @@ func ExampleNewTypeValidator() { func ExampleTypeValidator_Validate() { msgv, err := NewTypeValidator( // Validates found msg types - map[MessageType]Validator{SimpleEventMessageType: Validators{AlwaysValid}}, + map[MessageType]Validator{SimpleEventMessageType: AlwaysValid}, // Validates unfound msg types AlwaysInvalid) if err != nil { From df7e2ff8508c4938c4912fb5eee7e13b616098dd Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 8 Jun 2022 05:54:33 -0400 Subject: [PATCH 19/25] Update based on PR review * [misunderstanding] Remove unexported field `isbad` from `TypeValidator` and its references * [misunderstanding] Remove `IsBad` func from `TypeValidator` * Use `assert.Zero/NotZero` funcs to test `TypeValidator`'s state --- validator.go | 12 +----------- validator_test.go | 10 +++++----- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/validator.go b/validator.go index 79c6a13..f3ed27e 100644 --- a/validator.go +++ b/validator.go @@ -71,16 +71,11 @@ func (vf ValidatorFunc) Validate(m Message) error { type TypeValidator struct { m map[MessageType]Validator defaultValidators Validator - isbad bool } // Validate validates messages based on message type or using the defaultValidators // if message type is unfound. func (m TypeValidator) Validate(msg Message) error { - if m.isbad { - return ErrInvalidTypeValidator - } - vs := m.m[msg.MessageType()] if vs == nil { return m.defaultValidators.Validate(msg) @@ -89,15 +84,10 @@ func (m TypeValidator) Validate(msg Message) error { return vs.Validate(msg) } -// IsBad returns a boolean indicating whether the TypeValidator receiver is valid -func (m TypeValidator) IsBad() bool { - return m.isbad -} - // NewTypeValidator is a TypeValidator factory. func NewTypeValidator(m map[MessageType]Validator, defaultValidators ...Validator) (TypeValidator, error) { if m == nil { - return TypeValidator{isbad: true}, ErrInvalidValidator + return TypeValidator{}, ErrInvalidValidator } if defaultValidators == nil { diff --git a/validator_test.go b/validator_test.go index 70701d3..9c2bdcb 100644 --- a/validator_test.go +++ b/validator_test.go @@ -116,7 +116,7 @@ func testTypeValidatorValidate(t *testing.T) { msgv, err := NewTypeValidator(tc.m, tc.defaultValidators...) require.NoError(err) require.NotNil(msgv) - require.False(msgv.IsBad()) + assert.NotZero(msgv) err = msgv.Validate(tc.msg) if tc.expectedErr != nil { assert.ErrorIs(err, tc.expectedErr) @@ -164,16 +164,16 @@ func testTypeValidatorFactory(t *testing.T) { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) msgv, err := NewTypeValidator(tc.m, tc.defaultValidators...) - assert.NotNil(msgv) if tc.expectedErr != nil { assert.ErrorIs(err, tc.expectedErr) - assert.ErrorIs(msgv.Validate(Message{}), ErrInvalidTypeValidator) - assert.True(msgv.IsBad()) + assert.NotNil(msgv) + assert.NotZero(msgv) return } assert.NoError(err) - assert.False(msgv.IsBad()) + // Zero asserts that msgv is the zero value for its type and not nil. + assert.Zero(msgv) }) } } From ffd531f457e777c93920a8c592816a57e35b9cac Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 8 Jun 2022 05:55:49 -0400 Subject: [PATCH 20/25] Move exported fields to the top --- validator_test.go | 186 +++++++++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/validator_test.go b/validator_test.go index 9c2bdcb..e618b25 100644 --- a/validator_test.go +++ b/validator_test.go @@ -26,6 +26,99 @@ import ( "go.uber.org/multierr" ) +func TestValidators(t *testing.T) { + tests := []struct { + description string + vs Validators + msg Message + expectedErr []error + }{ + // Success case + { + description: "Empty Validators success", + vs: Validators{}, + msg: Message{Type: SimpleEventMessageType}, + }, + // Failure case + { + description: "Mix Validators error", + vs: Validators{AlwaysValid, nil, AlwaysInvalid, Validators{AlwaysValid, nil, AlwaysInvalid}}, + msg: Message{Type: SimpleEventMessageType}, + expectedErr: []error{ErrInvalidMsgType, ErrInvalidMsgType}, + }, + } + + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + assert := assert.New(t) + err := tc.vs.Validate(tc.msg) + if tc.expectedErr != nil { + assert.Equal(multierr.Errors(err), tc.expectedErr) + for _, e := range tc.expectedErr { + assert.ErrorIs(err, e) + } + return + } + + assert.NoError(err) + }) + } +} + +func TestHelperValidators(t *testing.T) { + tests := []struct { + description string + test func(*testing.T) + }{ + {"AlwaysInvalid", testAlwaysInvalid}, + {"AlwaysValid", testAlwaysValid}, + } + + for _, tc := range tests { + t.Run(tc.description, tc.test) + } +} + +func TestTypeValidator(t *testing.T) { + tests := []struct { + description string + test func(*testing.T) + }{ + {"Validate", testTypeValidatorValidate}, + {"Factory", testTypeValidatorFactory}, + } + + for _, tc := range tests { + t.Run(tc.description, tc.test) + } +} + +func ExampleNewTypeValidator() { + msgv, err := NewTypeValidator( + // Validates found msg types + map[MessageType]Validator{SimpleEventMessageType: AlwaysValid}, + // Validates unfound msg types + AlwaysInvalid) + fmt.Printf("%v %T", err == nil, msgv) + // Output: true wrp.TypeValidator +} + +func ExampleTypeValidator_Validate() { + msgv, err := NewTypeValidator( + // Validates found msg types + map[MessageType]Validator{SimpleEventMessageType: AlwaysValid}, + // Validates unfound msg types + AlwaysInvalid) + if err != nil { + return + } + + foundErr := msgv.Validate(Message{Type: SimpleEventMessageType}) // Found success + unfoundErr := msgv.Validate(Message{Type: CreateMessageType}) // Unfound error + fmt.Println(foundErr == nil, unfoundErr == nil) + // Output: true false +} + func testTypeValidatorValidate(t *testing.T) { tests := []struct { description string @@ -341,96 +434,3 @@ func testAlwaysInvalid(t *testing.T) { }) } } - -func TestValidators(t *testing.T) { - tests := []struct { - description string - vs Validators - msg Message - expectedErr []error - }{ - // Success case - { - description: "Empty Validators success", - vs: Validators{}, - msg: Message{Type: SimpleEventMessageType}, - }, - // Failure case - { - description: "Mix Validators error", - vs: Validators{AlwaysValid, nil, AlwaysInvalid, Validators{AlwaysValid, nil, AlwaysInvalid}}, - msg: Message{Type: SimpleEventMessageType}, - expectedErr: []error{ErrInvalidMsgType, ErrInvalidMsgType}, - }, - } - - for _, tc := range tests { - t.Run(tc.description, func(t *testing.T) { - assert := assert.New(t) - err := tc.vs.Validate(tc.msg) - if tc.expectedErr != nil { - assert.Equal(multierr.Errors(err), tc.expectedErr) - for _, e := range tc.expectedErr { - assert.ErrorIs(err, e) - } - return - } - - assert.NoError(err) - }) - } -} - -func TestHelperValidators(t *testing.T) { - tests := []struct { - description string - test func(*testing.T) - }{ - {"AlwaysInvalid", testAlwaysInvalid}, - {"AlwaysValid", testAlwaysValid}, - } - - for _, tc := range tests { - t.Run(tc.description, tc.test) - } -} - -func TestTypeValidator(t *testing.T) { - tests := []struct { - description string - test func(*testing.T) - }{ - {"Validate", testTypeValidatorValidate}, - {"Factory", testTypeValidatorFactory}, - } - - for _, tc := range tests { - t.Run(tc.description, tc.test) - } -} - -func ExampleNewTypeValidator() { - msgv, err := NewTypeValidator( - // Validates found msg types - map[MessageType]Validator{SimpleEventMessageType: AlwaysValid}, - // Validates unfound msg types - AlwaysInvalid) - fmt.Printf("%v %T", err == nil, msgv) - // Output: true wrp.TypeValidator -} - -func ExampleTypeValidator_Validate() { - msgv, err := NewTypeValidator( - // Validates found msg types - map[MessageType]Validator{SimpleEventMessageType: AlwaysValid}, - // Validates unfound msg types - AlwaysInvalid) - if err != nil { - return - } - - foundErr := msgv.Validate(Message{Type: SimpleEventMessageType}) // Found success - unfoundErr := msgv.Validate(Message{Type: CreateMessageType}) // Unfound error - fmt.Println(foundErr == nil, unfoundErr == nil) - // Output: true false -} From 13a9a576c1ba8d6ee2aea8197eaed9335d62420f Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 8 Jun 2022 06:34:20 -0400 Subject: [PATCH 21/25] update tests to include correct mac length --- validator_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/validator_test.go b/validator_test.go index e618b25..8c9d440 100644 --- a/validator_test.go +++ b/validator_test.go @@ -312,7 +312,7 @@ func testAlwaysValid(t *testing.T) { msg: Message{ Type: SimpleRequestResponseMessageType, Source: "external.com", - Destination: "mac:FFEEAADD44443333", + Destination: "MAC:11:22:33:44:55:66", TransactionUUID: "DEADBEEF", ContentType: "ContentType", Accept: "Accept", @@ -339,7 +339,7 @@ func testAlwaysValid(t *testing.T) { msg: Message{ Type: lastMessageType, Source: "external.com", - Destination: "mac:FFEEAADD44443333", + Destination: "MAC:11:22:33:44:55:66", }, }, } @@ -394,7 +394,7 @@ func testAlwaysInvalid(t *testing.T) { msg: Message{ Type: SimpleRequestResponseMessageType, Source: "external.com", - Destination: "mac:FFEEAADD44443333", + Destination: "MAC:11:22:33:44:55:66", TransactionUUID: "DEADBEEF", ContentType: "ContentType", Accept: "Accept", @@ -421,7 +421,7 @@ func testAlwaysInvalid(t *testing.T) { msg: Message{ Type: lastMessageType, Source: "external.com", - Destination: "mac:FFEEAADD44443333", + Destination: "MAC:11:22:33:44:55:66", }, }, } From 3ac1d027bec3bfbbb8c469d7c2372ed5dc69c74f Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 8 Jun 2022 06:45:19 -0400 Subject: [PATCH 22/25] `testAlwaysValid` & `testAlwaysInvalid` ensure a non-existing message type is used --- validator_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/validator_test.go b/validator_test.go index 8c9d440..de5c421 100644 --- a/validator_test.go +++ b/validator_test.go @@ -337,7 +337,7 @@ func testAlwaysValid(t *testing.T) { { description: "Bad message type success", msg: Message{ - Type: lastMessageType, + Type: lastMessageType + 1, Source: "external.com", Destination: "MAC:11:22:33:44:55:66", }, @@ -419,7 +419,7 @@ func testAlwaysInvalid(t *testing.T) { { description: "Bad message type error", msg: Message{ - Type: lastMessageType, + Type: lastMessageType + 1, Source: "external.com", Destination: "MAC:11:22:33:44:55:66", }, From e553e7e250f15da86a4c34df4abdfb5bcc992d51 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 8 Jun 2022 06:48:04 -0400 Subject: [PATCH 23/25] `testTypeValidatorFactory` swap `assert.Zero/NotZero` --- validator_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/validator_test.go b/validator_test.go index de5c421..2ff1457 100644 --- a/validator_test.go +++ b/validator_test.go @@ -259,14 +259,14 @@ func testTypeValidatorFactory(t *testing.T) { msgv, err := NewTypeValidator(tc.m, tc.defaultValidators...) if tc.expectedErr != nil { assert.ErrorIs(err, tc.expectedErr) - assert.NotNil(msgv) - assert.NotZero(msgv) + // Zero asserts that msgv is the zero value for its type and not nil. + assert.Zero(msgv) return } assert.NoError(err) - // Zero asserts that msgv is the zero value for its type and not nil. - assert.Zero(msgv) + assert.NotNil(msgv) + assert.NotZero(msgv) }) } } From 8e6882ba1e63fb6bf61b2a973a1e698e0fdb7aed Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 8 Jun 2022 08:24:12 -0400 Subject: [PATCH 24/25] Add missing scheme to source fields & add missing `assert.ErrorIs` to `testAlwaysInvalid` --- validator_test.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/validator_test.go b/validator_test.go index 2ff1457..8f9278f 100644 --- a/validator_test.go +++ b/validator_test.go @@ -287,7 +287,7 @@ func testAlwaysValid(t *testing.T) { description: "Not UTF8 success", msg: Message{ Type: SimpleRequestResponseMessageType, - Source: "external.com", + Source: "dns:external.com", // Not UFT8 Destination string Destination: "mac:\xed\xbf\xbf", TransactionUUID: "DEADBEEF", @@ -307,11 +307,12 @@ func testAlwaysValid(t *testing.T) { SessionID: "sessionID123", }, }, + // Failure case { description: "Filled message success", msg: Message{ Type: SimpleRequestResponseMessageType, - Source: "external.com", + Source: "dns:external.com", Destination: "MAC:11:22:33:44:55:66", TransactionUUID: "DEADBEEF", ContentType: "ContentType", @@ -338,7 +339,7 @@ func testAlwaysValid(t *testing.T) { description: "Bad message type success", msg: Message{ Type: lastMessageType + 1, - Source: "external.com", + Source: "dns:external.com", Destination: "MAC:11:22:33:44:55:66", }, }, @@ -369,7 +370,7 @@ func testAlwaysInvalid(t *testing.T) { description: "Not UTF8 error", msg: Message{ Type: SimpleRequestResponseMessageType, - Source: "external.com", + Source: "dns:external.com", // Not UFT8 Destination string Destination: "mac:\xed\xbf\xbf", TransactionUUID: "DEADBEEF", @@ -393,7 +394,7 @@ func testAlwaysInvalid(t *testing.T) { description: "Filled message error", msg: Message{ Type: SimpleRequestResponseMessageType, - Source: "external.com", + Source: "dns:external.com", Destination: "MAC:11:22:33:44:55:66", TransactionUUID: "DEADBEEF", ContentType: "ContentType", @@ -420,7 +421,7 @@ func testAlwaysInvalid(t *testing.T) { description: "Bad message type error", msg: Message{ Type: lastMessageType + 1, - Source: "external.com", + Source: "dns:external.com", Destination: "MAC:11:22:33:44:55:66", }, }, @@ -430,7 +431,7 @@ func testAlwaysInvalid(t *testing.T) { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) err := AlwaysInvalid.Validate(tc.msg) - assert.Error(err) + assert.ErrorIs(err, ErrInvalidMsgType) }) } } From fc099bfb7b1f5e2c0737b5f5a75278ec3c4a7276 Mon Sep 17 00:00:00 2001 From: Owen Cabalceta Date: Wed, 8 Jun 2022 16:24:40 -0400 Subject: [PATCH 25/25] Update based on PR feedback * rename `defaultValidators` to `defaultValidator` * replace `defaultValidators` variadic to `defaultValidator Validator` in `NewTypeValidator` func --- validator.go | 20 ++++++++-------- validator_test.go | 58 +++++++++++++++++++++++------------------------ 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/validator.go b/validator.go index f3ed27e..1b3c07e 100644 --- a/validator.go +++ b/validator.go @@ -67,35 +67,35 @@ func (vf ValidatorFunc) Validate(m Message) error { } // TypeValidator is a WRP validator that validates based on message type -// or using the defaultValidators if message type is unfound. +// or using the defaultValidator if message type is unfound. type TypeValidator struct { - m map[MessageType]Validator - defaultValidators Validator + m map[MessageType]Validator + defaultValidator Validator } -// Validate validates messages based on message type or using the defaultValidators +// Validate validates messages based on message type or using the defaultValidator // if message type is unfound. func (m TypeValidator) Validate(msg Message) error { vs := m.m[msg.MessageType()] if vs == nil { - return m.defaultValidators.Validate(msg) + return m.defaultValidator.Validate(msg) } return vs.Validate(msg) } // NewTypeValidator is a TypeValidator factory. -func NewTypeValidator(m map[MessageType]Validator, defaultValidators ...Validator) (TypeValidator, error) { +func NewTypeValidator(m map[MessageType]Validator, defaultValidator Validator) (TypeValidator, error) { if m == nil { return TypeValidator{}, ErrInvalidValidator } - if defaultValidators == nil { - defaultValidators = Validators{AlwaysInvalid} + if defaultValidator == nil { + defaultValidator = AlwaysInvalid } return TypeValidator{ - m: m, - defaultValidators: Validators(defaultValidators), + m: m, + defaultValidator: defaultValidator, }, nil } diff --git a/validator_test.go b/validator_test.go index 8f9278f..70c3aab 100644 --- a/validator_test.go +++ b/validator_test.go @@ -121,11 +121,11 @@ func ExampleTypeValidator_Validate() { func testTypeValidatorValidate(t *testing.T) { tests := []struct { - description string - m map[MessageType]Validator - defaultValidators []Validator - msg Message - expectedErr error + description string + m map[MessageType]Validator + defaultValidator Validator + msg Message + expectedErr error }{ // Success case { @@ -140,24 +140,24 @@ func testTypeValidatorValidate(t *testing.T) { m: map[MessageType]Validator{ SimpleEventMessageType: AlwaysInvalid, }, - defaultValidators: []Validator{AlwaysValid}, - msg: Message{Type: CreateMessageType}, + defaultValidator: AlwaysValid, + msg: Message{Type: CreateMessageType}, }, { description: "Unfound success, nil list of default Validators", m: map[MessageType]Validator{ SimpleEventMessageType: AlwaysInvalid, }, - defaultValidators: []Validator{nil}, - msg: Message{Type: CreateMessageType}, + defaultValidator: Validators{nil}, + msg: Message{Type: CreateMessageType}, }, { description: "Unfound success, empty map of default Validators", m: map[MessageType]Validator{ SimpleEventMessageType: AlwaysInvalid, }, - defaultValidators: []Validator{}, - msg: Message{Type: CreateMessageType}, + defaultValidator: Validators{}, + msg: Message{Type: CreateMessageType}, }, // Failure case { @@ -165,9 +165,9 @@ func testTypeValidatorValidate(t *testing.T) { m: map[MessageType]Validator{ SimpleEventMessageType: AlwaysInvalid, }, - defaultValidators: []Validator{AlwaysValid}, - msg: Message{Type: SimpleEventMessageType}, - expectedErr: ErrInvalidMsgType, + defaultValidator: AlwaysValid, + msg: Message{Type: SimpleEventMessageType}, + expectedErr: ErrInvalidMsgType, }, { description: "Found error, nil Validator", @@ -190,9 +190,9 @@ func testTypeValidatorValidate(t *testing.T) { m: map[MessageType]Validator{ SimpleEventMessageType: AlwaysInvalid, }, - defaultValidators: nil, - msg: Message{Type: CreateMessageType}, - expectedErr: ErrInvalidMsgType, + defaultValidator: nil, + msg: Message{Type: CreateMessageType}, + expectedErr: ErrInvalidMsgType, }, { description: "Unfound error, empty map of Validators", @@ -206,7 +206,7 @@ func testTypeValidatorValidate(t *testing.T) { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) require := require.New(t) - msgv, err := NewTypeValidator(tc.m, tc.defaultValidators...) + msgv, err := NewTypeValidator(tc.m, tc.defaultValidator) require.NoError(err) require.NotNil(msgv) assert.NotZero(msgv) @@ -223,10 +223,10 @@ func testTypeValidatorValidate(t *testing.T) { func testTypeValidatorFactory(t *testing.T) { tests := []struct { - description string - m map[MessageType]Validator - defaultValidators []Validator - expectedErr error + description string + m map[MessageType]Validator + defaultValidator Validator + expectedErr error }{ // Success case { @@ -234,8 +234,8 @@ func testTypeValidatorFactory(t *testing.T) { m: map[MessageType]Validator{ SimpleEventMessageType: AlwaysValid, }, - defaultValidators: []Validator{AlwaysValid}, - expectedErr: nil, + defaultValidator: AlwaysValid, + expectedErr: nil, }, { description: "Omit default Validators success", @@ -246,17 +246,17 @@ func testTypeValidatorFactory(t *testing.T) { }, // Failure case { - description: "Nil map of Validators error", - m: nil, - defaultValidators: []Validator{AlwaysValid}, - expectedErr: ErrInvalidValidator, + description: "Nil map of Validators error", + m: nil, + defaultValidator: AlwaysValid, + expectedErr: ErrInvalidValidator, }, } for _, tc := range tests { t.Run(tc.description, func(t *testing.T) { assert := assert.New(t) - msgv, err := NewTypeValidator(tc.m, tc.defaultValidators...) + msgv, err := NewTypeValidator(tc.m, tc.defaultValidator) if tc.expectedErr != nil { assert.ErrorIs(err, tc.expectedErr) // Zero asserts that msgv is the zero value for its type and not nil.