185 lines
4.8 KiB
Go
185 lines
4.8 KiB
Go
package destructive
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/log"
|
|
"github.com/ethereum/go-ethereum/whisper/whisperv6"
|
|
"github.com/status-im/status-go/api"
|
|
. "github.com/status-im/status-go/t/utils"
|
|
|
|
"github.com/ethereum/go-ethereum/p2p"
|
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
|
"github.com/stretchr/testify/suite"
|
|
)
|
|
|
|
const (
|
|
defaultTimeout = 40 * time.Second
|
|
)
|
|
|
|
func TestPeersSuiteNetworkConnection(t *testing.T) {
|
|
suite.Run(t, &PeersTestSuite{controller: new(NetworkConnectionController)})
|
|
}
|
|
|
|
type PeersTestSuite struct {
|
|
suite.Suite
|
|
|
|
backend *api.StatusBackend
|
|
controller *NetworkConnectionController
|
|
}
|
|
|
|
func (s *PeersTestSuite) SetupTest() {
|
|
s.backend = api.NewStatusBackend()
|
|
config, err := MakeTestNodeConfig(GetNetworkID())
|
|
s.Require().NoError(err)
|
|
// we need to enable atleast 1 protocol, otherwise peers won't connect
|
|
config.LightEthConfig.Enabled = false
|
|
config.WhisperConfig.Enabled = true
|
|
s.Require().NoError(s.backend.StartNode(config))
|
|
}
|
|
|
|
func (s *PeersTestSuite) TearDownTest() {
|
|
s.Require().NoError(s.backend.StopNode())
|
|
}
|
|
|
|
func consumeUntil(events <-chan *p2p.PeerEvent, f func(ev *p2p.PeerEvent) bool, timeout time.Duration) error {
|
|
timer := time.After(timeout)
|
|
for {
|
|
select {
|
|
case ev := <-events:
|
|
if f(ev) {
|
|
return nil
|
|
}
|
|
case <-timer:
|
|
return errors.New("timeout")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *PeersTestSuite) TestSentEnvelope() {
|
|
node := s.backend.StatusNode()
|
|
w, err := node.WhisperService()
|
|
s.NoError(err)
|
|
|
|
client, _ := node.GethNode().Attach()
|
|
s.NotNil(client)
|
|
var symID string
|
|
s.NoError(client.Call(&symID, "shh_newSymKey"))
|
|
msg := whisperv6.NewMessage{
|
|
SymKeyID: symID,
|
|
PowTarget: whisperv6.DefaultMinimumPoW,
|
|
PowTime: 200,
|
|
TTL: 10,
|
|
Topic: whisperv6.TopicType{0x01, 0x01, 0x01, 0x01},
|
|
Payload: []byte("hello"),
|
|
}
|
|
stop := make(chan struct{})
|
|
defer close(stop)
|
|
go func() {
|
|
ticker := time.NewTicker(2 * time.Second)
|
|
for {
|
|
select {
|
|
case <-stop:
|
|
return
|
|
case <-ticker.C:
|
|
var hash common.Hash
|
|
s.NoError(client.Call(&hash, "shhext_post", msg))
|
|
}
|
|
}
|
|
}()
|
|
|
|
events := make(chan whisperv6.EnvelopeEvent, 100)
|
|
sub := w.SubscribeEnvelopeEvents(events)
|
|
defer sub.Unsubscribe()
|
|
waitAtLeastOneSent := func(timelimit time.Duration) {
|
|
timeout := time.After(timelimit)
|
|
for {
|
|
select {
|
|
case ev := <-events:
|
|
if ev.Event == whisperv6.EventEnvelopeSent {
|
|
return
|
|
}
|
|
case <-timeout:
|
|
s.FailNow("failed waiting for at least one envelope SENT")
|
|
return
|
|
}
|
|
}
|
|
}
|
|
waitAtLeastOneSent(60 * time.Second)
|
|
s.Require().NoError(s.controller.Enable())
|
|
waitEnvelopes := func(timelimit time.Duration, expect bool) {
|
|
timeout := time.After(timelimit)
|
|
for {
|
|
select {
|
|
case ev := <-events:
|
|
if ev.Event == whisperv6.EventEnvelopeSent {
|
|
if !expect {
|
|
s.FailNow("Unexpected SENT event")
|
|
}
|
|
}
|
|
case <-timeout:
|
|
return
|
|
}
|
|
}
|
|
}
|
|
// we verify that during this time no SENT events were fired
|
|
// must be less then 10s (current read socket deadline) to avoid reconnect
|
|
waitEnvelopes(9*time.Second, false)
|
|
s.Require().NoError(s.controller.Disable())
|
|
waitAtLeastOneSent(3 * time.Second)
|
|
}
|
|
|
|
// TestStaticPeersReconnect : it tests how long it takes to reconnect with
|
|
// peers after losing connection. This is something we will have to support
|
|
// in order for mobile devices to reconnect fast if network connectivity
|
|
// is lost for ~30s.
|
|
func (s *PeersTestSuite) TestStaticPeersReconnect() {
|
|
// both on rinkeby and ropsten we can expect atleast 2 peers connected
|
|
expectedPeersCount := 2
|
|
events := make(chan *p2p.PeerEvent, 10)
|
|
node := s.backend.StatusNode().GethNode()
|
|
s.Require().NotNil(node)
|
|
|
|
subscription := node.Server().SubscribeEvents(events)
|
|
defer subscription.Unsubscribe()
|
|
peers := map[discover.NodeID]struct{}{}
|
|
before := time.Now()
|
|
s.Require().NoError(consumeUntil(events, func(ev *p2p.PeerEvent) bool {
|
|
log.Info("tests", "event", ev)
|
|
if ev.Type == p2p.PeerEventTypeAdd {
|
|
peers[ev.Peer] = struct{}{}
|
|
}
|
|
return len(peers) == expectedPeersCount
|
|
}, defaultTimeout))
|
|
s.WithinDuration(time.Now(), before, 5*time.Second)
|
|
|
|
s.Require().NoError(s.controller.Enable())
|
|
before = time.Now()
|
|
|
|
s.Require().NoError(consumeUntil(events, func(ev *p2p.PeerEvent) bool {
|
|
log.Info("tests", "event", ev)
|
|
if ev.Type == p2p.PeerEventTypeDrop {
|
|
delete(peers, ev.Peer)
|
|
}
|
|
return len(peers) == 0
|
|
}, defaultTimeout))
|
|
s.WithinDuration(time.Now(), before, 31*time.Second)
|
|
|
|
s.Require().NoError(s.controller.Disable())
|
|
before = time.Now()
|
|
go func() {
|
|
s.NoError(s.backend.StatusNode().ReconnectStaticPeers())
|
|
}()
|
|
s.Require().NoError(consumeUntil(events, func(ev *p2p.PeerEvent) bool {
|
|
log.Info("tests", "event", ev)
|
|
if ev.Type == p2p.PeerEventTypeAdd {
|
|
peers[ev.Peer] = struct{}{}
|
|
}
|
|
return len(peers) == expectedPeersCount
|
|
}, defaultTimeout))
|
|
s.WithinDuration(time.Now(), before, 31*time.Second)
|
|
}
|