Remove github.com/stretchr/testify from monero levin/rpc tests
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
DataHoarder 2024-04-07 19:48:55 +02:00
parent b36c9561b9
commit 1f33aeccc5
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
5 changed files with 163 additions and 101 deletions

7
go.mod
View file

@ -13,7 +13,6 @@ require (
github.com/go-zeromq/zmq4 v0.16.1-0.20240124085909-e75c615ba1b3
github.com/goccy/go-json v0.10.2
github.com/sclevine/spec v1.4.0
github.com/stretchr/testify v1.8.1
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc
golang.org/x/sys v0.19.0
lukechampine.com/uint128 v1.3.0
@ -21,16 +20,10 @@ require (
require (
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dolthub/maphash v0.1.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace github.com/goccy/go-json => github.com/WeebDataHoarder/go-json v0.0.0-20230730135821-d8f6463bb887

17
go.sum
View file

@ -14,8 +14,6 @@ github.com/WeebDataHoarder/go-json v0.0.0-20230730135821-d8f6463bb887 h1:P01nqSM
github.com/WeebDataHoarder/go-json v0.0.0-20230730135821-d8f6463bb887/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dolthub/maphash v0.1.0 h1:bsQ7JsF4FkkWyrP3oCnFJgrCUAFbFf3kOl4L/QxPDyQ=
@ -24,21 +22,10 @@ github.com/dolthub/swiss v0.2.2-0.20240312182618-f4b2babd2bc1 h1:F7u1ZVCidajlPuJ
github.com/dolthub/swiss v0.2.2-0.20240312182618-f4b2babd2bc1/go.mod h1:8AhKZZ1HK7g18j7v7k6c5cYIGEZJcPn0ARsai8cUrh0=
github.com/floatdrop/lru v1.3.0 h1:83abtaKjXcWrPmtzTAk2Ggq8DUKqI29YzrTrB8+vu0c=
github.com/floatdrop/lru v1.3.0/go.mod h1:83zlXKA06Bm32JImNINCiTr0ldadvdAjUe5jSwIaw0s=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
@ -51,10 +38,6 @@ golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=

View file

@ -1,15 +1,56 @@
package levin_test
import (
"fmt"
"reflect"
"strings"
"testing"
"git.gammaspectra.live/P2Pool/consensus/v3/monero/client/levin"
"github.com/sclevine/spec"
"github.com/sclevine/spec/report"
"github.com/stretchr/testify/assert"
"git.gammaspectra.live/P2Pool/consensus/v3/monero/client/levin"
)
func assertNoError(t *testing.T, err error, msgAndArgs ...any) {
if err != nil {
message := ""
if len(msgAndArgs) > 0 {
message = fmt.Sprint(msgAndArgs...) + ": "
}
t.Errorf("%sunexpected err: %s", message, err)
}
}
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 TestLevin(t *testing.T) {
spec.Run(t, "NewHeaderFromBytes", func(t *testing.T, when spec.G, it spec.S) {
it("fails w/ wrong size", func() {
@ -18,7 +59,7 @@ func TestLevin(t *testing.T) {
}
_, err := levin.NewHeaderFromBytesBytes(bytes)
assert.Error(t, err)
assertError(t, err)
})
it("fails w/ wrong signature", func() {
@ -35,8 +76,8 @@ func TestLevin(t *testing.T) {
}
_, err := levin.NewHeaderFromBytesBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "signature mismatch")
assertError(t, err)
assertContains(t, err.Error(), "signature mismatch")
})
it("fails w/ invalid command", func() {
@ -53,8 +94,8 @@ func TestLevin(t *testing.T) {
}
_, err := levin.NewHeaderFromBytesBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid command")
assertError(t, err)
assertContains(t, err.Error(), "invalid command")
})
it("fails w/ invalid return code", func() {
@ -71,8 +112,8 @@ func TestLevin(t *testing.T) {
}
_, err := levin.NewHeaderFromBytesBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid return code")
assertError(t, err)
assertContains(t, err.Error(), "invalid return code")
})
it("fails w/ invalid version", func() {
@ -89,8 +130,8 @@ func TestLevin(t *testing.T) {
}
_, err := levin.NewHeaderFromBytesBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid version")
assertError(t, err)
assertContains(t, err.Error(), "invalid version")
})
it("assembles properly from pong", func() {
@ -107,11 +148,11 @@ func TestLevin(t *testing.T) {
}
header, err := levin.NewHeaderFromBytesBytes(bytes)
assert.NoError(t, err)
assert.Equal(t, header.Command, levin.CommandPing)
assert.Equal(t, header.ReturnCode, levin.LevinOk)
assert.Equal(t, header.Flags, levin.LevinPacketReponse)
assert.Equal(t, header.Version, levin.LevinProtocolVersion)
assertNoError(t, err)
assertEqual(t, header.Command, levin.CommandPing)
assertEqual(t, header.ReturnCode, levin.LevinOk)
assertEqual(t, header.Flags, levin.LevinPacketReponse)
assertEqual(t, header.Version, levin.LevinProtocolVersion)
})
})
@ -119,7 +160,7 @@ func TestLevin(t *testing.T) {
it("assembles properly w/ ping", func() {
bytes := levin.NewRequestHeader(levin.CommandPing, 1).Bytes()
assert.ElementsMatch(t, bytes, []byte{
assertEqual(t, bytes, []byte{
0x01, 0x21, 0x01, 0x01, // signature
0x01, 0x01, 0x01, 0x01,
0x01, 0x00, 0x00, 0x00, // length -- 0 for a ping msg
@ -135,7 +176,7 @@ func TestLevin(t *testing.T) {
it("assembles properly w/ handshake", func() {
bytes := levin.NewRequestHeader(levin.CommandHandshake, 4).Bytes()
assert.ElementsMatch(t, bytes, []byte{
assertEqual(t, bytes, []byte{
0x01, 0x21, 0x01, 0x01, // signature
0x01, 0x01, 0x01, 0x01,
0x04, 0x00, 0x00, 0x00, // length -- 0 for a ping msg

View file

@ -3,11 +3,9 @@ package levin_test
import (
"testing"
"git.gammaspectra.live/P2Pool/consensus/v3/monero/client/levin"
"github.com/sclevine/spec"
"github.com/sclevine/spec/report"
"github.com/stretchr/testify/assert"
"git.gammaspectra.live/P2Pool/consensus/v3/monero/client/levin"
)
func TestPortableStorage(t *testing.T) {
@ -18,8 +16,8 @@ func TestPortableStorage(t *testing.T) {
}
_, err := levin.NewPortableStorageFromBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "sig-a doesn't match")
assertError(t, err)
assertContains(t, err.Error(), "sig-a doesn't match")
})
it("fails w/ wrong sigB", func() {
@ -29,8 +27,8 @@ func TestPortableStorage(t *testing.T) {
}
_, err := levin.NewPortableStorageFromBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "sig-b doesn't match")
assertError(t, err)
assertContains(t, err.Error(), "sig-b doesn't match")
})
it("fails w/ wrong format ver", func() {
@ -41,8 +39,8 @@ func TestPortableStorage(t *testing.T) {
}
_, err := levin.NewPortableStorageFromBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "version doesn't match")
assertError(t, err)
assertContains(t, err.Error(), "version doesn't match")
})
it("reads the contents", func() {
@ -80,19 +78,19 @@ func TestPortableStorage(t *testing.T) {
}
ps, err := levin.NewPortableStorageFromBytes(bytes)
assert.NoError(t, err)
assertNoError(t, err)
assert.Len(t, ps.Entries, 2)
assert.Equal(t, ps.Entries[0].Name, "node_data")
assert.EqualValues(t, ps.Entries[0].Value, levin.Entries{
assertEqual(t, len(ps.Entries), 2, "len")
assertEqual(t, ps.Entries[0].Name, "node_data")
assertEqual(t, ps.Entries[0].Value, levin.Entries{
{
Name: "foo",
Value: "bar",
},
})
assert.Equal(t, ps.Entries[1].Name, "payload_data")
assert.EqualValues(t, ps.Entries[1].Value, levin.Entries{
assertEqual(t, ps.Entries[1].Name, "payload_data")
assertEqual(t, ps.Entries[1].Value, levin.Entries{
{
Name: "number",
Value: uint32(1),
@ -106,22 +104,22 @@ func TestPortableStorage(t *testing.T) {
b := []byte{0x08}
n, v := levin.ReadVarInt(b)
assert.Equal(t, n, 1)
assert.Equal(t, v, 2)
assertEqual(t, n, 1)
assertEqual(t, v, 2)
})
it("64 <= i <= 16383", func() {
b := []byte{0x01, 0x02}
n, v := levin.ReadVarInt(b)
assert.Equal(t, n, 2)
assert.Equal(t, v, 128)
assertEqual(t, n, 2)
assertEqual(t, v, 128)
})
it("16384 <= i <= 1073741823", func() {
b := []byte{0x02, 0x00, 0x01, 0x00}
n, v := levin.ReadVarInt(b)
assert.Equal(t, n, 4)
assert.Equal(t, v, 16384)
assertEqual(t, n, 4)
assertEqual(t, v, 16384)
})
}, spec.Report(report.Log{}), spec.Parallel(), spec.Random())
@ -130,8 +128,8 @@ func TestPortableStorage(t *testing.T) {
i := 2 // 0b00000010
b, err := levin.VarIn(i)
assert.NoError(t, err)
assert.Equal(t, b, []byte{
assertNoError(t, err)
assertEqual(t, b, []byte{
0x08, // 0b00001000 (shift left twice, union 0)
})
})
@ -140,8 +138,8 @@ func TestPortableStorage(t *testing.T) {
i := 128 // 0b010000000
b, err := levin.VarIn(i)
assert.NoError(t, err)
assert.Equal(t, b, []byte{
assertNoError(t, err)
assertEqual(t, b, []byte{
0x01, 0x02, // 0b1000000001 ((128 * 2 * 2) | 1) == 513
// ' '
// 1 2 * 256
@ -152,8 +150,8 @@ func TestPortableStorage(t *testing.T) {
i := 16384 // 1 << 14
b, err := levin.VarIn(i)
assert.NoError(t, err)
assert.Equal(t, b, []byte{
assertNoError(t, err)
assertEqual(t, b, []byte{
0x02, 0x00, 0x01, 0x00, // (1 << 16) | 2
})
})
@ -188,7 +186,7 @@ func TestPortableStorage(t *testing.T) {
},
}
assert.Equal(t, []byte{
assertEqual(t, []byte{
0x01, 0x11, 0x01, 0x01, // sig a
0x01, 0x01, 0x02, 0x01, // sig b
0x01, // format ver

View file

@ -6,16 +6,45 @@ import (
"git.gammaspectra.live/P2Pool/consensus/v3/utils"
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"git.gammaspectra.live/P2Pool/consensus/v3/monero/client/rpc"
"github.com/sclevine/spec"
"github.com/sclevine/spec/report"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"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)
}
}
// nolint:funlen
func TestClient(t *testing.T) {
spec.Run(t, "JSONRPC", func(t *testing.T, when spec.G, it spec.S) {
@ -30,11 +59,13 @@ func TestClient(t *testing.T) {
daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
require.NoError(t, err)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = client.JSONRPC(ctx, "method", nil, nil)
assert.Error(t, err)
assert.Contains(t, err.Error(), "do:")
assertError(t, err)
assertContains(t, err.Error(), "do:")
})
it("errors w/ empty response", func() {
@ -44,11 +75,13 @@ func TestClient(t *testing.T) {
defer daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
require.NoError(t, err)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = client.JSONRPC(ctx, "method", nil, nil)
assert.Error(t, err)
assert.Contains(t, err.Error(), "decode")
assertError(t, err)
assertContains(t, err.Error(), "decode")
})
it("errors w/ non-200 response", func() {
@ -60,11 +93,13 @@ func TestClient(t *testing.T) {
defer daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
require.NoError(t, err)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = client.JSONRPC(ctx, "method", nil, nil)
assert.Error(t, err)
assert.Contains(t, err.Error(), "non-2xx status")
assertError(t, err)
assertContains(t, err.Error(), "non-2xx status")
})
it("makes GET request to the jsonrpc endpoint", func() {
@ -82,11 +117,13 @@ func TestClient(t *testing.T) {
defer daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
require.NoError(t, err)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = client.JSONRPC(ctx, "method", nil, nil)
assert.Equal(t, rpc.EndpointJSONRPC, endpoint)
assert.Equal(t, method, "GET")
assertEqual(t, rpc.EndpointJSONRPC, endpoint)
assertEqual(t, method, "GET")
})
it("encodes rpc in request", func() {
@ -101,20 +138,24 @@ func TestClient(t *testing.T) {
handler := func(w http.ResponseWriter, r *http.Request) {
err := utils.NewJSONDecoder(r.Body).Decode(body)
assert.NoError(t, err)
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()))
require.NoError(t, err)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
err = client.JSONRPC(ctx, "rpc-method", params, nil)
assert.Equal(t, body.ID, "0")
assert.Equal(t, body.JSONRPC, "2.0")
assert.Equal(t, body.Method, "rpc-method")
assert.Equal(t, body.Params, params)
assertEqual(t, body.ID, "0")
assertEqual(t, body.JSONRPC, "2.0")
assertEqual(t, body.Method, "rpc-method")
assertEqual(t, body.Params, params)
})
it("captures result", func() {
@ -126,14 +167,18 @@ func TestClient(t *testing.T) {
defer daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
require.NoError(t, err)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
result := map[string]string{}
err = client.JSONRPC(ctx, "rpc-method", nil, &result)
assert.NoError(t, err)
err = client.JSONRPC(ctx, "rpc-method/home/shoghicp/radio/p2pool-observer", nil, &result)
if err != nil {
t.Errorf("unexpected err: %v", err)
}
assert.Equal(t, result, map[string]string{"foo": "bar"})
assertEqual(t, result, map[string]string{"foo": "bar"})
})
it("fails if rpc errored", func() {
@ -145,15 +190,17 @@ func TestClient(t *testing.T) {
defer daemon.Close()
client, err = rpc.NewClient(daemon.URL, rpc.WithHTTPClient(daemon.Client()))
require.NoError(t, err)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
result := map[string]string{}
err = client.JSONRPC(ctx, "rpc-method", nil, &result)
assert.Error(t, err)
assertError(t, err)
assert.Contains(t, err.Error(), "foo")
assert.Contains(t, err.Error(), "-1")
assertContains(t, err.Error(), "foo")
assertContains(t, err.Error(), "-1")
})
}, spec.Report(report.Terminal{}), spec.Parallel(), spec.Random())
}