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.
This commit is contained in:
Josh Rickmar 2013-10-09 09:44:28 -04:00
parent 7ad6d73416
commit 31489c15b3
2 changed files with 58 additions and 3 deletions

View file

@ -6,7 +6,6 @@ package btcjson
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
) )
@ -158,7 +157,15 @@ type ListUnSpentResult struct {
type Error struct { type Error struct {
Code int `json:"code,omitempty"` Code int `json:"code,omitempty"`
Message string `json:"message,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 // 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 jsonErr Error
var id interface{} var id interface{}
err = json.Unmarshal(objmap["error"], &jsonErr) err = json.Unmarshal(objmap["error"], &jsonErr)
jsonErr.Error = errors.New(string(jsonErr.Code) + ": " + jsonErr.Message)
if err != nil { if err != nil {
err = fmt.Errorf("Error unmarshalling json reply: %v", err) err = fmt.Errorf("Error unmarshalling json reply: %v", err)
return result, err return result, err

View file

@ -7,6 +7,7 @@ package btcjson_test
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"github.com/conformal/btcjson" "github.com/conformal/btcjson"
"io" "io"
"io/ioutil" "io/ioutil"
@ -381,3 +382,51 @@ func TestReadResultCmd(t *testing.T) {
return 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)
}
}
}
}