status-im/status-go

View on GitHub
peers/cotopicpool_test.go

Summary

Maintainability
A
0 mins
Test Coverage
package peers

import (
    "context"
    "testing"
    "time"

    "github.com/stretchr/testify/suite"

    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/crypto"
    "github.com/ethereum/go-ethereum/p2p"
    "github.com/ethereum/go-ethereum/p2p/discv5"
    "github.com/ethereum/go-ethereum/p2p/enode"

    "github.com/status-im/status-go/params"
)

type CacheOnlyTopicPoolSuite struct {
    suite.Suite

    peer      *p2p.Server
    topicPool *cacheOnlyTopicPool
}

func TestCacheOnlyTopicPoolSuite(t *testing.T) {
    suite.Run(t, new(CacheOnlyTopicPoolSuite))
}

func (s *CacheOnlyTopicPoolSuite) SetupTest() {
    maxCachedPeersMultiplier = 1
    key, _ := crypto.GenerateKey()
    name := common.MakeName("peer", "1.0")
    s.peer = &p2p.Server{
        Config: p2p.Config{
            MaxPeers:    10,
            Name:        name,
            ListenAddr:  "0.0.0.0:0",
            PrivateKey:  key,
            NoDiscovery: true,
        },
    }
    s.Require().NoError(s.peer.Start())
    limits := params.NewLimits(1, 2)
    cache, err := newInMemoryCache()
    s.Require().NoError(err)
    t := newTopicPool(nil, MailServerDiscoveryTopic, limits, 100*time.Millisecond, 200*time.Millisecond, cache)
    s.topicPool = newCacheOnlyTopicPool(t, &testTrueVerifier{})
    s.topicPool.running = 1
    // This is a buffered channel to simplify testing.
    // If your test generates more than 10 mode changes,
    // override this `period` field or consume from it
    // using `AssertConsumed()`.
    s.topicPool.period = make(chan time.Duration, 10)
}

func (s *CacheOnlyTopicPoolSuite) TearDown() {
    s.peer.Stop()
}

func (s *CacheOnlyTopicPoolSuite) TestReplacementPeerIsCounted() {
    s.topicPool.limits = params.NewLimits(1, 1)
    s.topicPool.maxCachedPeers = 1

    id1, err := crypto.GenerateKey()
    s.Require().NoError(err)
    peer1 := discv5.NewNode(discv5.PubkeyID(&id1.PublicKey), s.peer.Self().IP(), 32311, 32311)
    id2, err := crypto.GenerateKey()
    s.Require().NoError(err)
    peer2 := discv5.NewNode(discv5.PubkeyID(&id2.PublicKey), s.peer.Self().IP(), 32311, 32311)
    s.Require().NoError(s.topicPool.processFoundNode(s.peer, peer1))
    s.Require().NoError(s.topicPool.processFoundNode(s.peer, peer2))
    s.topicPool.ConfirmAdded(s.peer, enode.PubkeyToIDV4(&id1.PublicKey))
    s.topicPool.ConfirmAdded(s.peer, enode.PubkeyToIDV4(&id1.PublicKey))
    s.True(s.topicPool.MaxReached())

    // When we stop searching for peers (when Max limit is reached)
    s.topicPool.StopSearch(s.peer)
    s.True(s.topicPool.MaxReached())
    s.Equal(0, s.topicPool.limits.Max)
    s.Equal(0, s.topicPool.limits.Min)

    // Then we should drop all connected peers
    s.Equal(len(s.topicPool.connectedPeers), 0)

    // And cached peers should remain
    cachedPeers := s.topicPool.cache.GetPeersRange(s.topicPool.topic, s.topicPool.maxCachedPeers)
    s.Equal(1, len(cachedPeers))
}

func (s *CacheOnlyTopicPoolSuite) TestConfirmAddedSignals() {
    sentNodeID := ""
    sentTopic := ""
    sendEnodeDiscovered = func(enode, topic string) {
        sentNodeID = enode
        sentTopic = topic
    }

    id, err := crypto.GenerateKey()
    s.Require().NoError(err)
    nodeID := enode.PubkeyToIDV4(&id.PublicKey)

    s.topicPool.ConfirmAdded(s.peer, nodeID)
    s.Equal(nodeID.String(), sentNodeID)
    s.Equal(MailServerDiscoveryTopic, sentTopic)
}

func (s *CacheOnlyTopicPoolSuite) TestNotTrustedPeer() {
    var signalCalled bool
    sendEnodeDiscovered = func(_, _ string) { signalCalled = true }

    s.topicPool.limits = params.NewLimits(1, 1)
    s.topicPool.maxCachedPeers = 1
    s.topicPool.verifier = &testFalseVerifier{}

    id, err := crypto.GenerateKey()
    s.Require().NoError(err)
    foundPeer := discv5.NewNode(discv5.PubkeyID(&id.PublicKey), s.peer.Self().IP(), 32311, 32311)
    s.Require().NoError(s.topicPool.processFoundNode(s.peer, foundPeer))
    s.topicPool.ConfirmAdded(s.peer, enode.PubkeyToIDV4(&id.PublicKey))

    s.False(signalCalled)
    // limits should not change
    s.Equal(1, s.topicPool.limits.Max)
    s.Equal(1, s.topicPool.limits.Min)
    // not verified peer shoud not be added to the cache
    s.Equal(0, len(s.topicPool.cache.GetPeersRange(s.topicPool.topic, s.topicPool.limits.Max)))
}

type testTrueVerifier struct{}

func (v *testTrueVerifier) VerifyNode(context.Context, enode.ID) bool {
    return true
}

type testFalseVerifier struct{}

func (v *testFalseVerifier) VerifyNode(context.Context, enode.ID) bool {
    return false
}