From 31489c15b3a178562aa4245a83e353414ddeb044 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Wed, 9 Oct 2013 09:44:28 -0400 Subject: [PATCH] Remove the embedded error and satisify the builtin error interface This also adds tests to verify that the created error string follows the expected format of "code: message" and tests to verify that Error can be used as an error. Additionally, the idiom var _, _ error = Error{}, &Error{} was added so the build will fail if the builtin error interface is never satisified in the future. --- jsonapi.go | 12 +++++++++--- jsonapi_test.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/jsonapi.go b/jsonapi.go index 0752a702..30d30578 100644 --- a/jsonapi.go +++ b/jsonapi.go @@ -6,7 +6,6 @@ package btcjson import ( "encoding/json" - "errors" "fmt" ) @@ -158,7 +157,15 @@ type ListUnSpentResult struct { type Error struct { Code int `json:"code,omitempty"` Message string `json:"message,omitempty"` - Error error `json:"-"` +} + +// Guarantee Error satisifies the builtin error interface +var _, _ error = Error{}, &Error{} + +// Error returns a string describing the btcjson error. This +// satisifies the builtin error interface. +func (e Error) Error() string { + return fmt.Sprintf("%d: %s", e.Code, e.Message) } // jsonWithArgs takes a command, an id, and an interface which contains an @@ -723,7 +730,6 @@ func ReadResultCmd(cmd string, message []byte) (Reply, error) { var jsonErr Error var id interface{} err = json.Unmarshal(objmap["error"], &jsonErr) - jsonErr.Error = errors.New(string(jsonErr.Code) + ": " + jsonErr.Message) if err != nil { err = fmt.Errorf("Error unmarshalling json reply: %v", err) return result, err diff --git a/jsonapi_test.go b/jsonapi_test.go index 24c076ca..1135d2c0 100644 --- a/jsonapi_test.go +++ b/jsonapi_test.go @@ -7,6 +7,7 @@ package btcjson_test import ( "bytes" "encoding/json" + "fmt" "github.com/conformal/btcjson" "io" "io/ioutil" @@ -381,3 +382,51 @@ func TestReadResultCmd(t *testing.T) { return } + +// TestErrorInterface tests that the Error type satisifies the builtin +// error interface and tests that the error string is created in the form +// "code: message". +func TestErrorInterface(t *testing.T) { + codes := []int{ + -1, + 0, + 1, + } + messages := []string{ + "parse error", + "error getting field", + "method not found", + } + + // Create an Error and check that both Error and *Error can be used + // as an error. + var jsonError btcjson.Error + var iface interface{} = jsonError + var ifacep interface{} = &jsonError + if _, ok := iface.(error); !ok { + t.Error("cannot type assert Error as error") + return + } + if _, ok := ifacep.(error); !ok { + t.Error("cannot type assert *Error as error") + return + } + + // Verify jsonError is converted to the expected string using a few + // combinations of codes and messages. + for _, code := range codes { + for _, message := range messages { + // Create Error + jsonError := btcjson.Error{ + Code: code, + Message: message, + } + + exp := fmt.Sprintf("%d: %s", jsonError.Code, jsonError.Message) + res := fmt.Sprintf("%v", jsonError) + if exp != res { + t.Errorf("error string '%s' differs from expected '%v'", res, exp) + } + } + } +}