From 2daff0957a929c56c069ca965bfb7b2966d98f4d Mon Sep 17 00:00:00 2001
From: Roman Khimov <roman@nspcc.ru>
Date: Tue, 24 Sep 2019 18:47:23 +0300
Subject: [PATCH] rpc: check for error responses in tests

sendrawtransaction_negative was actually wrong in trying to get
SendTXResponse, it received an error.
---
 pkg/rpc/server_helper_test.go | 10 ++++++++++
 pkg/rpc/server_test.go        | 33 +++++++++++++++++++++++++++++----
 2 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/pkg/rpc/server_helper_test.go b/pkg/rpc/server_helper_test.go
index 718ff6cf9..2eb7331ac 100644
--- a/pkg/rpc/server_helper_test.go
+++ b/pkg/rpc/server_helper_test.go
@@ -18,6 +18,16 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
+// ErrorResponse struct represents JSON-RPC error.
+type ErrorResponse struct {
+	Jsonrpc string `json:"jsonrpc"`
+	Error   struct {
+		Code    int    `json:"code"`
+		Message string `json:"message"`
+	} `json:"error"`
+	ID int `json:"id"`
+}
+
 // SendTXResponse struct for testing.
 type SendTXResponse struct {
 	Jsonrpc string `json:"jsonrpc"`
diff --git a/pkg/rpc/server_test.go b/pkg/rpc/server_test.go
index 40796bdf9..2db969c7c 100644
--- a/pkg/rpc/server_test.go
+++ b/pkg/rpc/server_test.go
@@ -28,6 +28,7 @@ func TestRPC(t *testing.T) {
 	t.Run("getbestblockhash", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getbestblockhash", "params": []}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res StringResultResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -37,6 +38,7 @@ func TestRPC(t *testing.T) {
 	t.Run("getblock", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getblock", "params": [1]}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res GetBlockResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -49,6 +51,7 @@ func TestRPC(t *testing.T) {
 	t.Run("getblockcount", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getblockcount", "params": []}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res IntResultResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -58,6 +61,7 @@ func TestRPC(t *testing.T) {
 	t.Run("getblockhash", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getblockhash", "params": [1]}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res StringResultResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -70,6 +74,7 @@ func TestRPC(t *testing.T) {
 	t.Run("getconnectioncount", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getconnectioncount", "params": []}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res IntResultResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -79,6 +84,7 @@ func TestRPC(t *testing.T) {
 	t.Run("getversion", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getversion", "params": []}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res GetVersionResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -88,6 +94,7 @@ func TestRPC(t *testing.T) {
 	t.Run("getpeers", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getpeers", "params": []}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res GetPeersResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -99,6 +106,7 @@ func TestRPC(t *testing.T) {
 	t.Run("validateaddress_positive", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "validateaddress", "params": ["AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i"]}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res ValidateAddrResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -108,6 +116,7 @@ func TestRPC(t *testing.T) {
 	t.Run("validateaddress_negative", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "validateaddress", "params": [1]}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res ValidateAddrResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -117,6 +126,7 @@ func TestRPC(t *testing.T) {
 	t.Run("getassetstate_positive", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getassetstate", "params": ["602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"]}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res GetAssetResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -127,6 +137,7 @@ func TestRPC(t *testing.T) {
 	t.Run("getassetstate_negative", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getassetstate", "params": ["602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de2"]}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res StringResultResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -136,6 +147,7 @@ func TestRPC(t *testing.T) {
 	t.Run("getaccountstate_positive", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getaccountstate", "params": ["AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU"]}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res GetAccountStateResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -146,6 +158,7 @@ func TestRPC(t *testing.T) {
 	t.Run("getaccountstate_negative", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getaccountstate", "params": ["AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y"]}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res StringResultResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -157,6 +170,7 @@ func TestRPC(t *testing.T) {
 		TXHash := block.Transactions[1].Hash()
 		rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s"]}"`, TXHash.ReverseString())
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res StringResultResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -166,6 +180,7 @@ func TestRPC(t *testing.T) {
 	t.Run("sendrawtransaction_positive", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "sendrawtransaction", "params": ["d1001b00046e616d6567d3d8602814a429a91afdbaa3914884a1c90c733101201cc9c05cefffe6cdd7b182816a9152ec218d2ec000000141403387ef7940a5764259621e655b3c621a6aafd869a611ad64adcc364d8dd1edf84e00a7f8b11b630a377eaef02791d1c289d711c08b7ad04ff0d6c9caca22cfe6232103cbb45da6072c14761c9da545749d9cfd863f860c351066d16df480602a2024c6ac"]}`
 		body := doRPCCall(rpc, handler, t)
+		checkErrResponse(t, body, false)
 		var res SendTXResponse
 		err := json.Unmarshal(bytes.TrimSpace(body), &res)
 		assert.NoErrorf(t, err, "could not parse response: %s", body)
@@ -175,13 +190,23 @@ func TestRPC(t *testing.T) {
 	t.Run("sendrawtransaction_negative", func(t *testing.T) {
 		rpc := `{"jsonrpc": "2.0", "id": 1, "method": "sendrawtransaction", "params": ["0274d792072617720636f6e7472616374207472616e73616374696f6e206465736372697074696f6e01949354ea0a8b57dfee1e257a1aedd1e0eea2e5837de145e8da9c0f101bfccc8e0100029b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc500a3e11100000000ea610aa6db39bd8c8556c9569d94b5e5a5d0ad199b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc5004f2418010000001cc9c05cefffe6cdd7b182816a9152ec218d2ec0014140dbd3cddac5cb2bd9bf6d93701f1a6f1c9dbe2d1b480c54628bbb2a4d536158c747a6af82698edf9f8af1cac3850bcb772bd9c8e4ac38f80704751cc4e0bd0e67232103cbb45da6072c14761c9da545749d9cfd863f860c351066d16df480602a2024c6ac"]}`
 		body := doRPCCall(rpc, handler, t)
-		var res SendTXResponse
-		err := json.Unmarshal(bytes.TrimSpace(body), &res)
-		assert.NoErrorf(t, err, "could not parse response: %s", body)
-		assert.Equal(t, false, res.Result)
+		checkErrResponse(t, body, true)
 	})
 }
 
+func checkErrResponse(t *testing.T, body []byte, expectingFail bool) {
+	var errresp ErrorResponse
+	err := json.Unmarshal(bytes.TrimSpace(body), &errresp)
+	assert.Nil(t, err)
+	if expectingFail {
+		assert.NotEqual(t, 0, errresp.Error.Code)
+		assert.NotEqual(t, "", errresp.Error.Message)
+	} else {
+		assert.Equal(t, 0, errresp.Error.Code)
+		assert.Equal(t, "", errresp.Error.Message)
+	}
+}
+
 func doRPCCall(rpcCall string, handler http.HandlerFunc, t *testing.T) []byte {
 	req := httptest.NewRequest("POST", "http://0.0.0.0:20333/", strings.NewReader(rpcCall))
 	req.Header.Set("Content-Type", "application/json")