-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
client: Add tests for error handling.
The tests are to ensure that vspd errors are correctly wrapped as types.ErrorResponse, and non-vspd errors contain adequate information for debugging. A small change in the client code itself was required to satisfy these conditions.
- Loading branch information
1 parent
36505b5
commit 31a2726
Showing
2 changed files
with
106 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
|
||
"github.com/decred/dcrd/txscript/v4/stdaddr" | ||
"github.com/decred/slog" | ||
"github.com/decred/vspd/types" | ||
) | ||
|
||
func NoopSign(ctx context.Context, message string, address stdaddr.Address) ([]byte, error) { | ||
return nil, nil | ||
} | ||
|
||
func NoopValidate(resp *http.Response, body []byte, serverPubkey []byte) error { | ||
return nil | ||
} | ||
|
||
// TestErrorDetails ensures errors returned by client.do contain adequate | ||
// information for debugging (HTTP status and response body). | ||
func TestErrorDetails(t *testing.T) { | ||
|
||
tests := map[string]struct { | ||
httpStatus int | ||
responseBodyBytes []byte | ||
expectedErr string | ||
vspdError bool | ||
}{ | ||
"500, vspd error": { | ||
httpStatus: 500, | ||
responseBodyBytes: []byte(`{"code": 1, "message": "bad request"}`), | ||
expectedErr: `bad request`, | ||
vspdError: true, | ||
}, | ||
"500, no body": { | ||
httpStatus: 500, | ||
responseBodyBytes: nil, | ||
expectedErr: `http status 500 (Internal Server Error) with no body`, | ||
vspdError: false, | ||
}, | ||
"500, non vspd error": { | ||
httpStatus: 500, | ||
responseBodyBytes: []byte(`an error occurred`), | ||
expectedErr: `http status 500 (Internal Server Error) with body "an error occurred"`, | ||
vspdError: false, | ||
}, | ||
"500, non vspd error (json)": { | ||
httpStatus: 500, | ||
responseBodyBytes: []byte(`{"some": "json"}`), | ||
expectedErr: `http status 500 (Internal Server Error) with body "{\"some\": \"json\"}"`, | ||
vspdError: false, | ||
}, | ||
} | ||
|
||
for testName, testData := range tests { | ||
t.Run(testName, func(t *testing.T) { | ||
|
||
testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { | ||
res.WriteHeader(testData.httpStatus) | ||
_, err := res.Write(testData.responseBodyBytes) | ||
if err != nil { | ||
t.Fatalf("writing response body failed: %v", err) | ||
} | ||
})) | ||
|
||
client := Client{ | ||
URL: testServer.URL, | ||
PubKey: []byte("fake pubkey"), | ||
Sign: NoopSign, | ||
Validate: NoopValidate, | ||
Log: slog.Disabled, | ||
} | ||
|
||
var resp interface{} | ||
err := client.do(context.TODO(), http.MethodGet, "", nil, &resp, nil) | ||
|
||
testServer.Close() | ||
|
||
if err == nil { | ||
t.Fatalf("client.do did not return an error") | ||
} | ||
|
||
if err.Error() != testData.expectedErr { | ||
t.Fatalf("client.do returned incorrect error, expected %q, got %q", | ||
testData.expectedErr, err.Error()) | ||
} | ||
|
||
if testData.vspdError { | ||
// Error should be unwrappable as a vspd error response. | ||
var e types.ErrorResponse | ||
if !errors.As(err, &e) { | ||
t.Fatal("unable to unwrap vspd error") | ||
} | ||
} | ||
|
||
}) | ||
} | ||
} |