github.com/koko1123/flow-go-1@v0.29.6/network/p2p/connection/peerManager_integration_test.go (about)

     1  package connection_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/libp2p/go-libp2p/core/host"
     9  	"github.com/libp2p/go-libp2p/core/network"
    10  	"github.com/libp2p/go-libp2p/core/peer"
    11  	"github.com/libp2p/go-libp2p/core/peerstore"
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/koko1123/flow-go-1/model/flow"
    16  	"github.com/koko1123/flow-go-1/module/irrecoverable"
    17  	"github.com/koko1123/flow-go-1/network/p2p"
    18  	"github.com/koko1123/flow-go-1/network/p2p/connection"
    19  	p2ptest "github.com/koko1123/flow-go-1/network/p2p/test"
    20  	"github.com/koko1123/flow-go-1/network/p2p/translator"
    21  	"github.com/koko1123/flow-go-1/network/p2p/utils"
    22  	"github.com/koko1123/flow-go-1/utils/unittest"
    23  )
    24  
    25  // TestPeerManager_Integration tests the correctness of integration between PeerManager and Libp2pConnector over
    26  // a fully connected topology.
    27  // PeerManager should be able to connect to all peers using the connector, and must also tear down the connection to
    28  // peers that are excluded from its identity provider.
    29  func TestPeerManager_Integration(t *testing.T) {
    30  	count := 5
    31  	ctx, cancel := context.WithCancel(context.Background())
    32  
    33  	signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx)
    34  
    35  	// create nodes
    36  	nodes, identities := p2ptest.NodesFixture(t, unittest.IdentifierFixture(), "test_peer_manager", count)
    37  
    38  	p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond)
    39  	defer p2ptest.StopNodes(t, nodes, cancel, 100*time.Millisecond)
    40  
    41  	thisNode := nodes[0]
    42  	topologyPeers := identities[1:]
    43  
    44  	// adds address of all other nodes into the peer store of this node, so that it can dial them.
    45  	info, invalid := utils.PeerInfosFromIDs(topologyPeers)
    46  	require.Empty(t, invalid)
    47  	for _, i := range info {
    48  		thisNode.Host().Peerstore().SetAddrs(i.ID, i.Addrs, peerstore.PermanentAddrTTL)
    49  	}
    50  
    51  	// setup
    52  	connector, err := connection.NewLibp2pConnector(unittest.Logger(), thisNode.Host(), connection.ConnectionPruningEnabled)
    53  	require.NoError(t, err)
    54  
    55  	idTranslator, err := translator.NewFixedTableIdentityTranslator(identities)
    56  	require.NoError(t, err)
    57  
    58  	peerManager := connection.NewPeerManager(unittest.Logger(), connection.DefaultPeerUpdateInterval, connector)
    59  	peerManager.SetPeersProvider(func() peer.IDSlice {
    60  		// peerManager is furnished with a full topology that connects to all nodes
    61  		// in the topologyPeers.
    62  		peers := peer.IDSlice{}
    63  		for _, id := range topologyPeers {
    64  			peerId, err := idTranslator.GetPeerID(id.NodeID)
    65  			require.NoError(t, err)
    66  			peers = append(peers, peerId)
    67  		}
    68  
    69  		return peers
    70  	})
    71  
    72  	// initially no node should be in peer store of this node.
    73  	require.Empty(t, thisNode.Host().Network().Peers())
    74  	peerManager.ForceUpdatePeers(ctx)
    75  	time.Sleep(1 * time.Second)
    76  	// after a forced update all other nodes must be added to the peer store of this node.
    77  	require.Len(t, thisNode.Host().Network().Peers(), count-1)
    78  	// after a forced update there must be a connection between this node and other nodes
    79  	connectedToAll(t, thisNode.Host(), idTranslator, topologyPeers.NodeIDs())
    80  
    81  	// kicks one node out of the othersIds; this imitates evicting, ejecting, or unstaking a node
    82  	evictedId := topologyPeers[0]     // evicted one
    83  	topologyPeers = topologyPeers[1:] // updates otherIds list
    84  	peerManager.ForceUpdatePeers(ctx)
    85  	time.Sleep(1 * time.Second)
    86  	// after a forced update, the evicted one should be excluded from the peer store.
    87  	require.Len(t, thisNode.Host().Network().Peers(), count-2)
    88  	// there must be a connection between this node and other nodes (except evicted one).
    89  	connectedToAll(t, thisNode.Host(), idTranslator, topologyPeers.NodeIDs())
    90  
    91  	// there must be no connection between this node and evicted one
    92  	peerId, err := idTranslator.GetPeerID(evictedId.NodeID)
    93  	require.NoError(t, err)
    94  	assert.Equal(t, thisNode.Host().Network().Connectedness(peerId), network.NotConnected)
    95  }
    96  
    97  // connectedToAll is a test helper that fails if there is no connection between this host and at least one of the
    98  // nodes in "all".
    99  func connectedToAll(t *testing.T, host host.Host, translator p2p.IDTranslator, all flow.IdentifierList) {
   100  	for _, id := range all {
   101  		peerId, err := translator.GetPeerID(id)
   102  		require.NoError(t, err)
   103  		assert.Equal(t, host.Network().Connectedness(peerId), network.Connected)
   104  	}
   105  }