diff --git a/Makefile b/Makefile index 5ee3e5e78..0568745cd 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ statusgo-ios-simulator-mainnet: xgo @echo "iOS framework cross compilation done (mainnet)." ci: mock - build/env.sh go test -timeout 40m -v ./geth/api + build/env.sh go test -timeout 10m -v ./geth/api/... build/env.sh go test -timeout 40m -v ./geth/common build/env.sh go test -timeout 40m -v ./geth/jail build/env.sh go test -timeout 40m -v ./geth/node diff --git a/geth/api/backend_jail_test.go b/geth/api/backend_jail_test.go index baef71c29..1d35eb49e 100644 --- a/geth/api/backend_jail_test.go +++ b/geth/api/backend_jail_test.go @@ -51,7 +51,6 @@ func (s *BackendTestSuite) TestJailSendQueuedTransaction() { "value": "0.000001" }` - txCompletedSuccessfully := make(chan struct{}) txHashes := make(chan gethcommon.Hash, 1) // replace transaction notification handler @@ -77,7 +76,6 @@ func (s *BackendTestSuite) TestJailSendQueuedTransaction() { log.Info("Transaction complete", "URL", "https://ropsten.etherscan.io/tx/%s"+txHash.Hex()) - txCompletedSuccessfully <- struct{}{} // so that timeout is aborted txHashes <- txHash } }) @@ -172,18 +170,24 @@ func (s *BackendTestSuite) TestJailSendQueuedTransaction() { jailInstance := s.backend.JailManager() for _, test := range tests { jailInstance.BaseJS(string(static.MustAsset(txSendFolder + test.file))) - common.PanicAfter(1*time.Minute, txCompletedSuccessfully, test.name) jailInstance.Parse(testChatID, ``) + // used by notification handler requireMessageId = test.requireMessageId for _, command := range test.commands { s.T().Logf("%s: %s", test.name, command.command) response := jailInstance.Call(testChatID, command.command, command.params) + var txHash gethcommon.Hash if command.command == `["commands", "send"]` { - txHash = <-txHashes + select { + case txHash = <-txHashes: + case <-time.After(time.Minute): + s.FailNow("test timed out: %s", test.name) + } } + expectedResponse := strings.Replace(command.expectedResponse, "TX_HASH", txHash.Hex(), 1) require.Equal(expectedResponse, response) } @@ -206,9 +210,7 @@ func (s *BackendTestSuite) TestContractDeployment() { cell, err := jailInstance.Cell(testChatID) require.NoError(err) - // make sure you panic if transaction complete doesn't return - completeQueuedTransaction := make(chan struct{}, 1) - common.PanicAfter(1*time.Minute, completeQueuedTransaction, s.T().Name()) + completeQueuedTransaction := make(chan struct{}) // replace transaction notification handler var txHash gethcommon.Hash @@ -256,7 +258,11 @@ func (s *BackendTestSuite) TestContractDeployment() { `) require.NoError(err) - <-completeQueuedTransaction + select { + case <-completeQueuedTransaction: + case <-time.After(time.Minute): + s.FailNow("test timed out") + } responseValue, err := cell.Get("responseValue") require.NoError(err) @@ -493,7 +499,7 @@ func (s *BackendTestSuite) TestJailWhisper() { privateKeyID: identity, topics: [topic], }); - + // post message var message = { ttl: 20, @@ -536,7 +542,7 @@ func (s *BackendTestSuite) TestJailWhisper() { sig: identity2, topics: [topic], }); - + // post message var message = { sig: identity2, @@ -749,8 +755,17 @@ func (s *BackendTestSuite) TestJailVMPersistence() { }(tc) } - common.PanicAfter(60*time.Second, nil, "test timed out") - wg.Wait() + finishTestCases := make(chan struct{}) + go func() { + wg.Wait() + close(finishTestCases) + }() + + select { + case <-finishTestCases: + case <-time.After(time.Minute): + s.FailNow("some tests failed to finish in time") + } // Validate total. cell, err := jailInstance.Cell(testChatID) diff --git a/geth/api/backend_test.go b/geth/api/backend_test.go index 44659e316..836d30d30 100644 --- a/geth/api/backend_test.go +++ b/geth/api/backend_test.go @@ -157,11 +157,10 @@ func (s *BackendTestSuite) TestNodeStartStop() { require.True(s.backend.IsNodeRunning()) } -func (s *BackendTestSuite) TestStartNodeWithUpstreamEnabled(t *testing.T) { +func (s *BackendTestSuite) TestStartNodeWithUpstreamEnabled() { require := s.Require() backend := api.NewStatusBackend() - require.NotNil(t, backend) nodeConfig, err := MakeTestNodeConfig(params.RopstenNetworkID) require.NoError(err) diff --git a/geth/api/backend_txqueue_test.go b/geth/api/backend_txqueue_test.go index b373a8834..7790c1375 100644 --- a/geth/api/backend_txqueue_test.go +++ b/geth/api/backend_txqueue_test.go @@ -27,13 +27,10 @@ func (s *BackendTestSuite) TestSendContractTx() { time.Sleep(TestConfig.Node.SyncSeconds * time.Second) // allow to sync - // create an account sampleAddress, _, _, err := s.backend.AccountManager().CreateAccount(TestConfig.Account1.Password) require.NoError(err) - // make sure you panic if transaction complete doesn't return - completeQueuedTransaction := make(chan struct{}, 10) - common.PanicAfter(2*time.Minute, completeQueuedTransaction, s.T().Name()) + completeQueuedTransaction := make(chan struct{}) // replace transaction notification handler var txHash gethcommon.Hash @@ -81,7 +78,7 @@ func (s *BackendTestSuite) TestSendContractTx() { ) s.NoError(err, fmt.Sprintf("cannot complete queued transaction[%v]", event["id"])) - log.Info("contract transaction complete", "URL", "https://rinkeby.etherscan.io/tx/"+txHash.Hex()) + log.Info("contract transaction complete", "URL", "https://ropsten.etherscan.io/tx/"+txHash.Hex()) close(completeQueuedTransaction) return } @@ -100,7 +97,12 @@ func (s *BackendTestSuite) TestSendContractTx() { }) s.NoError(err, "cannot send transaction") - <-completeQueuedTransaction + select { + case <-completeQueuedTransaction: + case <-time.After(2 * time.Minute): + s.FailNow("completing transaction timed out") + } + s.Equal(txHashCheck.Hex(), txHash.Hex(), "transaction hash returned from SendTransaction is invalid") s.False(reflect.DeepEqual(txHashCheck, gethcommon.Hash{}), "transaction was never queued or completed") s.Zero(s.TxQueueManager().TransactionQueue().Count(), "tx queue must be empty at this point") @@ -122,9 +124,7 @@ func (s *BackendTestSuite) TestSendEtherTx() { sampleAddress, _, _, err := s.backend.AccountManager().CreateAccount(TestConfig.Account1.Password) require.NoError(err) - // make sure you panic if transaction complete doesn't return - completeQueuedTransaction := make(chan struct{}, 1) - common.PanicAfter(1*time.Minute, completeQueuedTransaction, s.T().Name()) + completeQueuedTransaction := make(chan struct{}) // replace transaction notification handler var txHash = gethcommon.Hash{} @@ -170,7 +170,7 @@ func (s *BackendTestSuite) TestSendEtherTx() { ) s.NoError(err, fmt.Sprintf("cannot complete queued transaction[%v]", event["id"])) - log.Info("contract transaction complete", "URL", "https://rinkeby.etherscan.io/tx/"+txHash.Hex()) + log.Info("contract transaction complete", "URL", "https://ropsten.etherscan.io/tx/"+txHash.Hex()) close(completeQueuedTransaction) return } @@ -184,7 +184,12 @@ func (s *BackendTestSuite) TestSendEtherTx() { }) s.NoError(err, "cannot send transaction") - <-completeQueuedTransaction + select { + case <-completeQueuedTransaction: + case <-time.After(2 * time.Minute): + s.FailNow("completing transaction timed out") + } + s.Equal(txHashCheck.Hex(), txHash.Hex(), "transaction hash returned from SendTransaction is invalid") s.False(reflect.DeepEqual(txHashCheck, gethcommon.Hash{}), "transaction was never queued or completed") s.Zero(s.backend.TxQueueManager().TransactionQueue().Count(), "tx queue must be empty at this point") @@ -205,9 +210,7 @@ func (s *BackendTestSuite) TestDoubleCompleteQueuedTransactions() { // log into account from which transactions will be sent require.NoError(s.backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) - // make sure you panic if transaction complete doesn't return - completeQueuedTransaction := make(chan struct{}, 1) - common.PanicAfter(1*time.Minute, completeQueuedTransaction, s.T().Name()) + completeQueuedTransaction := make(chan struct{}) // replace transaction notification handler txFailedEventCalled := false @@ -260,7 +263,12 @@ func (s *BackendTestSuite) TestDoubleCompleteQueuedTransactions() { }) s.NoError(err, "cannot send transaction") - <-completeQueuedTransaction + select { + case <-completeQueuedTransaction: + case <-time.After(time.Minute): + s.FailNow("test timed out") + } + s.Equal(txHashCheck.Hex(), txHash.Hex(), "transaction hash returned from SendTransaction is invalid") s.False(reflect.DeepEqual(txHashCheck, gethcommon.Hash{}), "transaction was never queued or completed") s.Zero(s.backend.TxQueueManager().TransactionQueue().Count(), "tx queue must be empty at this point") @@ -285,9 +293,7 @@ func (s *BackendTestSuite) TestDiscardQueuedTransaction() { // log into account from which transactions will be sent require.NoError(s.backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) - // make sure you panic if transaction complete doesn't return - completeQueuedTransaction := make(chan struct{}, 1) - common.PanicAfter(1*time.Minute, completeQueuedTransaction, s.T().Name()) + completeQueuedTransaction := make(chan struct{}) // replace transaction notification handler txFailedEventCalled := false @@ -341,7 +347,12 @@ func (s *BackendTestSuite) TestDiscardQueuedTransaction() { }) s.EqualError(err, node.ErrQueuedTxDiscarded.Error(), "transaction is expected to be discarded") - <-completeQueuedTransaction + select { + case <-completeQueuedTransaction: + case <-time.After(time.Minute): + s.FailNow("test timed out") + } + s.True(reflect.DeepEqual(txHashCheck, gethcommon.Hash{}), "transaction returned hash, while it shouldn't") s.Zero(s.backend.TxQueueManager().TransactionQueue().Count(), "tx queue must be empty at this point") s.True(txFailedEventCalled, "expected tx failure signal is not received") @@ -363,10 +374,9 @@ func (s *BackendTestSuite) TestCompleteMultipleQueuedTransactions() { err := s.backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password) require.NoError(err) - // make sure you panic if transaction complete doesn't return testTxCount := 3 txIDs := make(chan common.QueuedTxID, testTxCount) - allTestTxCompleted := make(chan struct{}, 1) + allTestTxCompleted := make(chan struct{}) // replace transaction notification handler node.SetDefaultNodeNotificationHandler(func(jsonEvent string) { @@ -410,7 +420,7 @@ func (s *BackendTestSuite) TestCompleteMultipleQueuedTransactions() { txResult.Hash == (gethcommon.Hash{}) && txID != "invalid-tx-id", "invalid hash (expected non empty hash): %s", txID, ) - log.Info("transaction complete", "URL", "https://rinkeby.etherscan.io/tx/"+txResult.Hash.Hex()) + log.Info("transaction complete", "URL", "https://ropsten.etherscan.io/tx/"+txResult.Hash.Hex()) } time.Sleep(1 * time.Second) // make sure that tx complete signal propagates @@ -429,7 +439,7 @@ func (s *BackendTestSuite) TestCompleteMultipleQueuedTransactions() { } completeTxs(ids) - allTestTxCompleted <- struct{}{} + close(allTestTxCompleted) }() // send multiple transactions @@ -439,9 +449,8 @@ func (s *BackendTestSuite) TestCompleteMultipleQueuedTransactions() { select { case <-allTestTxCompleted: - // pass case <-time.After(30 * time.Second): - require.Fail("test timed out") + s.FailNow("test timed out") } require.Zero(s.TxQueueManager().TransactionQueue().Count(), "queue should be empty") @@ -465,10 +474,9 @@ func (s *BackendTestSuite) TestDiscardMultipleQueuedTransactions() { // log into account from which transactions will be sent require.NoError(s.backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) - // make sure you panic if transaction complete doesn't return testTxCount := 3 txIDs := make(chan common.QueuedTxID, testTxCount) - allTestTxDiscarded := make(chan struct{}, 1) + allTestTxDiscarded := make(chan struct{}) // replace transaction notification handler txFailedEventCallCount := 0 @@ -499,7 +507,7 @@ func (s *BackendTestSuite) TestDiscardMultipleQueuedTransactions() { txFailedEventCallCount++ if txFailedEventCallCount == testTxCount { - allTestTxDiscarded <- struct{}{} + close(allTestTxDiscarded) } } }) @@ -560,9 +568,8 @@ func (s *BackendTestSuite) TestDiscardMultipleQueuedTransactions() { select { case <-allTestTxDiscarded: - // pass case <-time.After(1 * time.Minute): - require.Fail("test timed out") + require.FailNow("test timed out") } require.Zero(s.backend.TxQueueManager().TransactionQueue().Count(), "tx queue must be empty at this point") diff --git a/geth/jail/execution_policy.go b/geth/jail/execution_policy.go index 893e61980..effa3c22e 100644 --- a/geth/jail/execution_policy.go +++ b/geth/jail/execution_policy.go @@ -99,15 +99,19 @@ func (ep *ExecutionPolicy) executeWithClient(client *rpc.Client, req common.RPCC return nil, common.StopRPCCallError{Err: err} } - err = client.Call(&result, req.Method, req.Params...) - if err != nil { - if err2, ok := err.(gethrpc.Error); ok { - resp.Set("error", map[string]interface{}{ - "code": err2.ErrorCode(), - "message": err2.Error(), - }) - } else { - resp = newErrorResponse(call.Otto, -32603, err.Error(), &req.ID).Object() + if client == nil { + resp = newErrorResponse(call.Otto, -32603, "RPC client is not available. Node is stopped?", &req.ID).Object() + } else { + err = client.Call(&result, req.Method, req.Params...) + if err != nil { + if err2, ok := err.(gethrpc.Error); ok { + resp.Set("error", map[string]interface{}{ + "code": err2.ErrorCode(), + "message": err2.Error(), + }) + } else { + resp = newErrorResponse(call.Otto, -32603, err.Error(), &req.ID).Object() + } } } diff --git a/geth/jail/jail.go b/geth/jail/jail.go index 010b715a5..b00be529f 100644 --- a/geth/jail/jail.go +++ b/geth/jail/jail.go @@ -176,9 +176,10 @@ func (jail *Jail) Send(call otto.FunctionCall) (response otto.Value) { // Execute the requests. for _, req := range reqs { + log.Info("execute request", "method", req.Method) res, err := jail.policy.Execute(req, call) - if err != nil { + log.Info("request errored", "error", err.Error()) switch err.(type) { case common.StopRPCCallError: return newErrorResponse(call.Otto, -32603, err.Error(), nil)