Skip to content

Commit

Permalink
feat(errors): added error.Is compatibility (#432)
Browse files Browse the repository at this point in the history
Signed-off-by: Mateusz Urbanek <murbanek@akamai.com>
Co-authored-by: Zhiwei Liang <121905282+zliang-akamai@users.noreply.github.com>
  • Loading branch information
shanduur and zliang-akamai committed Dec 5, 2023
1 parent d853175 commit 8990c63
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 2 deletions.
17 changes: 15 additions & 2 deletions errors.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package linodego

import (
"errors"
"fmt"
"net/http"
"reflect"
Expand Down Expand Up @@ -97,8 +98,20 @@ func (e APIError) Error() string {
return strings.Join(x, "; ")
}

func (g Error) Error() string {
return fmt.Sprintf("[%03d] %s", g.Code, g.Message)
func (err Error) Error() string {
return fmt.Sprintf("[%03d] %s", err.Code, err.Message)
}

func (err Error) StatusCode() int {
return err.Code
}

func (err Error) Is(target error) bool {
if x, ok := target.(interface{ StatusCode() int }); ok || errors.As(target, &x) {
return err.StatusCode() == x.StatusCode()
}

return false
}

// NewError creates a linodego.Error with a Code identifying the source err type,
Expand Down
94 changes: 94 additions & 0 deletions errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net/http"
"net/http/httptest"
Expand Down Expand Up @@ -200,3 +201,96 @@ func TestCoupleAPIErrors(t *testing.T) {
}
})
}

func TestErrorIs(t *testing.T) {
t.Parallel()

defaultError := &Error{
Message: "default error",
Code: http.StatusInternalServerError,
}

for _, tc := range []struct {
testName string
err1 error
err2 error
expectedResult bool
}{
{
testName: "base errors.Is comparision",
err1: defaultError,
err2: defaultError,
expectedResult: true,
},
{
testName: "wrapped default",
err1: fmt.Errorf("test wrap: %w", defaultError),
err2: defaultError,
expectedResult: true,
},
{
testName: "deeply wrapped error",
err1: fmt.Errorf("wrap 1: %w", fmt.Errorf("wrap 2: %w", defaultError)),
err2: defaultError,
expectedResult: true,
},
{
testName: "default and Error from empty resty error",
err1: NewError(restyError("", "")),
err2: defaultError,
expectedResult: true,
},
{
testName: "default and Error from resty error with field",
err1: NewError(restyError("", "test field")),
err2: defaultError,
expectedResult: true,
},
{
testName: "default and Error from resty error with field and reason",
err1: NewError(restyError("test reason", "test field")),
err2: defaultError,
expectedResult: true,
},
{
testName: "default and Error from resty error with reason",
err1: NewError(restyError("test reason", "")),
err2: defaultError,
expectedResult: true,
},
{
testName: "error and nil",
err1: defaultError,
err2: nil,
expectedResult: false,
},
{
testName: "wrapped nil",
err1: fmt.Errorf("test wrap: %w", nil),
err2: defaultError,
expectedResult: false,
},
{
testName: "both errors are different nil", // NOTE: nils of different types are never equal
err1: nil,
err2: (*Error)(nil),
expectedResult: false,
},
{
testName: "different error types",
err1: errors.New("different error type"),
err2: defaultError,
expectedResult: false,
},
} {
tc := tc

t.Run(tc.testName, func(t *testing.T) {
t.Parallel()

if errors.Is(tc.err1, tc.err2) != tc.expectedResult {
t.Errorf("expected %+#v to be equal %+#v", tc.err1, tc.err2)
}
})
}
}

0 comments on commit 8990c63

Please sign in to comment.