From 51d91f4274b06a4b07550d33663bae135b2734c5 Mon Sep 17 00:00:00 2001 From: Luther Monson Date: Thu, 5 Oct 2023 03:10:32 -0700 Subject: [PATCH] refactor to NewError to not log fatal or panic, add tests --- errors.go | 14 +++++++------- errors_test.go | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/errors.go b/errors.go index d7e7ae291..702959049 100644 --- a/errors.go +++ b/errors.go @@ -2,20 +2,21 @@ package linodego import ( "fmt" - "log" "net/http" + "reflect" "strings" "github.com/go-resty/resty/v2" ) const ( + ErrorUnsupported = iota // ErrorFromString is the Code identifying Errors created by string types - ErrorFromString = 1 + ErrorFromString // ErrorFromError is the Code identifying Errors created by error types - ErrorFromError = 2 + ErrorFromError // ErrorFromStringer is the Code identifying Errors created by fmt.Stringer types - ErrorFromStringer = 3 + ErrorFromStringer ) // Error wraps the LinodeGo error with the relevant http.Response @@ -113,7 +114,7 @@ func NewError(err any) *Error { apiError, ok := e.Error().(*APIError) if !ok { - log.Fatalln("Unexpected Resty Error Response") + return &Error{Code: ErrorUnsupported, Message: "Unexpected Resty Error Response, no error"} } return &Error{ @@ -128,7 +129,6 @@ func NewError(err any) *Error { case fmt.Stringer: return &Error{Code: ErrorFromStringer, Message: e.String()} default: - log.Fatalln("Unsupported type to linodego.NewError") - panic(err) + return &Error{Code: ErrorUnsupported, Message: fmt.Sprintf("Unsupported type to linodego.NewError: %s", reflect.TypeOf(e))} } } diff --git a/errors_test.go b/errors_test.go index ee379365d..7206cdcb8 100644 --- a/errors_test.go +++ b/errors_test.go @@ -13,6 +13,58 @@ import ( "github.com/google/go-cmp/cmp" ) +type tstringer string + +func (t tstringer) String() string { + return string(t) +} + +func TestNewError(t *testing.T) { + if NewError(nil) != nil { + t.Errorf("nil error should return nil") + } + if NewError(struct{}{}).Code != ErrorUnsupported { + t.Error("empty struct should return unsupported error type") + } + err := errors.New("test") + newErr := NewError(&err) + if newErr.Message == err.Error() && newErr.Code == ErrorFromError { + t.Error("nil error should return nil") + } + + if err := NewError(&resty.Response{Request: &resty.Request{}}); err.Message != "Unexpected Resty Error Response, no error" { + t.Error("Unexpected Resty Error Response, no error") + } + + rerr := &resty.Response{ + RawResponse: &http.Response{ + StatusCode: 500, + }, + Request: &resty.Request{ + Error: &APIError{ + []APIErrorReason{ + { + Reason: "testreason", + Field: "testfield", + }, + }, + }, + }, + } + + if err := NewError(rerr); err.Message != "[testfield] testreason" { + t.Error("rest response error should should be set") + } + + if err := NewError("stringerror"); err.Message != "stringerror" || err.Code != ErrorFromString { + t.Errorf("string error should be set") + } + + if err := NewError(tstringer("teststringer")); err.Message != "teststringer" || err.Code != ErrorFromStringer { + t.Errorf("stringer error should be set") + } +} + func createTestServer(method, route, contentType, body string, statusCode int) (*httptest.Server, *Client) { h := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { if r.Method == method && r.URL.Path == route {