|
|
@ -10,16 +10,14 @@ import ( |
|
|
|
"testing" |
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert" |
|
|
|
"github.com/stretchr/testify/require" |
|
|
|
|
|
|
|
rs "github.com/tendermint/tendermint/rpc/lib/server" |
|
|
|
types "github.com/tendermint/tendermint/rpc/lib/types" |
|
|
|
"github.com/tendermint/tmlibs/log" |
|
|
|
) |
|
|
|
|
|
|
|
// Ensure that nefarious/unintended inputs to `params`
|
|
|
|
// do not crash our RPC handlers.
|
|
|
|
// See Issue https://github.com/tendermint/tendermint/issues/708.
|
|
|
|
func TestRPCParams(t *testing.T) { |
|
|
|
func testMux() *http.ServeMux { |
|
|
|
funcMap := map[string]*rs.RPCFunc{ |
|
|
|
"c": rs.NewRPCFunc(func(s string, i int) (string, error) { return "foo", nil }, "s,i"), |
|
|
|
} |
|
|
@ -28,25 +26,31 @@ func TestRPCParams(t *testing.T) { |
|
|
|
logger := log.NewTMLogger(buf) |
|
|
|
rs.RegisterRPCFuncs(mux, funcMap, logger) |
|
|
|
|
|
|
|
return mux |
|
|
|
} |
|
|
|
|
|
|
|
func statusOK(code int) bool { return code >= 200 && code <= 299 } |
|
|
|
|
|
|
|
// Ensure that nefarious/unintended inputs to `params`
|
|
|
|
// do not crash our RPC handlers.
|
|
|
|
// See Issue https://github.com/tendermint/tendermint/issues/708.
|
|
|
|
func TestRPCParams(t *testing.T) { |
|
|
|
mux := testMux() |
|
|
|
tests := []struct { |
|
|
|
payload string |
|
|
|
wantErr string |
|
|
|
notification bool |
|
|
|
payload string |
|
|
|
wantErr string |
|
|
|
}{ |
|
|
|
{`{"jsonrpc": "2.0"}`, "", true}, // The server SHOULD NOT respond to a notification according to JSONRPC Section 4.1.
|
|
|
|
{`{"jsonrpc": "2.0", "id": "0"}`, "Method not found", false}, |
|
|
|
{`{"jsonrpc": "2.0", "method": "y", "id": "0"}`, "Method not found", false}, |
|
|
|
{`{"jsonrpc": "2.0", "method": "c", "id": "0", "params": null}`, "", false}, |
|
|
|
{`{"method": "c", "id": "0", "params": {}}`, "", false}, |
|
|
|
{`{"method": "c", "id": "0", "params": a}`, "invalid character", false}, |
|
|
|
{`{"method": "c", "id": "0", "params": ["a", 10]}`, "", false}, |
|
|
|
{`{"method": "c", "id": "0", "params": ["a"]}`, "got 1", false}, |
|
|
|
{`{"method": "c", "id": "0", "params": ["a", "b"]}`, "of type int", false}, |
|
|
|
{`{"method": "c", "id": "0", "params": [1, 1]}`, "of type string", false}, |
|
|
|
{`{"jsonrpc": "2.0", "id": "0"}`, "Method not found"}, |
|
|
|
{`{"jsonrpc": "2.0", "method": "y", "id": "0"}`, "Method not found"}, |
|
|
|
{`{"jsonrpc": "2.0", "method": "c", "id": "0", "params": null}`, ""}, |
|
|
|
{`{"method": "c", "id": "0", "params": {}}`, ""}, |
|
|
|
{`{"method": "c", "id": "0", "params": a}`, "invalid character"}, |
|
|
|
{`{"method": "c", "id": "0", "params": ["a", 10]}`, ""}, |
|
|
|
{`{"method": "c", "id": "0", "params": ["a"]}`, "got 1"}, |
|
|
|
{`{"method": "c", "id": "0", "params": ["a", "b"]}`, "of type int"}, |
|
|
|
{`{"method": "c", "id": "0", "params": [1, 1]}`, "of type string"}, |
|
|
|
} |
|
|
|
|
|
|
|
statusOK := func(code int) bool { return code >= 200 && code <= 299 } |
|
|
|
|
|
|
|
for i, tt := range tests { |
|
|
|
req, _ := http.NewRequest("POST", "http://localhost/", strings.NewReader(tt.payload)) |
|
|
|
rec := httptest.NewRecorder() |
|
|
@ -60,11 +64,6 @@ func TestRPCParams(t *testing.T) { |
|
|
|
continue |
|
|
|
} |
|
|
|
|
|
|
|
if tt.notification { |
|
|
|
assert.Equal(t, len(blob), 0, "#%d: a notification SHOULD NOT be responded to by the server", i) |
|
|
|
continue |
|
|
|
} |
|
|
|
|
|
|
|
recv := new(types.RPCResponse) |
|
|
|
assert.Nil(t, json.Unmarshal(blob, recv), "#%d: expecting successful parsing of an RPCResponse:\nblob: %s", i, blob) |
|
|
|
assert.NotEqual(t, recv, new(types.RPCResponse), "#%d: not expecting a blank RPCResponse", i) |
|
|
@ -78,3 +77,18 @@ func TestRPCParams(t *testing.T) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func TestRPCNotification(t *testing.T) { |
|
|
|
mux := testMux() |
|
|
|
body := strings.NewReader(`{"jsonrpc": "2.0"}`) |
|
|
|
req, _ := http.NewRequest("POST", "http://localhost/", body) |
|
|
|
rec := httptest.NewRecorder() |
|
|
|
mux.ServeHTTP(rec, req) |
|
|
|
res := rec.Result() |
|
|
|
|
|
|
|
// Always expecting back a JSONRPCResponse
|
|
|
|
require.True(t, statusOK(res.StatusCode), "should always return 2XX") |
|
|
|
blob, err := ioutil.ReadAll(res.Body) |
|
|
|
require.Nil(t, err, "reading from the body should not give back an error") |
|
|
|
require.Equal(t, len(blob), 0, "a notification SHOULD NOT be responded to by the server") |
|
|
|
} |