package jail import ( "fmt" "net/http" "net/http/httptest" "testing" "time" "github.com/robertkrimen/otto" "sync/atomic" gethrpc "github.com/ethereum/go-ethereum/rpc" "github.com/status-im/status-go/geth/params" "github.com/status-im/status-go/geth/rpc" "github.com/status-im/status-go/geth/signal" "github.com/stretchr/testify/suite" ) func TestHandlersTestSuite(t *testing.T) { suite.Run(t, new(HandlersTestSuite)) } type HandlersTestSuite struct { suite.Suite responseFixture string ts *httptest.Server tsCalls int32 client *gethrpc.Client } func (s *HandlersTestSuite) SetupTest() { s.responseFixture = `{"json-rpc":"2.0","id":10,"result":true}` s.ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { atomic.AddInt32(&s.tsCalls, 1) fmt.Fprintln(w, s.responseFixture) })) client, err := gethrpc.Dial(s.ts.URL) s.NoError(err) s.client = client } func (s *HandlersTestSuite) TearDownTest() { s.ts.Close() s.tsCalls = 0 } func (s *HandlersTestSuite) TestWeb3SendHandlerSuccess() { client, err := rpc.NewClient(s.client, params.UpstreamRPCConfig{}) s.NoError(err) jail := New(&testRPCClientProvider{client}) cell, _, err := jail.createAndInitCell("cell1") s.NoError(err) // web3.eth.syncing is an arbitrary web3 sync RPC call. value, err := cell.Run("web3.eth.syncing") s.NoError(err) result, err := value.ToBoolean() s.NoError(err) s.True(result) } func (s *HandlersTestSuite) TestWeb3SendHandlerFailure() { jail := New(nil) cell, _, err := jail.createAndInitCell("cell1") s.NoError(err) _, err = cell.Run("web3.eth.syncing") s.Error(err, ErrNoRPCClient.Error()) } func (s *HandlersTestSuite) TestWeb3SendAsyncHandlerSuccess() { client, err := rpc.NewClient(s.client, params.UpstreamRPCConfig{}) s.NoError(err) jail := New(&testRPCClientProvider{client}) cell, _, err := jail.createAndInitCell("cell1") s.NoError(err) errc := make(chan string) resultc := make(chan string) err = cell.Set("__getSyncingCallback", func(call otto.FunctionCall) otto.Value { errc <- call.Argument(0).String() resultc <- call.Argument(1).String() return otto.UndefinedValue() }) s.NoError(err) _, err = cell.Run(`web3.eth.getSyncing(__getSyncingCallback)`) s.NoError(err) s.Equal(`null`, <-errc) s.Equal(`true`, <-resultc) } func (s *HandlersTestSuite) TestWeb3SendAsyncHandlerWithoutCallbackSuccess() { client, err := rpc.NewClient(s.client, params.UpstreamRPCConfig{}) s.NoError(err) jail := New(&testRPCClientProvider{client}) cell, _, err := jail.createAndInitCell("cell1") s.NoError(err) _, err = cell.Run(`web3.eth.getSyncing()`) s.NoError(err) // As there is no callback, it's not possible to detect when // the request hit the server. time.Sleep(time.Millisecond * 100) s.Equal(int32(1), atomic.LoadInt32(&s.tsCalls)) } func (s *HandlersTestSuite) TestWeb3SendAsyncHandlerFailure() { jail := New(nil) cell, _, err := jail.createAndInitCell("cell1") s.NoError(err) errc := make(chan otto.Value) resultc := make(chan string) err = cell.Set("__getSyncingCallback", func(call otto.FunctionCall) otto.Value { errc <- call.Argument(0) resultc <- call.Argument(1).String() return otto.UndefinedValue() }) s.NoError(err) _, err = cell.Run(`web3.eth.getSyncing(__getSyncingCallback)`) s.NoError(err) errValue := <-errc message, err := errValue.Object().Get("message") s.NoError(err) s.Equal(ErrNoRPCClient.Error(), message.String()) s.Equal(`undefined`, <-resultc) } func (s *HandlersTestSuite) TestWeb3IsConnectedHandler() { client, err := rpc.NewClient(s.client, params.UpstreamRPCConfig{}) s.NoError(err) jail := New(&testRPCClientProvider{client}) cell, _, err := jail.createAndInitCell("cell1") s.NoError(err) // When result is true. value, err := cell.Run("web3.isConnected()") s.NoError(err) valueBoolean, err := value.ToBoolean() s.NoError(err) s.True(valueBoolean) // When result is false. s.responseFixture = `{"json-rpc":"2.0","id":10,"result":false}` value, err = cell.Run("web3.isConnected()") s.NoError(err) valueBoolean, err = value.ToBoolean() s.NoError(err) s.False(valueBoolean) } func (s *HandlersTestSuite) TestSendSignalHandler() { jail := New(nil) cell, _, err := jail.createAndInitCell("cell1") s.NoError(err) signal.SetDefaultNodeNotificationHandler(func(jsonEvent string) { s.Contains(jsonEvent, "test signal message") }) value, err := cell.Run(`statusSignals.sendSignal("test signal message")`) s.NoError(err) result, err := cell.GetObjectValue(value, "result") s.NoError(err) resultBool, err := result.ToBoolean() s.NoError(err) s.True(resultBool) }