26c341d04d
* WIP! add Ethereum JSONRPC Websocket test * move to test-rpc * clean up * fix batch request with websocket * refactor
175 lines
4.5 KiB
Go
175 lines
4.5 KiB
Go
package rpc
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/gorilla/websocket"
|
|
"github.com/stretchr/testify/require"
|
|
"net/url"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
HOST_WS = os.Getenv("HOST_WS")
|
|
wsUrl string
|
|
)
|
|
|
|
func init() {
|
|
if HOST_WS == "" {
|
|
HOST_WS = "localhost:8542"
|
|
}
|
|
|
|
u := url.URL{Scheme: "ws", Host: HOST_WS, Path: ""}
|
|
wsUrl = u.String()
|
|
}
|
|
|
|
func TestWsSingleRequest(t *testing.T) {
|
|
t.Log("test simple rpc request net_version with Websocket")
|
|
|
|
wc, _, err := websocket.DefaultDialer.Dial(wsUrl, nil)
|
|
require.NoError(t, err)
|
|
defer wc.Close()
|
|
|
|
wsWriteMessage(t, wc, `{"jsonrpc":"2.0","method":"net_version","params":[],"id":1}`)
|
|
|
|
time.Sleep(1 * time.Second)
|
|
mb := readMessage(t, wc)
|
|
msg := jsonUnmarshal(t, mb)
|
|
result, ok := msg["result"].(string)
|
|
require.True(t, ok)
|
|
require.Equal(t, "9000", result)
|
|
}
|
|
|
|
func TestWsBatchRequest(t *testing.T) {
|
|
t.Log("test batch request with Websocket")
|
|
|
|
wc, _, err := websocket.DefaultDialer.Dial(wsUrl, nil)
|
|
require.NoError(t, err)
|
|
defer wc.Close()
|
|
|
|
wsWriteMessage(t, wc, `[{"jsonrpc":"2.0","method":"net_version","params":[],"id":1},{"jsonrpc":"2.0","method":"eth_protocolVersion","params":[],"id":2}]`)
|
|
|
|
time.Sleep(1 * time.Second)
|
|
mb := readMessage(t, wc)
|
|
|
|
var msg []map[string]interface{}
|
|
err = json.Unmarshal(mb, &msg)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 2, len(msg))
|
|
|
|
// net_version
|
|
resNetVersion := msg[0]
|
|
result, ok := resNetVersion["result"].(string)
|
|
require.True(t, ok)
|
|
require.Equal(t, "9000", result)
|
|
id, ok := resNetVersion["id"].(float64)
|
|
require.True(t, ok)
|
|
require.Equal(t, 1, int(id))
|
|
|
|
// eth_protocolVersion
|
|
resEthProtocolVersion := msg[1]
|
|
result, ok = resEthProtocolVersion["result"].(string)
|
|
require.True(t, ok)
|
|
require.Equal(t, "0x41", result)
|
|
id, ok = resEthProtocolVersion["id"].(float64)
|
|
require.True(t, ok)
|
|
require.Equal(t, 2, int(id))
|
|
}
|
|
|
|
func TestWsEth_subscribe_newHeads(t *testing.T) {
|
|
t.Log("test eth_subscribe newHeads with Websocket")
|
|
|
|
wc, _, err := websocket.DefaultDialer.Dial(wsUrl, nil)
|
|
require.NoError(t, err)
|
|
defer wc.Close()
|
|
|
|
wsWriteMessage(t, wc, `{"id":1,"method":"eth_subscribe","params":["newHeads",{}]}`)
|
|
|
|
time.Sleep(1 * time.Second)
|
|
mb := readMessage(t, wc)
|
|
msg := jsonUnmarshal(t, mb)
|
|
subscribeId, ok := msg["result"].(string)
|
|
require.True(t, ok)
|
|
require.True(t, strings.HasPrefix(subscribeId, "0x"))
|
|
|
|
time.Sleep(3 * time.Second)
|
|
mb = readMessage(t, wc)
|
|
msg = jsonUnmarshal(t, mb)
|
|
method, ok := msg["method"].(string)
|
|
require.Equal(t, "eth_subscription", method)
|
|
|
|
// id should not exist with eth_subscription event
|
|
_, ok = msg["id"].(float64)
|
|
require.False(t, ok)
|
|
|
|
wsUnsubscribe(t, wc, subscribeId) // eth_unsubscribe
|
|
}
|
|
|
|
func TestWsEth_subscribe_log(t *testing.T) {
|
|
t.Log("test eth_subscribe log with websocket")
|
|
|
|
wc, _, err := websocket.DefaultDialer.Dial(wsUrl, nil)
|
|
require.NoError(t, err)
|
|
defer wc.Close()
|
|
|
|
wsWriteMessage(t, wc, fmt.Sprintf(`{"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["logs",{"topics":["%s", "%s"]}]}`, helloTopic, worldTopic))
|
|
|
|
time.Sleep(1 * time.Second)
|
|
mb := readMessage(t, wc)
|
|
msg := jsonUnmarshal(t, mb)
|
|
subscribeId, ok := msg["result"].(string)
|
|
require.True(t, ok)
|
|
require.True(t, strings.HasPrefix(subscribeId, "0x"))
|
|
|
|
// do something here to receive subscription messages
|
|
deployTestContractWithFunction(t)
|
|
|
|
time.Sleep(3 * time.Second)
|
|
mb = readMessage(t, wc)
|
|
msg = jsonUnmarshal(t, mb)
|
|
method, ok := msg["method"].(string)
|
|
require.Equal(t, "eth_subscription", method)
|
|
|
|
// id should not exist with eth_subscription event
|
|
_, ok = msg["id"].(float64)
|
|
require.False(t, ok)
|
|
|
|
wsUnsubscribe(t, wc, subscribeId) // eth_unsubscribe
|
|
}
|
|
|
|
func wsWriteMessage(t *testing.T, wc *websocket.Conn, jsonStr string) {
|
|
t.Logf("send: %s", jsonStr)
|
|
err := wc.WriteMessage(websocket.TextMessage, []byte(jsonStr))
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func wsUnsubscribe(t *testing.T, wc *websocket.Conn, subscribeId string) {
|
|
t.Logf("eth_unsubscribe %s", subscribeId)
|
|
wsWriteMessage(t, wc, fmt.Sprintf(`{"id":1,"method":"eth_unsubscribe","params":["%s"]}`, subscribeId))
|
|
|
|
time.Sleep(1 * time.Second)
|
|
mb := readMessage(t, wc)
|
|
msg := jsonUnmarshal(t, mb)
|
|
|
|
result, ok := msg["result"].(bool)
|
|
require.True(t, ok)
|
|
require.True(t, result)
|
|
}
|
|
|
|
func readMessage(t *testing.T, wc *websocket.Conn) []byte {
|
|
_, mb, err := wc.ReadMessage()
|
|
require.NoError(t, err)
|
|
t.Logf("recv: %s", mb)
|
|
return mb
|
|
}
|
|
|
|
func jsonUnmarshal(t *testing.T, mb []byte) map[string]interface{} {
|
|
var msg map[string]interface{}
|
|
err := json.Unmarshal(mb, &msg)
|
|
require.NoError(t, err)
|
|
return msg
|
|
}
|