status-go/t/e2e/rpc/rpc_test.go
Dmitry Shulyak 2d964bfe9f Remove async operations from node manager (#584)
The main goal of this change is to remove async operations from node manager.
Additionally all of the signals from node manager are moved to status backend.

All of the async operation now will have the following behaviour:
- If node in the correct state exit immediatly without error
- If node not in the correct state exit immediatly with error
- In all other cases spawn a goroutine with wanted operation
- All the progress regarding that operation will be reported
  by using signals
- Signals should be handled in once place, which is StatusBackend

There are 2 potentially breaking changes:
- Empty event field will be ommited when Envelope is sent to a client
- All errors will be delivered to a client as an Envelope, previously
  some errors (NodeExists, NoRunningNode) were delivered synchronously

Signed-off-by: Dmitry Shulyak <yashulyak@gmail.com>
2018-02-09 14:37:56 +01:00

180 lines
4.9 KiB
Go

package rpc
import (
"context"
"fmt"
"sync"
"testing"
"time"
"math/big"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/geth/node"
"github.com/status-im/status-go/geth/params"
e2e "github.com/status-im/status-go/t/e2e"
. "github.com/status-im/status-go/t/utils"
"github.com/stretchr/testify/suite"
)
func TestRPCTestSuite(t *testing.T) {
suite.Run(t, new(RPCTestSuite))
}
type RPCTestSuite struct {
e2e.NodeManagerTestSuite
}
func (s *RPCTestSuite) SetupTest() {
s.NodeManager = node.NewNodeManager()
s.NotNil(s.NodeManager)
}
func (s *RPCTestSuite) TestCallRPC() {
if GetNetworkID() == params.StatusChainNetworkID {
s.T().Skip()
}
for _, upstreamEnabled := range []bool{false, true} {
nodeConfig, err := e2e.MakeTestNodeConfig(GetNetworkID())
s.NoError(err)
nodeConfig.IPCEnabled = false
nodeConfig.WSEnabled = false
nodeConfig.HTTPHost = "" // to make sure that no HTTP interface is started
if upstreamEnabled {
networkURL, err := GetRemoteURL()
s.NoError(err)
nodeConfig.UpstreamConfig.Enabled = true
nodeConfig.UpstreamConfig.URL = networkURL
}
s.NoError(s.NodeManager.StartNode(nodeConfig))
rpcClient := s.NodeManager.RPCClient()
s.NotNil(rpcClient)
type rpcCall struct {
inputJSON string
validator func(resultJSON string)
}
var rpcCalls = []rpcCall{
{
`{"jsonrpc":"2.0","method":"shh_version","params":[],"id":67}`,
func(resultJSON string) {
expected := `{"jsonrpc":"2.0","id":67,"result":"5.0"}`
s.Equal(expected, resultJSON)
},
},
{
`{"jsonrpc":"2.0","method":"web3_sha3","params":["0x68656c6c6f20776f726c64"],"id":64}`,
func(resultJSON string) {
expected := `{"jsonrpc":"2.0","id":64,"result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"}`
s.Equal(expected, resultJSON)
},
},
{
`{"jsonrpc":"2.0","method":"net_version","params":[],"id":67}`,
func(resultJSON string) {
expected := `{"jsonrpc":"2.0","id":67,"result":"` + fmt.Sprintf("%d", GetNetworkID()) + `"}`
s.Equal(expected, resultJSON)
},
},
{
`[{"jsonrpc":"2.0","method":"net_listening","params":[],"id":67}]`,
func(resultJSON string) {
expected := `[{"jsonrpc":"2.0","id":67,"result":true}]`
s.Equal(expected, resultJSON)
},
},
{
`[{"jsonrpc":"2.0","method":"net_version","params":[],"id":67},{"jsonrpc":"2.0","method":"web3_sha3","params":["0x68656c6c6f20776f726c64"],"id":68}]`,
func(resultJSON string) {
expected := `[{"jsonrpc":"2.0","id":67,"result":"` + fmt.Sprintf("%d", GetNetworkID()) + `"},{"jsonrpc":"2.0","id":68,"result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"}]`
s.Equal(expected, resultJSON)
},
},
}
var wg sync.WaitGroup
for _, r := range rpcCalls {
wg.Add(1)
go func(r rpcCall) {
defer wg.Done()
resultJSON := rpcClient.CallRaw(r.inputJSON)
r.validator(resultJSON)
}(r)
}
done := make(chan struct{})
go func() {
wg.Wait()
close(done)
}()
select {
case <-time.After(time.Second * 30):
s.Fail("test timed out")
case <-done:
}
s.NoError(s.NodeManager.StopNode())
}
}
// TestCallRawResult checks if returned response is a valid JSON-RPC response.
func (s *RPCTestSuite) TestCallRawResult() {
nodeConfig, err := e2e.MakeTestNodeConfig(GetNetworkID())
s.NoError(err)
s.NoError(s.NodeManager.StartNode(nodeConfig))
client := s.NodeManager.RPCClient()
s.NotNil(client)
jsonResult := client.CallRaw(`{"jsonrpc":"2.0","method":"shh_version","params":[],"id":67}`)
s.Equal(`{"jsonrpc":"2.0","id":67,"result":"5.0"}`, jsonResult)
s.NoError(s.NodeManager.StopNode())
}
// TestCallRawResultGetTransactionReceipt checks if returned response
// for a not yet mained transaction is null.
// Issue: https://github.com/status-im/status-go/issues/547
func (s *RPCTestSuite) TestCallRawResultGetTransactionReceipt() {
nodeConfig, err := e2e.MakeTestNodeConfig(GetNetworkID())
s.NoError(err)
s.NoError(s.NodeManager.StartNode(nodeConfig))
client := s.NodeManager.RPCClient()
s.NotNil(client)
jsonResult := client.CallRaw(`{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x0ca0d8f2422f62bea77e24ed17db5711a77fa72064cccbb8e53c53b699cd3b34"],"id":5}`)
s.Equal(`{"jsonrpc":"2.0","id":5,"result":null}`, jsonResult)
s.NoError(s.NodeManager.StopNode())
}
// TestCallContextResult checks if result passed to CallContext
// is set accordingly to its underlying memory layout.
func (s *RPCTestSuite) TestCallContextResult() {
s.StartTestNode()
defer s.StopTestNode()
EnsureNodeSync(s.NodeManager)
client := s.NodeManager.RPCClient()
s.NotNil(client)
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
defer cancel()
var balance hexutil.Big
err := client.CallContext(ctx, &balance, "eth_getBalance", TestConfig.Account1.Address, "latest")
s.NoError(err)
s.True(balance.ToInt().Cmp(big.NewInt(0)) > 0, "balance should be higher than 0")
}