diff --git a/internals/api/uuid/uuid.go b/internals/api/uuid/uuid.go index d958e5de..d6813068 100644 --- a/internals/api/uuid/uuid.go +++ b/internals/api/uuid/uuid.go @@ -9,8 +9,7 @@ import ( // Errors var ( - errInvalidUUID = errio.Namespace("uuid").Code("invalid") - ErrInvalidUUIDErr = errInvalidUUID.ErrorPref("invalid uuid: %s") + ErrInvalidUUID = errio.Namespace("uuid").Code("invalid").ErrorPref("invalid uuid: %s") ) // UUID is a wrapper around go.uuid.UUID @@ -28,7 +27,7 @@ func New() *UUID { func FromString(str string) (*UUID, error) { id, err := gid.FromString(str) if err != nil { - return nil, ErrInvalidUUIDErr(err) + return nil, ErrInvalidUUID(err) } return &UUID{id}, nil } @@ -53,12 +52,3 @@ func Validate(str string) error { _, err := FromString(str) return err } - -// IsErrInvalidUUID returns whether the given error is returned for an invalid uuid. -func IsErrInvalidUUID(err error) bool { - publicErr, ok := err.(errio.PublicError) - if !ok { - return false - } - return publicErr.Namespace == errInvalidUUID.Namespace && publicErr.Code == errInvalidUUID.Code -} diff --git a/internals/errio/errors.go b/internals/errio/errors.go index bda15b17..ea490e0b 100644 --- a/internals/errio/errors.go +++ b/internals/errio/errors.go @@ -254,3 +254,12 @@ func Wrap(base PublicStatusError, errs ...error) PublicStatusError { return base } + +// Equals returns whether the errors have matching namespace and code. +func Equals(a PublicError, b error) bool { + publicError, ok := b.(PublicError) + if !ok { + return false + } + return a.Namespace == publicError.Namespace && a.Code == publicError.Code +} diff --git a/internals/errio/errors_test.go b/internals/errio/errors_test.go index 32e767b9..9e763e86 100644 --- a/internals/errio/errors_test.go +++ b/internals/errio/errors_test.go @@ -6,6 +6,8 @@ import ( "net/http" "reflect" "testing" + + "github.com/secrethub/secrethub-go/internals/assert" ) var ( @@ -112,3 +114,40 @@ func TestUnexpectedStatusError(t *testing.T) { t.Error("returned error does not contain a message") } } + +func TestEquals(t *testing.T) { + cases := map[string]struct { + a PublicError + b error + expected bool + }{ + "completely equal errors": { + a: Namespace("app").Code("invalid foo").Error("invalid value for foo: value should be a string"), + b: Namespace("app").Code("invalid foo").Error("invalid value for foo: value should be a string"), + expected: true, + }, + "different error message": { + a: Namespace("app").Code("invalid value").Error("invalid value for foo: value should be a string"), + b: Namespace("app").Code("invalid value").Error("invalid value for foo: value cannot contain special characters"), + expected: true, + }, + "different namespace": { + a: Namespace("app").Code("invalid foo").Error("invalid value for foo: value should be a string"), + b: Namespace("foo").Code("invalid foo").Error("invalid value for foo: value should be a string"), + expected: false, + }, + "different code": { + a: Namespace("app").Code("invalid foo").Error("invalid value for foo: value should be a string"), + b: Namespace("app").Code("unauthenticated").Error("request is not authenticated"), + expected: false, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + actual := Equals(tc.a, tc.b) + + assert.Equal(t, actual, tc.expected) + }) + } +}