consensus/monero/client/rpc/client_test.go
DataHoarder 5136295d91
All checks were successful
continuous-integration/drone/push Build is passing
Remove github.com/sclevine/spec dependency on tests from monero levin/rpc packages
2024-04-11 03:47:52 +02:00

213 lines
5.3 KiB
Go

package rpc_test
import (
"context"
"fmt"
"git.gammaspectra.live/P2Pool/consensus/v3/utils"
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"git.gammaspectra.live/P2Pool/consensus/v3/monero/client/rpc"
)
func assertError(t *testing.T, err error, msgAndArgs ...any) {
if err == nil {
message := ""
if len(msgAndArgs) > 0 {
message = fmt.Sprint(msgAndArgs...) + ": "
}
t.Errorf("%sexpected err", message)
}
}
func assertContains(t *testing.T, actual, expected string, msgAndArgs ...any) {
if !strings.Contains(actual, expected) {
message := ""
if len(msgAndArgs) > 0 {
message = fmt.Sprint(msgAndArgs...) + ": "
}
t.Errorf("%sactual: %v expected: %v", message, actual, expected)
}
}
func assertEqual(t *testing.T, actual, expected any, msgAndArgs ...any) {
if !reflect.DeepEqual(actual, expected) {
message := ""
if len(msgAndArgs) > 0 {
message = fmt.Sprint(msgAndArgs...) + ": "
}
t.Errorf("%sactual: %v expected: %v", message, actual, expected)
}
}
func it(t *testing.T, msg string, f func(t *testing.T)) {
t.Run(msg, func(t *testing.T) {
f(t)
})
}
// nolint:funlen
func TestClient(t *testing.T) {
t.Parallel()
t.Run("JSONRPC", func(t *testing.T) {
var (
ctx = context.Background()
client *rpc.Client
err error
)
it(t, "errors when daemon down", func(t *testing.T) {
daemon := httptest.NewServer(http.HandlerFunc(nil))
daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = client.JSONRPC(ctx, "method", nil, nil)
assertError(t, err)
assertContains(t, err.Error(), "do:")
})
it(t, "errors w/ empty response", func(t *testing.T) {
handler := func(w http.ResponseWriter, r *http.Request) {}
daemon := httptest.NewServer(http.HandlerFunc(handler))
defer daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = client.JSONRPC(ctx, "method", nil, nil)
assertError(t, err)
assertContains(t, err.Error(), "decode")
})
it(t, "errors w/ non-200 response", func(t *testing.T) {
handler := func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(500)
}
daemon := httptest.NewServer(http.HandlerFunc(handler))
defer daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = client.JSONRPC(ctx, "method", nil, nil)
assertError(t, err)
assertContains(t, err.Error(), "non-2xx status")
})
it(t, "makes GET request to the jsonrpc endpoint", func(t *testing.T) {
var (
endpoint string
method string
)
handler := func(w http.ResponseWriter, r *http.Request) {
endpoint = r.URL.Path
method = r.Method
}
daemon := httptest.NewServer(http.HandlerFunc(handler))
defer daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = client.JSONRPC(ctx, "method", nil, nil)
assertEqual(t, rpc.EndpointJSONRPC, endpoint)
assertEqual(t, method, "GET")
})
it(t, "encodes rpc in request", func(t *testing.T) {
var (
body = &rpc.RequestEnvelope{}
params = map[string]interface{}{
"foo": "bar",
"caz": 123.123,
}
)
handler := func(w http.ResponseWriter, r *http.Request) {
err := utils.NewJSONDecoder(r.Body).Decode(body)
if err != nil {
t.Errorf("unexpected err: %v", err)
}
}
daemon := httptest.NewServer(http.HandlerFunc(handler))
defer daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = client.JSONRPC(ctx, "rpc-method", params, nil)
assertEqual(t, body.ID, "0")
assertEqual(t, body.JSONRPC, "2.0")
assertEqual(t, body.Method, "rpc-method")
assertEqual(t, body.Params, params)
})
it(t, "captures result", func(t *testing.T) {
handler := func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, `{"id":"id", "jsonrpc":"jsonrpc", "result": {"foo": "bar"}}`)
}
daemon := httptest.NewServer(http.HandlerFunc(handler))
defer daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
result := map[string]string{}
err = client.JSONRPC(ctx, "rpc-method/home/shoghicp/radio/p2pool-observer", nil, &result)
if err != nil {
t.Errorf("unexpected err: %v", err)
}
assertEqual(t, result, map[string]string{"foo": "bar"})
})
it(t, "fails if rpc errored", func(t *testing.T) {
handler := func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, `{"id":"id", "jsonrpc":"jsonrpc", "error": {"code": -1, "message":"foo"}}`)
}
daemon := httptest.NewServer(http.HandlerFunc(handler))
defer daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
result := map[string]string{}
err = client.JSONRPC(ctx, "rpc-method", nil, &result)
assertError(t, err)
assertContains(t, err.Error(), "foo")
assertContains(t, err.Error(), "-1")
})
})
}