status-go/t/destructive/peers_test.go

110 lines
3.0 KiB
Go

package destructive
import (
"errors"
"testing"
"time"
"github.com/ethereum/go-ethereum/log"
"github.com/status-im/status-go/geth/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")
}
}
}
// 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)
}