diff --git a/Gopkg.lock b/Gopkg.lock index 632dd8d0..56004e90 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,25 +2,32 @@ [[projects]] + digest = "1:04aea75705cb453e24bf8c1506a24a5a9036537dbc61ddf71d20900d6c7c3ab9" name = "github.com/DATA-DOG/go-sqlmock" packages = ["."] + pruneopts = "UT" revision = "d76b18b42f285b792bf985118980ce9eacea9d10" version = "v1.3.0" [[projects]] + digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" name = "github.com/davecgh/go-spew" packages = ["spew"] - revision = "346938d642f2ec3594ed81d874461961cd0faa76" - version = "v1.1.0" + pruneopts = "UT" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" [[projects]] branch = "master" + digest = "1:5771b86b64a5e64d8e3d70337813686586210131ac4fb4c6a97b43c8e25e2253" name = "github.com/dgrijalva/jwt-go" packages = ["."] - revision = "0b96aaa707760d6ab28d9b9d1913ff5993328bae" + pruneopts = "UT" + revision = "3af4c746e1c248ee8491a3e0c6f7a9cd831e95f8" [[projects]] branch = "master" + digest = "1:5a8d32b3e55e592f903fead865fe933164388ef3748f23430f9ca54a0dbd87cc" name = "github.com/golang/protobuf" packages = [ "jsonpb", @@ -34,89 +41,119 @@ "ptypes/duration", "ptypes/struct", "ptypes/timestamp", - "ptypes/wrappers" + "ptypes/wrappers", ] - revision = "93b26e6a70e37abb14f2f88194949312b0592a84" + pruneopts = "UT" + revision = "31e0d063dd98c052257e5b69eeb006818133f45c" [[projects]] + digest = "1:3a26588bc48b96825977c1b3df964f8fd842cd6860cc26370588d3563433cf11" name = "github.com/google/uuid" packages = ["."] - revision = "064e2069ce9c359c118179501254f67d7d37ba24" - version = "0.2" + pruneopts = "UT" + revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494" + version = "v1.0.0" [[projects]] branch = "master" + digest = "1:a35934b7fbebbc8c1c3f06661907202f7ce6bf36375730642d049f77c86db341" name = "github.com/grpc-ecosystem/go-grpc-middleware" packages = [ ".", "auth", "logging/logrus/ctxlogrus", "tags", - "util/metautils" + "util/metautils", ] - revision = "e9c5d9645c437ab1b204cff969a2c0fb16cd4276" + pruneopts = "UT" + revision = "498ae206fc3cfe81cd82e48c1d4354026fa5f9ec" [[projects]] + digest = "1:6a06217fc753e65aea71446b777393009ef6797dadc0086c4f75bd16590be04d" name = "github.com/grpc-ecosystem/grpc-gateway" packages = [ "runtime", "runtime/internal", - "utilities" + "utilities", ] + pruneopts = "UT" revision = "92583770e3f01b09a0d3e9bdf64321d8bebd48f2" version = "v1.4.1" [[projects]] + digest = "1:6895fbe5a10c5aebd1965cac6f6905dcdb21bee01e08912d3ba6a805c2485f6a" name = "github.com/jinzhu/gorm" packages = [ ".", - "dialects/postgres" + "dialects/postgres", ] + pruneopts = "UT" revision = "6ed508ec6a4ecb3531899a69cbc746ccf65a4166" version = "v1.9.1" [[projects]] branch = "master" + digest = "1:fd97437fbb6b7dce04132cf06775bd258cce305c44add58eb55ca86c6c325160" name = "github.com/jinzhu/inflection" packages = ["."] + pruneopts = "UT" revision = "04140366298a54a039076d798123ffa108fff46c" [[projects]] branch = "master" + digest = "1:f44d34fda864bed6d6c71514cd40b2ee097e6e67f745d5d014113e1faa5af8b7" + name = "github.com/konsorten/go-windows-terminal-sequences" + packages = ["."] + pruneopts = "UT" + revision = "b729f2633dfe35f4d1d8a32385f6685610ce1cb5" + +[[projects]] + branch = "master" + digest = "1:b18ffc558326ebaed3b4a175617f1e12ed4e3f53d6ebfe5ba372a3de16d22278" name = "github.com/lib/pq" packages = [ ".", "hstore", - "oid" + "oid", ] - revision = "90697d60dd844d5ef6ff15135d0203f65d2f53b8" + pruneopts = "UT" + revision = "4ded0e9383f75c197b3a2aaa6d590ac52df6fd79" [[projects]] + digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" name = "github.com/pmezard/go-difflib" packages = ["difflib"] + pruneopts = "UT" revision = "792786c7400a136282c1664665ae0a8db921c6c2" version = "v1.0.0" [[projects]] + digest = "1:dc2d85c13ac22c22a1f3170a41a8e1b897fa05134aaf533f16df44f66a25b4a1" name = "github.com/sirupsen/logrus" packages = ["."] - revision = "3e01752db0189b9157070a0e1668a620f9a85da2" - version = "v1.0.6" + pruneopts = "UT" + revision = "a67f783a3814b8729bd2dac5780b5f78f8dbd64d" + version = "v1.1.0" [[projects]] + digest = "1:18752d0b95816a1b777505a97f71c7467a8445b8ffb55631a7bf779f6ba4fa83" name = "github.com/stretchr/testify" packages = ["assert"] + pruneopts = "UT" revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" version = "v1.2.2" [[projects]] branch = "master" + digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8" name = "golang.org/x/crypto" packages = ["ssh/terminal"] - revision = "c126467f60eb25f8f27e5a981f32a87e3965053f" + pruneopts = "UT" + revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900" [[projects]] branch = "master" + digest = "1:505dbee0833715a72a529bb57c354826ad42a4496fad787fa143699b4de1a6d0" name = "golang.org/x/net" packages = [ "context", @@ -125,20 +162,24 @@ "http2/hpack", "idna", "internal/timeseries", - "trace" + "trace", ] - revision = "3673e40ba22529d22c3fd7c93e97b0ce50fa7bdd" + pruneopts = "UT" + revision = "68fc911561ed0cb104e22deafa05515909b706ab" [[projects]] branch = "master" + digest = "1:8a35cf7e4a316cee63d627d7de15b81901a19f8a3f9aff0d1a80c746a57234d6" name = "golang.org/x/sys" packages = [ "unix", - "windows" + "windows", ] - revision = "e072cadbbdc8dd3d3ffa82b8b4b9304c261d9311" + pruneopts = "UT" + revision = "8469e314837c2e2471561de5c47bbf8bfd0d9099" [[projects]] + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" name = "golang.org/x/text" packages = [ "collate", @@ -154,23 +195,27 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable" + "unicode/rangetable", ] + pruneopts = "UT" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" + digest = "1:99c78803152bb77d5cfb7d7c903d5c99c3db256185da066c3f9d17ced45938b1" name = "google.golang.org/genproto" packages = [ "googleapis/api/annotations", "googleapis/rpc/code", "googleapis/rpc/status", - "protobuf/field_mask" + "protobuf/field_mask", ] - revision = "02b4e95473316948020af0b7a4f0f22c73929b0e" + pruneopts = "UT" + revision = "af9cb2a35e7f169ec875002c1829c9b315cddc04" [[projects]] + digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" name = "google.golang.org/grpc" packages = [ ".", @@ -197,14 +242,44 @@ "stats", "status", "tap", - "transport" + "transport", ] + pruneopts = "UT" revision = "168a6198bcb0ef175f7dacec0b8691fc141dc9b8" version = "v1.13.0" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "04664cc10ab834fd459789ef3ba1c1e3dfa0e5cecc8025720516af58fa233f4e" + input-imports = [ + "github.com/DATA-DOG/go-sqlmock", + "github.com/dgrijalva/jwt-go", + "github.com/golang/protobuf/jsonpb", + "github.com/golang/protobuf/proto", + "github.com/golang/protobuf/protoc-gen-go/generator", + "github.com/golang/protobuf/ptypes/wrappers", + "github.com/google/uuid", + "github.com/grpc-ecosystem/go-grpc-middleware/auth", + "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus", + "github.com/grpc-ecosystem/grpc-gateway/runtime", + "github.com/grpc-ecosystem/grpc-gateway/utilities", + "github.com/jinzhu/gorm", + "github.com/jinzhu/gorm/dialects/postgres", + "github.com/jinzhu/inflection", + "github.com/lib/pq", + "github.com/sirupsen/logrus", + "github.com/stretchr/testify/assert", + "golang.org/x/net/context", + "google.golang.org/genproto/googleapis/api/annotations", + "google.golang.org/genproto/googleapis/rpc/code", + "google.golang.org/genproto/protobuf/field_mask", + "google.golang.org/grpc", + "google.golang.org/grpc/codes", + "google.golang.org/grpc/credentials", + "google.golang.org/grpc/grpclog", + "google.golang.org/grpc/metadata", + "google.golang.org/grpc/status", + "google.golang.org/grpc/transport", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 47311747..ba54a2ee 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -18,9 +18,9 @@ name = "github.com/grpc-ecosystem/grpc-gateway" version = "1.4.1" -[[constraint]] +[[override]] name = "github.com/lyft/protoc-gen-validate" - version = "0.0.5" + version = "0.0.7" [[constraint]] name = "github.com/sirupsen/logrus" diff --git a/errors/mappers/validationerrors/README.md b/errors/mappers/validationerrors/README.md index 536c6a71..0933535a 100644 --- a/errors/mappers/validationerrors/README.md +++ b/errors/mappers/validationerrors/README.md @@ -87,7 +87,7 @@ Example Usage: ), errors.MapFunc(func(ctx context.Context, err error) (error, bool) { vErr, _ := err.(validationerrors.ValidationError) - return errors.NewContainer(codes.InvalidArgument, "Custom error message for field: %v reason: %v", vErr.Field, vErr.Reason), true + return errors.NewContainer(codes.InvalidArgument, "Custom error message for field: %v reason: %v", vErr.Field(), vErr.Reason()), true }), ), } diff --git a/errors/mappers/validationerrors/interceptor.go b/errors/mappers/validationerrors/interceptor.go index 296027c5..306301a8 100644 --- a/errors/mappers/validationerrors/interceptor.go +++ b/errors/mappers/validationerrors/interceptor.go @@ -3,12 +3,9 @@ package validationerrors import ( "context" "fmt" - "reflect" - "strings" - - "google.golang.org/grpc" "github.com/infobloxopen/atlas-app-toolkit/util" + "google.golang.org/grpc" ) type validator interface { @@ -32,70 +29,74 @@ func UnaryServerInterceptor() grpc.UnaryServerInterceptor { // GetValidationError function returns a validation error from an error. func GetValidationError(err error) error { - // Check if the error is of type of validation - typeOfError := reflect.TypeOf(err) - valueOfError := reflect.ValueOf(err) - - // Check if the error is a struct and a type of validation error that contains a cause. - if valueOfError.Kind() == reflect.Struct && strings.Contains(typeOfError.String(), "ValidationError") && - !valueOfError.FieldByName("Cause").IsNil() { - cause := valueOfError.FieldByName("Cause") - typeOfCause := reflect.TypeOf(cause.Interface()) - - valueOfCause := reflect.ValueOf(cause.Interface()) - if strings.Contains(typeOfCause.String(), "ValidationError") && - valueOfCause.FieldByName("Field").String() != "" && - valueOfCause.FieldByName("Reason").String() != "" && - !valueOfCause.FieldByName("Cause").IsNil() { - // Retrieve the field and reason from the error - field := valueOfCause.FieldByName("Field").String() - field = util.CamelToSnake(field) - reason := valueOfCause.FieldByName("Reason").String() - key := valueOfCause.FieldByName("Key").Bool() - causeValue := valueOfCause.FieldByName("Cause").Interface() - if causeErr, ok := causeValue.(error); ok { - return ValidationError{ - Field: field, - Reason: reason, - Key: key, - Cause: causeErr, - ErrorTypeName: typeOfCause.String(), - } + // Check if the error is type of validation + if vErr, ok := err.(RequestValidationError); ok { + if causeErr, ok := vErr.Cause().(RequestValidationError); ok { + return ValidationError{ + field: util.CamelToSnake(causeErr.Field()), + reason: causeErr.Reason(), + key: causeErr.Key(), + cause: causeErr.Cause(), } } } - // If it isn't a lyft validation error return the error return err } // ValidationError represents the validation error that contains which field failed and the reasoning behind it. type ValidationError struct { - Field string - Reason string - Key bool - Cause error - ErrorTypeName string // Error Name (“ABValidationError”) + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ValidationError) ErrorName() string { + return "ValidationError" } -// Error satisfies the builtin error interface. +// Error satisfies the builtin error interface func (e ValidationError) Error() string { cause := "" - if e.Cause != nil { - cause = fmt.Sprintf(" | caused by: %v", e.Cause.Error()) + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) } key := "" - if e.Key { + if e.key { key = "key for " } return fmt.Sprintf( - "invalid %s%s.%s: %s%s", + "invalid %sValidationError.%s: %s%s", key, - e.ErrorTypeName, - e.Field, - e.Reason, + e.field, + e.reason, cause) } var _ error = ValidationError{} + +// RequestValidationError represent a validation error +type RequestValidationError interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} + +var _ RequestValidationError = ValidationError{} diff --git a/errors/mappers/validationerrors/interceptor_test.go b/errors/mappers/validationerrors/interceptor_test.go index eda5bd5e..5c09cd5e 100644 --- a/errors/mappers/validationerrors/interceptor_test.go +++ b/errors/mappers/validationerrors/interceptor_test.go @@ -28,48 +28,48 @@ func TestUnaryServerInterceptor_ValidationErrors(t *testing.T) { // Test cases { "ValidationErrorEmail", - mockRequestValidationError{ - Field: "Payload", - Reason: "embedded message failed validation", - Cause: mockValidationError{ - Field: "PrimaryEmail", - Reason: "value must be a valid email address", - Cause: fmt.Errorf("mail: no angle-addr"), - Key: true, + mocReqValidationError{ + field: "Payload", + reason: "embedded message failed validation", + cause: mocReqValidationError{ + field: "PrimaryEmail", + reason: "value must be a valid email address", + cause: fmt.Errorf("mail: no angle-addr"), + key: true, }, - Key: true, + key: true, }, - &ValidationError{Key: true, Field: "primary_email", Reason: "value must be a valid email address", Cause: fmt.Errorf("mail: no angle-addr"), ErrorTypeName: "validationerrors.mockValidationError"}, + &ValidationError{key: true, field: "primary_email", reason: "value must be a valid email address", cause: fmt.Errorf("mail: no angle-addr")}, }, { "ValidationErrorInt", - mockRequestValidationError{ - Field: "Payload", - Reason: "embedded message failed validation", - Cause: mockValidationError{ - Field: "Id", - Reason: "value must be greater than 50", - Cause: fmt.Errorf("invalid Contact.Id"), - Key: true, + mocReqValidationError{ + field: "Payload", + reason: "embedded message failed validation", + cause: mocReqValidationError{ + field: "Id", + reason: "value must be greater than 50", + cause: fmt.Errorf("invalid Contact.Id"), + key: true, }, - Key: true, + key: true, }, - &ValidationError{Key: true, Field: "id", Reason: "value must be greater than 50", Cause: fmt.Errorf("invalid Contact.Id"), ErrorTypeName: "validationerrors.mockValidationError"}, + &ValidationError{key: true, field: "id", reason: "value must be greater than 50", cause: fmt.Errorf("invalid Contact.Id")}, }, { "ValidationErrorList", - mockRequestValidationError{ - Field: "Payload", - Reason: "embedded message failed validation", - Cause: mockValidationError{ - Field: "FirstName", - Reason: "value must not be in list [fizz buzz]", - Cause: fmt.Errorf("invalid Contact.MiddleName"), - Key: true, + mocReqValidationError{ + field: "Payload", + reason: "embedded message failed validation", + cause: mocReqValidationError{ + field: "FirstName", + reason: "value must not be in list [fizz buzz]", + cause: fmt.Errorf("invalid Contact.MiddleName"), + key: true, }, - Key: true, + key: true, }, - &ValidationError{Key: true, Field: "first_name", Reason: "value must not be in list [fizz buzz]", Cause: fmt.Errorf("invalid Contact.MiddleName"), ErrorTypeName: "validationerrors.mockValidationError"}, + &ValidationError{key: true, field: "first_name", reason: "value must not be in list [fizz buzz]", cause: fmt.Errorf("invalid Contact.MiddleName")}, }, { "NotValidationError", @@ -82,58 +82,27 @@ func TestUnaryServerInterceptor_ValidationErrors(t *testing.T) { }, { "ValidationErrorNoCause", - mockRequestValidationError{ - Field: "Payload", - Reason: "embedded message failed validation", - Key: true, + mocReqValidationError{ + field: "Payload", + reason: "embedded message failed validation", + key: true, }, - fmt.Errorf("invalid key for CreateRequest.Payload: embedded message failed validation"), + fmt.Errorf("invalid key for ValidationError.Payload: embedded message failed validation"), }, { "ValidationErrorBadCause", - mockRequestValidationError{ - Field: "Payload", - Reason: "embedded message failed validation", - Cause: fmt.Errorf("Not validation"), - Key: true, + mocReqValidationError{ + field: "Payload", + reason: "embedded message failed validation", + cause: fmt.Errorf("Not validation"), + key: true, }, - fmt.Errorf("invalid key for CreateRequest.Payload: embedded message failed validation | caused by: Not validation"), - }, - { - "ValidationErrorBadField", - mockRequestValidationError{ - Field: "Payload", - Reason: "embedded message failed validation", - Cause: mockValidationError{ - Reason: "no field", - Cause: fmt.Errorf("bad test"), - Key: true, - }, - Key: true, - }, - fmt.Errorf("invalid key for CreateRequest.Payload: embedded message failed validation | caused by: invalid key for CreateRequest.: no field | caused by: bad test"), - }, - { - "ValidationErrorBadReason", - mockRequestValidationError{ - Field: "Payload", - Reason: "embedded message failed validation", - Cause: mockValidationError{ - Field: "testField", - Cause: fmt.Errorf("bad test"), - Key: true, - }, - Key: true, - }, - fmt.Errorf("invalid key for CreateRequest.Payload: embedded message failed validation | caused by: invalid key for CreateRequest.testField: | caused by: bad test"), + fmt.Errorf("invalid key for ValidationError.Payload: embedded message failed validation | caused by: Not validation"), }, } for _, tt := range tests { - fmt.Println("THE ACTUAL method ") _, actual := UnaryServerInterceptor()(ctx, tt.actual, nil, nil) - fmt.Println("THE ACTUAL ERROR ", actual) expected := tt.expected - fmt.Println("THE EXPECTED ERROR ", expected) if actual.Error() != expected.Error() { t.Errorf("Error received was incorrect for test %s, expected: \"%s\", actual: \"%s\"", tt.name, expected, actual) } @@ -172,8 +141,8 @@ func TestUnaryServerInterceptor_Success(t *testing.T) { // testResponse represents a mock response. type testResponse struct{} -// mockRequestValidationError represents a validation request error. -type mockRequestValidationError struct { +// mockNotValidation represents anoter validate error but not validation error. +type mockNotValidation struct { Field string Reason string Cause error @@ -181,42 +150,12 @@ type mockRequestValidationError struct { } // Error satisfies the builtin error interface -func (e mockRequestValidationError) Error() string { - cause := "" - if e.Cause != nil { - cause = fmt.Sprintf(" | caused by: %v", e.Cause) - } - - key := "" - if e.Key { - key = "key for " - } - - return fmt.Sprintf( - "invalid %sCreateRequest.%s: %s%s", - key, - e.Field, - e.Reason, - cause) -} - -// Error satisfies the builtin error interface -func (e mockRequestValidationError) Validate() error { +func (e mockNotValidation) Validate() error { return e } -var _ error = mockRequestValidationError{} - -// mockValidationError represents a validation error. -type mockValidationError struct { - Field string - Reason string - Cause error - Key bool -} - // Error satisfies the builtin error interface -func (e mockValidationError) Error() string { +func (e mockNotValidation) Error() string { cause := "" if e.Cause != nil { cause = fmt.Sprintf(" | caused by: %v", e.Cause) @@ -228,46 +167,74 @@ func (e mockValidationError) Error() string { } return fmt.Sprintf( - "invalid %sCreateRequest.%s: %s%s", + "invalid %sRequest.%s: %s%s", key, e.Field, e.Reason, cause) } -var _ error = mockValidationError{} +var _ error = mockNotValidation{} -// mockNotValidation represents anoter validate error but not validation error. -type mockNotValidation struct { - Field string - Reason string - Cause error - Key bool +// mocReqValidationError is the validation error returned by +// mocReqValidationError.Validate if the designated constraints aren't met. +type mocReqValidationError struct { + field string + reason string + cause error + key bool } -// Error satisfies the builtin error interface -func (e mockNotValidation) Validate() error { - return e +// Field function returns field value. +func (e mocReqValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e mocReqValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e mocReqValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e mocReqValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e mocReqValidationError) ErrorName() string { + return "ValidationError" } // Error satisfies the builtin error interface -func (e mockNotValidation) Error() string { +func (e mocReqValidationError) Error() string { cause := "" - if e.Cause != nil { - cause = fmt.Sprintf(" | caused by: %v", e.Cause) + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) } key := "" - if e.Key { + if e.key { key = "key for " } return fmt.Sprintf( - "invalid %sRequest.%s: %s%s", + "invalid %sValidationError.%s: %s%s", key, - e.Field, - e.Reason, + e.field, + e.reason, cause) } -var _ error = mockNotValidation{} +var _ error = mocReqValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = mocReqValidationError{} + +// Validate checks the field values on mocReqValidationError with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (e mocReqValidationError) Validate() error { + return e +} diff --git a/errors/mappers/validationerrors/validationerrors.go b/errors/mappers/validationerrors/validationerrors.go index 1fb5690c..77545a55 100644 --- a/errors/mappers/validationerrors/validationerrors.go +++ b/errors/mappers/validationerrors/validationerrors.go @@ -23,7 +23,7 @@ func ToMapFunc(f func(context.Context, ValidationError) (error, bool)) errors.Ma func CondValidation() errors.MapCond { return func(err error) bool { if vErr, ok := err.(ValidationError); ok { - if vErr.Field != "" && vErr.Reason != "" { + if vErr.Field() != "" && vErr.Reason() != "" { return true } } @@ -36,7 +36,7 @@ func CondValidation() errors.MapCond { func CondFieldEq(theField string) errors.MapCond { return func(err error) bool { if vErr, ok := err.(ValidationError); ok { - if vErr.Field == theField { + if vErr.Field() == theField { return true } } @@ -49,7 +49,7 @@ func CondFieldEq(theField string) errors.MapCond { func CondReasonEq(theReason string) errors.MapCond { return func(err error) bool { if vErr, ok := err.(ValidationError); ok { - if vErr.Reason == theReason { + if vErr.Reason() == theReason { return true } } @@ -63,7 +63,7 @@ func DefaultMapping() errors.MapFunc { CondValidation(), errors.MapFunc(func(ctx context.Context, err error) (error, bool) { vErr, _ := err.(ValidationError) - return errors.NewContainer(codes.InvalidArgument, "Invalid %s: %s", vErr.Field, vErr.Reason).WithField(vErr.Field, vErr.Reason), true + return errors.NewContainer(codes.InvalidArgument, "Invalid %s: %s", vErr.Field(), vErr.Reason()).WithField(vErr.Field(), vErr.Reason()), true }), ) } diff --git a/errors/mappers/validationerrors/validationerrors_test.go b/errors/mappers/validationerrors/validationerrors_test.go index 55bb9768..ba71308f 100644 --- a/errors/mappers/validationerrors/validationerrors_test.go +++ b/errors/mappers/validationerrors/validationerrors_test.go @@ -24,7 +24,7 @@ func TestCond(t *testing.T) { }, { name: "Validation Error base", - cond: CondValidation(), in: ValidationError{Key: true, Field: "foo", Reason: "bad foo", Cause: fmt.Errorf("bad input"), ErrorTypeName: "ValidationError"}, expected: true, + cond: CondValidation(), in: ValidationError{key: true, field: "foo", reason: "bad foo", cause: fmt.Errorf("bad input")}, expected: true, }, { name: "None Validation Error", @@ -32,15 +32,15 @@ func TestCond(t *testing.T) { }, { name: "CondFieldEq non pointer", - cond: CondFieldEq("bar"), in: &ValidationError{Field: "bar"}, expected: false, + cond: CondFieldEq("bar"), in: &ValidationError{field: "bar"}, expected: false, }, { name: "CondFieldEq base", - cond: CondFieldEq("foo"), in: ValidationError{Field: "foo"}, expected: true, + cond: CondFieldEq("foo"), in: ValidationError{field: "foo"}, expected: true, }, { name: "CondFieldEq base bad", - cond: CondFieldEq("foo"), in: ValidationError{Field: "bar"}, expected: false, + cond: CondFieldEq("foo"), in: ValidationError{field: "bar"}, expected: false, }, { name: "CondFieldEq bad", @@ -48,15 +48,15 @@ func TestCond(t *testing.T) { }, { name: "CondReasonEq non pointer", - cond: CondReasonEq("foo bar"), in: &ValidationError{Reason: "foo bar"}, expected: false, + cond: CondReasonEq("foo bar"), in: &ValidationError{reason: "foo bar"}, expected: false, }, { name: "CondReasonEq base", - cond: CondReasonEq("foo bar"), in: ValidationError{Reason: "foo bar"}, expected: true, + cond: CondReasonEq("foo bar"), in: ValidationError{reason: "foo bar"}, expected: true, }, { name: "CondReasonEq base bad", - cond: CondReasonEq("foo"), in: ValidationError{Reason: "foo foo"}, expected: false, + cond: CondReasonEq("foo"), in: ValidationError{reason: "foo foo"}, expected: false, }, { name: "CondReasonEq bad", @@ -77,7 +77,7 @@ func TestMapping(t *testing.T) { // ToMapFunc Custom Mapping f := ToMapFunc(func(ctx context.Context, err ValidationError) (error, bool) { - return errors.NewContainer(codes.InvalidArgument, "custom error message for field: %v", err.Field), true + return errors.NewContainer(codes.InvalidArgument, "custom error message for field: %v", err.Field()), true }) for _, tc := range []struct { @@ -90,7 +90,7 @@ func TestMapping(t *testing.T) { }{ { name: "DefaultMapping base", - in: ValidationError{Key: true, Field: "foo", Reason: "bad foo", Cause: fmt.Errorf("bad input"), ErrorTypeName: "ValidationError"}, + in: ValidationError{key: true, field: "foo", reason: "bad foo", cause: fmt.Errorf("bad input")}, expected: true, mapping: DefaultMapping(), statusCode: codes.InvalidArgument, @@ -105,13 +105,13 @@ func TestMapping(t *testing.T) { }, { name: "DefaultMapping empty field", - in: ValidationError{Key: true, Reason: "bad foo", Cause: fmt.Errorf("bad input"), ErrorTypeName: "ValidationError"}, + in: ValidationError{key: true, reason: "bad foo", cause: fmt.Errorf("bad input")}, expected: false, mapping: DefaultMapping(), }, { name: "DefaultMapping empty reason", - in: ValidationError{Key: true, Field: "foo", Cause: fmt.Errorf("bad input"), ErrorTypeName: "ValidationError"}, + in: ValidationError{key: true, field: "foo", cause: fmt.Errorf("bad input")}, expected: false, mapping: DefaultMapping(), }, @@ -131,7 +131,7 @@ func TestMapping(t *testing.T) { }, { name: "CustomMapping CondFieldEq base", - in: ValidationError{Key: true, Field: "foo", Reason: "bad foo", Cause: fmt.Errorf("bad input"), ErrorTypeName: "ValidationError"}, + in: ValidationError{key: true, field: "foo", reason: "bad foo", cause: fmt.Errorf("bad input")}, expected: true, mapping: errors.NewMapping( errors.CondAnd( @@ -140,7 +140,7 @@ func TestMapping(t *testing.T) { ), errors.MapFunc(func(ctx context.Context, err error) (error, bool) { vErr, _ := err.(ValidationError) - return errors.NewContainer(codes.InvalidArgument, "custom error message for field: %v", vErr.Field), true + return errors.NewContainer(codes.InvalidArgument, "custom error message for field: %v", vErr.Field()), true }), ), statusCode: codes.InvalidArgument, @@ -148,7 +148,7 @@ func TestMapping(t *testing.T) { }, { name: "CustomMapping CondFieldEq bad", - in: ValidationError{Key: true, Field: "foo", Reason: "bad foo", Cause: fmt.Errorf("bad input"), ErrorTypeName: "ValidationError"}, + in: ValidationError{key: true, field: "foo", reason: "bad foo", cause: fmt.Errorf("bad input")}, expected: false, mapping: errors.NewMapping( errors.CondAnd( @@ -157,13 +157,13 @@ func TestMapping(t *testing.T) { ), errors.MapFunc(func(ctx context.Context, err error) (error, bool) { vErr, _ := err.(ValidationError) - return errors.NewContainer(codes.InvalidArgument, "custom error message for field: %v", vErr.Field), true + return errors.NewContainer(codes.InvalidArgument, "custom error message for field: %v", vErr.Field()), true }), ), }, { name: "CustomMapping CondFieldEq empty", - in: ValidationError{Key: true, Reason: "bad foo", Cause: fmt.Errorf("bad input"), ErrorTypeName: "ValidationError"}, + in: ValidationError{key: true, reason: "bad foo", cause: fmt.Errorf("bad input")}, expected: false, mapping: errors.NewMapping( errors.CondAnd( @@ -172,7 +172,7 @@ func TestMapping(t *testing.T) { ), errors.MapFunc(func(ctx context.Context, err error) (error, bool) { vErr, _ := err.(ValidationError) - return errors.NewContainer(codes.InvalidArgument, "custom error message for field: %v", vErr.Field), true + return errors.NewContainer(codes.InvalidArgument, "custom error message for field: %v", vErr.Field()), true }), ), }, @@ -184,13 +184,13 @@ func TestMapping(t *testing.T) { CondFieldEq("bar"), errors.MapFunc(func(ctx context.Context, err error) (error, bool) { vErr, _ := err.(ValidationError) - return errors.NewContainer(codes.InvalidArgument, "custom error message for field: %v", vErr.Field), true + return errors.NewContainer(codes.InvalidArgument, "custom error message for field: %v", vErr.Field()), true }), ), }, { name: "CustomMapping CondReasonEq base", - in: ValidationError{Key: true, Field: "foo", Reason: "bad foo", Cause: fmt.Errorf("bad input"), ErrorTypeName: "ValidationError"}, + in: ValidationError{key: true, field: "foo", reason: "bad foo", cause: fmt.Errorf("bad input")}, expected: true, mapping: errors.NewMapping( errors.CondAnd( @@ -199,7 +199,7 @@ func TestMapping(t *testing.T) { ), errors.MapFunc(func(ctx context.Context, err error) (error, bool) { vErr, _ := err.(ValidationError) - return errors.NewContainer(codes.InvalidArgument, "custom error message for reason: %s", vErr.Reason), true + return errors.NewContainer(codes.InvalidArgument, "custom error message for reason: %s", vErr.Reason()), true }), ), statusCode: codes.InvalidArgument, @@ -207,7 +207,7 @@ func TestMapping(t *testing.T) { }, { name: "CustomMapping CondReasonEq bad", - in: ValidationError{Key: true, Field: "foo", Reason: "bad foo", Cause: fmt.Errorf("bad input"), ErrorTypeName: "ValidationError"}, + in: ValidationError{key: true, field: "foo", reason: "bad foo", cause: fmt.Errorf("bad input")}, expected: false, mapping: errors.NewMapping( errors.CondAnd( @@ -216,13 +216,13 @@ func TestMapping(t *testing.T) { ), errors.MapFunc(func(ctx context.Context, err error) (error, bool) { vErr, _ := err.(ValidationError) - return errors.NewContainer(codes.InvalidArgument, "custom error message for reason: %v", vErr.Reason), true + return errors.NewContainer(codes.InvalidArgument, "custom error message for reason: %s", vErr.Reason()), true }), ), }, { name: "CustomMapping CondReasonEq empty", - in: ValidationError{Key: true, Field: "foo", Cause: fmt.Errorf("bad input"), ErrorTypeName: "ValidationError"}, + in: ValidationError{key: true, field: "foo", cause: fmt.Errorf("bad input")}, expected: false, mapping: errors.NewMapping( errors.CondAnd( @@ -231,7 +231,7 @@ func TestMapping(t *testing.T) { ), errors.MapFunc(func(ctx context.Context, err error) (error, bool) { vErr, _ := err.(ValidationError) - return errors.NewContainer(codes.InvalidArgument, "custom error message for reason: %v", vErr.Reason), true + return errors.NewContainer(codes.InvalidArgument, "custom error message for reason: %v", vErr.Reason()), true }), ), }, @@ -243,13 +243,13 @@ func TestMapping(t *testing.T) { CondReasonEq("bar"), errors.MapFunc(func(ctx context.Context, err error) (error, bool) { vErr, _ := err.(ValidationError) - return errors.NewContainer(codes.InvalidArgument, "custom error message for reason: %v", vErr.Reason), true + return errors.NewContainer(codes.InvalidArgument, "custom error message for reason: %v", vErr.Reason()), true }), ), }, { name: "ToMapFunc base", - in: ValidationError{Key: true, Field: "foo", Reason: "bad foo", Cause: fmt.Errorf("bad input"), ErrorTypeName: "ValidationError"}, + in: ValidationError{key: true, field: "foo", reason: "bad foo", cause: fmt.Errorf("bad input")}, mapping: errors.NewMapping( errors.CondAnd( CondValidation(),