Skip to content

Commit

Permalink
Merge pull request #33 from Henry-Sarabia/iss-12
Browse files Browse the repository at this point in the history
Rename, refactor, and reorganize errors
  • Loading branch information
Henry Sarabia authored Feb 21, 2019
2 parents c90b564 + 86c75c1 commit d6da624
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 88 deletions.
2 changes: 1 addition & 1 deletion character_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func TestCharacterService_Search(t *testing.T) {
wantErr error
}{
{"Valid response", testCharacterSearch, "super", []Option{SetLimit(50)}, init, nil},
{"Empty query", testFileEmpty, "", []Option{SetLimit(50)}, nil, ErrEmptyQuery},
{"Empty query", testFileEmpty, "", []Option{SetLimit(50)}, nil, ErrEmptyQry},
{"Empty response", testFileEmpty, "super", nil, nil, errInvalidJSON},
{"Invalid option", testFileEmpty, "super", []Option{SetOffset(99999)}, nil, ErrOutOfRange},
{"No results", testFileEmptyArray, "non-existent entry", nil, nil, ErrNoResults},
Expand Down
2 changes: 1 addition & 1 deletion collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func TestCollectionService_Search(t *testing.T) {
wantErr error
}{
{"Valid response", testCollectionSearch, "super", []Option{SetLimit(50)}, init, nil},
{"Empty query", testFileEmpty, "", []Option{SetLimit(50)}, nil, ErrEmptyQuery},
{"Empty query", testFileEmpty, "", []Option{SetLimit(50)}, nil, ErrEmptyQry},
{"Empty response", testFileEmpty, "super", nil, nil, errInvalidJSON},
{"Invalid option", testFileEmpty, "super", []Option{SetOffset(99999)}, nil, ErrOutOfRange},
{"No results", testFileEmptyArray, "non-existent entry", nil, nil, ErrNoResults},
Expand Down
4 changes: 2 additions & 2 deletions endpoints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestClient_GetFields(t *testing.T) {
{"OK status with dot response", http.StatusOK, `["mugshot.width","name", "company.id"]`, []string{"company.id", "name", "mugshot.width"}, nil},
{"OK status with asterisk response", http.StatusOK, `["*"]`, []string{"*"}, nil},
{"Bad status with empty response", http.StatusBadRequest, "", nil, ErrBadRequest},
{"Not found status with error response", http.StatusNotFound, testErrNotFound, nil, ServerError{Status: 404, Message: "status not found"}},
{"Not found status with error response", http.StatusNotFound, testErrNotFound, nil, ServerError{Status: 404, Msg: "status not found"}},
}

for _, test := range tests {
Expand Down Expand Up @@ -52,7 +52,7 @@ func TestClient_GetCount(t *testing.T) {
{"OK status with count of zero response", http.StatusOK, `{"count": 0}`, 0, nil},
{"OK status with empty response", http.StatusOK, "", 0, errInvalidJSON},
{"Bad status with empty response", http.StatusBadRequest, "", 0, ErrBadRequest},
{"Not found status with error response", http.StatusNotFound, testErrNotFound, 0, ServerError{Status: 404, Message: "status not found"}},
{"Not found status with error response", http.StatusNotFound, testErrNotFound, 0, ServerError{Status: 404, Msg: "status not found"}},
}

for _, test := range tests {
Expand Down
54 changes: 37 additions & 17 deletions error.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,58 @@ package igdb

import (
"encoding/json"
"errors"
"github.com/pkg/errors"
"io/ioutil"
"log"
"net/http"
"strconv"
)

var (
// ErrNegativeID occurs when a negative ID is used as an argument in an API call.
ErrNegativeID = errors.New("ID cannot be negative")
// ErrEmptyIDs occurs when a List function is called without a populated int slice.
ErrEmptyIDs = errors.New("IDs argument empty")
// ErrNoResults occurs when the IGDB returns an empty array, void of results.
ErrNoResults = errors.New("results are empty")
// errInvalidJSON occurs when encountering an unexpected end of JSON input.
errInvalidJSON = errors.New("invalid JSON")
ErrEmptyIDs = errors.New("IDs argument empty")
)

// Errors returned when the IGDB responds with a problematic status code.
//
// For more information, visit: https://igdb.github.io/api/references/response-codes/
// Errors returned when encountering error status codes.
var (
ErrAuthFailed = errors.New("authentication failed - need valid API key in user-key header")
ErrBadRequest = errors.New("bad request - check query parameters")
ErrInternalError = errors.New("internal error - report bug")
// ErrBadRequest occurs when a request is malformed.
ErrBadRequest = ServerError{
Status: http.StatusBadRequest,
Msg: "bad request: check query parameters",
}
// ErrUnauthorized occurs when a request is made without authorization.
ErrUnauthorized = ServerError{
Status: http.StatusUnauthorized,
Msg: "authentication failed: check for valid API key in user-key header",
}
// ErrForbidden occurs when a request is made without authorization.
ErrForbidden = ServerError{
Status: http.StatusForbidden,
Msg: "authentication failed: check for valid API key in user-key header",
}
// ErrInternalError occurs when an unexpected IGDB server error occurs and should be reported.
ErrInternalError = ServerError{
Status: http.StatusInternalServerError,
Msg: "internal error: report bug",
}
)

// ServerError contains information on an
// error returned from an IGDB API call.
type ServerError struct {
Status int `json:"status"`
Message string `json:"message"`
Status int `json:"status"`
Msg string `json:"message"`
}

// Error formats the ServerError and fulfills the error interface.
func (e ServerError) Error() string {
return "server error: status: " + strconv.Itoa(e.Status) + " message: " + e.Message
return "igdb server error: status: " + strconv.Itoa(e.Status) + " message: " + e.Msg
}

// checkResponse checks the provided HTTP response
Expand All @@ -43,8 +64,10 @@ func checkResponse(resp *http.Response) error {
return nil
case http.StatusBadRequest:
return ErrBadRequest
case http.StatusUnauthorized, http.StatusForbidden:
return ErrAuthFailed
case http.StatusUnauthorized:
return ErrUnauthorized
case http.StatusForbidden:
return ErrForbidden
case http.StatusInternalServerError:
return ErrInternalError
}
Expand All @@ -59,15 +82,12 @@ func checkResponse(resp *http.Response) error {

err = json.Unmarshal(b, &e)
if err != nil {
return err
return errors.Wrap(err, "could not unmarshal server error message")
}

return e
}

// ErrNoResults occurs when the IGDB returns no results
var ErrNoResults = errors.New("results are empty")

// Byte representations of ASCII characters. Used for empty result checks.
const (
// openBracketASCII represents the ASCII code for an open bracket.
Expand Down
6 changes: 3 additions & 3 deletions error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ func TestCheckResponse(t *testing.T) {
}{
{"Status OK", http.StatusOK, "", nil},
{"Status Bad Request", http.StatusBadRequest, "", ErrBadRequest},
{"Status Unauthorized", http.StatusUnauthorized, "", ErrAuthFailed},
{"Status Forbidden", http.StatusForbidden, "", ErrAuthFailed},
{"Status Unauthorized", http.StatusUnauthorized, "", ErrUnauthorized},
{"Status Forbidden", http.StatusForbidden, "", ErrForbidden},
{"Status Internal Server Error", http.StatusInternalServerError, "", ErrInternalError},
{"Unexpected Status Not Found", http.StatusNotFound, testErrNotFound, ServerError{Status: 404, Message: "status not found"}},
{"Unexpected Status Not Found", http.StatusNotFound, testErrNotFound, ServerError{Status: 404, Msg: "status not found"}},
}

for _, test := range tests {
Expand Down
2 changes: 1 addition & 1 deletion game_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func TestGameService_Search(t *testing.T) {
wantErr error
}{
{"Valid response", testGameSearch, "mario", []Option{SetLimit(5)}, init, nil},
{"Empty query", testFileEmpty, "", []Option{SetLimit(5)}, nil, ErrEmptyQuery},
{"Empty query", testFileEmpty, "", []Option{SetLimit(5)}, nil, ErrEmptyQry},
{"Empty response", testFileEmpty, "mario", nil, nil, errInvalidJSON},
{"Invalid option", testFileEmpty, "mario", []Option{SetOffset(99999)}, nil, ErrOutOfRange},
{"No results", testFileEmptyArray, "non-existent entry", nil, nil, ErrNoResults},
Expand Down
48 changes: 24 additions & 24 deletions igdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ func TestClient_Send(t *testing.T) {
{"Status BadRequest, populated response", http.StatusBadRequest, testResult, testResultPlaceholder{}, ErrBadRequest},
{"Status BadRequest, empty array response", http.StatusBadRequest, "[]", testResultPlaceholder{}, ErrBadRequest},
{"Status BadRequest, empty response", http.StatusBadRequest, "", testResultPlaceholder{}, ErrBadRequest},
{"Status Unauthorized, populated response", http.StatusUnauthorized, testResult, testResultPlaceholder{}, ErrAuthFailed},
{"Status Unauthorized, empty array response", http.StatusUnauthorized, "[]", testResultPlaceholder{}, ErrAuthFailed},
{"Status Unauthorized, empty response", http.StatusUnauthorized, "", testResultPlaceholder{}, ErrAuthFailed},
{"Status Forbidden, populated response", http.StatusForbidden, testResult, testResultPlaceholder{}, ErrAuthFailed},
{"Status Forbidden, empty array response", http.StatusForbidden, "[]", testResultPlaceholder{}, ErrAuthFailed},
{"Status Forbidden, empty response", http.StatusForbidden, "", testResultPlaceholder{}, ErrAuthFailed},
{"Status Unauthorized, populated response", http.StatusUnauthorized, testResult, testResultPlaceholder{}, ErrUnauthorized},
{"Status Unauthorized, empty array response", http.StatusUnauthorized, "[]", testResultPlaceholder{}, ErrUnauthorized},
{"Status Unauthorized, empty response", http.StatusUnauthorized, "", testResultPlaceholder{}, ErrUnauthorized},
{"Status Forbidden, populated response", http.StatusForbidden, testResult, testResultPlaceholder{}, ErrForbidden},
{"Status Forbidden, empty array response", http.StatusForbidden, "[]", testResultPlaceholder{}, ErrForbidden},
{"Status Forbidden, empty response", http.StatusForbidden, "", testResultPlaceholder{}, ErrForbidden},
{"Status InternalServerError, populated response", http.StatusInternalServerError, testResult, testResultPlaceholder{}, ErrInternalError},
{"Status InternalServerError, empty array response", http.StatusInternalServerError, "[]", testResultPlaceholder{}, ErrInternalError},
{"Status InternalServerError, empty response", http.StatusInternalServerError, "", testResultPlaceholder{}, ErrInternalError},
Expand Down Expand Up @@ -304,23 +304,23 @@ func TestClient_Get(t *testing.T) {
testResult,
[]Option{},
testResultPlaceholder{},
ErrAuthFailed,
ErrUnauthorized,
},
{
"Status Unauthorized, populated response, single valid option",
http.StatusUnauthorized,
testResult,
[]Option{SetLimit(15)},
testResultPlaceholder{},
ErrAuthFailed,
ErrUnauthorized,
},
{
"Status Unauthorized, populated response, multiple valid options",
http.StatusUnauthorized,
testResult,
[]Option{SetLimit(15), SetOffset(20)},
testResultPlaceholder{},
ErrAuthFailed,
ErrUnauthorized,
},
{
"Status Unauthorized, populated response, single invalid option",
Expand All @@ -336,23 +336,23 @@ func TestClient_Get(t *testing.T) {
"[]",
[]Option{},
testResultPlaceholder{},
ErrAuthFailed,
ErrUnauthorized,
},
{
"Status Unauthorized, empty array response, single valid option",
http.StatusUnauthorized,
"[]",
[]Option{SetLimit(15)},
testResultPlaceholder{},
ErrAuthFailed,
ErrUnauthorized,
},
{
"Status Unauthorized, empty array response, multiple valid options",
http.StatusUnauthorized,
"[]",
[]Option{SetLimit(15), SetOffset(20)},
testResultPlaceholder{},
ErrAuthFailed,
ErrUnauthorized,
},
{
"Status Unauthorized, empty array response, single invalid option",
Expand All @@ -368,23 +368,23 @@ func TestClient_Get(t *testing.T) {
"",
[]Option{},
testResultPlaceholder{},
ErrAuthFailed,
ErrUnauthorized,
},
{
"Status Unauthorized, empty response, single valid option",
http.StatusUnauthorized,
"",
[]Option{SetLimit(15)},
testResultPlaceholder{},
ErrAuthFailed,
ErrUnauthorized,
},
{
"Status Unauthorized, empty response, multiple valid options",
http.StatusUnauthorized,
"",
[]Option{SetLimit(15), SetOffset(20)},
testResultPlaceholder{},
ErrAuthFailed,
ErrUnauthorized,
},
{
"Status Unauthorized, empty response, single invalid option",
Expand All @@ -400,23 +400,23 @@ func TestClient_Get(t *testing.T) {
testResult,
[]Option{},
testResultPlaceholder{},
ErrAuthFailed,
ErrForbidden,
},
{
"Status Forbidden, populated response, single valid option",
http.StatusForbidden,
testResult,
[]Option{SetLimit(15)},
testResultPlaceholder{},
ErrAuthFailed,
ErrForbidden,
},
{
"Status Forbidden, populated response, multiple valid options",
http.StatusForbidden,
testResult,
[]Option{SetLimit(15), SetOffset(20)},
testResultPlaceholder{},
ErrAuthFailed,
ErrForbidden,
},
{
"Status Forbidden, populated response, single invalid option",
Expand All @@ -432,23 +432,23 @@ func TestClient_Get(t *testing.T) {
"[]",
[]Option{},
testResultPlaceholder{},
ErrAuthFailed,
ErrForbidden,
},
{
"Status Forbidden, empty array response, single valid option",
http.StatusForbidden,
"[]",
[]Option{SetLimit(15)},
testResultPlaceholder{},
ErrAuthFailed,
ErrForbidden,
},
{
"Status Forbidden, empty array response, multiple valid options",
http.StatusForbidden,
"[]",
[]Option{SetLimit(15), SetOffset(20)},
testResultPlaceholder{},
ErrAuthFailed,
ErrForbidden,
},
{
"Status Forbidden, empty array response, single invalid option",
Expand All @@ -464,23 +464,23 @@ func TestClient_Get(t *testing.T) {
"",
[]Option{},
testResultPlaceholder{},
ErrAuthFailed,
ErrForbidden,
},
{
"Status Forbidden, empty response, single valid option",
http.StatusForbidden,
"",
[]Option{SetLimit(15)},
testResultPlaceholder{},
ErrAuthFailed,
ErrForbidden,
},
{
"Status Forbidden, empty response, multiple valid options",
http.StatusForbidden,
"",
[]Option{SetLimit(15), SetOffset(20)},
testResultPlaceholder{},
ErrAuthFailed,
ErrForbidden,
},
{
"Status Forbidden, empty response, single invalid option",
Expand Down
6 changes: 3 additions & 3 deletions image.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import (

// Errors returned when creating Image URLs.
var (
// ErrBlankID occurs when an empty string is used as an argument in a function.
ErrBlankID = errors.New("igdb: id value empty")
// ErrBlankID occurs when an empty string is used as an argument.
ErrBlankID = errors.New("image id value empty")
// ErrPixelRatio occurs when an unsupported display pixel ratio is used as an argument in a function.
ErrPixelRatio = errors.New("igdb: invalid display pixel ratio")
ErrPixelRatio = errors.New("invalid display pixel ratio")
)

//go:generate gomodifytags -file $GOFILE -struct Image -add-tags json -w
Expand Down
Loading

0 comments on commit d6da624

Please sign in to comment.