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:
parent
7ad6d73416
commit
31489c15b3
2 changed files with 58 additions and 3 deletions
12
jsonapi.go
12
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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue