github.com/celestiaorg/celestia-node@v0.15.0-beta.1/nodebuilder/p2p/p2p_test.go (about)

     1  package p2p
     2  
     3  import (
     4  	"context"
     5  	"crypto/rand"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/ipfs/go-datastore"
    10  	"github.com/libp2p/go-libp2p"
    11  	pubsub "github.com/libp2p/go-libp2p-pubsub"
    12  	libhost "github.com/libp2p/go-libp2p/core/host"
    13  	"github.com/libp2p/go-libp2p/core/metrics"
    14  	"github.com/libp2p/go-libp2p/core/network"
    15  	"github.com/libp2p/go-libp2p/core/protocol"
    16  	rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
    17  	mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
    18  	"github.com/stretchr/testify/assert"
    19  	"github.com/stretchr/testify/require"
    20  )
    21  
    22  // TestP2PModule_Host tests P2P Module methods on
    23  // the instance of Host.
    24  func TestP2PModule_Host(t *testing.T) {
    25  	net, err := mocknet.FullMeshConnected(2)
    26  	require.NoError(t, err)
    27  	host, peer := net.Hosts()[0], net.Hosts()[1]
    28  
    29  	mgr := newModule(host, nil, nil, nil, nil)
    30  
    31  	ctx := context.Background()
    32  
    33  	// test all methods on `manager.host`
    34  	peers, err := mgr.Peers(ctx)
    35  	require.NoError(t, err)
    36  	assert.Equal(t, host.Network().Peers(), peers)
    37  
    38  	peerInfo, err := mgr.PeerInfo(ctx, peer.ID())
    39  	require.NoError(t, err)
    40  	assert.Equal(t, libhost.InfoFromHost(peer).ID, peerInfo.ID)
    41  
    42  	connectedness, err := mgr.Connectedness(ctx, peer.ID())
    43  	require.NoError(t, err)
    44  	assert.Equal(t, host.Network().Connectedness(peer.ID()), connectedness)
    45  	// now disconnect using manager and check for connectedness match again
    46  	assert.NoError(t, mgr.ClosePeer(ctx, peer.ID()))
    47  	connectedness, err = mgr.Connectedness(ctx, peer.ID())
    48  	require.NoError(t, err)
    49  	assert.Equal(t, host.Network().Connectedness(peer.ID()), connectedness)
    50  }
    51  
    52  // TestP2PModule_ConnManager tests P2P Module methods on
    53  // the Host's ConnManager. Note that this test is constructed differently
    54  // than the one above because mocknet does not provide a ConnManager to its
    55  // mock peers.
    56  func TestP2PModule_ConnManager(t *testing.T) {
    57  	// make two full peers and connect them
    58  	host, err := libp2p.New()
    59  	require.NoError(t, err)
    60  
    61  	peer, err := libp2p.New()
    62  	require.NoError(t, err)
    63  
    64  	mgr := newModule(host, nil, nil, nil, nil)
    65  
    66  	ctx, cancel := context.WithCancel(context.Background())
    67  	t.Cleanup(cancel)
    68  
    69  	err = mgr.Connect(ctx, *libhost.InfoFromHost(peer))
    70  	require.NoError(t, err)
    71  
    72  	err = mgr.Protect(ctx, peer.ID(), "test")
    73  	require.NoError(t, err)
    74  	protected, err := mgr.IsProtected(ctx, peer.ID(), "test")
    75  	require.NoError(t, err)
    76  	assert.True(t, protected)
    77  
    78  	ok, err := mgr.Unprotect(ctx, peer.ID(), "test")
    79  	require.False(t, ok)
    80  	require.NoError(t, err)
    81  	protected, err = mgr.IsProtected(ctx, peer.ID(), "test")
    82  	require.NoError(t, err)
    83  	assert.False(t, protected)
    84  }
    85  
    86  // TestP2PModule_Autonat tests P2P Module methods on
    87  // the node's instance of AutoNAT.
    88  func TestP2PModule_Autonat(t *testing.T) {
    89  	host, err := libp2p.New(libp2p.EnableNATService())
    90  	require.NoError(t, err)
    91  
    92  	mgr := newModule(host, nil, nil, nil, nil)
    93  
    94  	status, err := mgr.NATStatus(context.Background())
    95  	assert.NoError(t, err)
    96  	assert.Equal(t, network.ReachabilityUnknown, status)
    97  }
    98  
    99  // TestP2PModule_Bandwidth tests P2P Module methods on
   100  // the Host's bandwidth reporter.
   101  func TestP2PModule_Bandwidth(t *testing.T) {
   102  	bw := metrics.NewBandwidthCounter()
   103  	host, err := libp2p.New(libp2p.BandwidthReporter(bw))
   104  	require.NoError(t, err)
   105  
   106  	protoID := protocol.ID("test")
   107  	// define a buf size, so we know how many bytes to read
   108  	bufSize := 1000
   109  
   110  	// create a peer to connect to
   111  	peer, err := libp2p.New(libp2p.BandwidthReporter(bw))
   112  	require.NoError(t, err)
   113  
   114  	// set stream handler on the host
   115  	host.SetStreamHandler(protoID, func(stream network.Stream) {
   116  		buf := make([]byte, bufSize)
   117  		_, err := stream.Read(buf)
   118  		require.NoError(t, err)
   119  
   120  		_, err = stream.Write(buf)
   121  		require.NoError(t, err)
   122  	})
   123  
   124  	mgr := newModule(host, nil, nil, bw, nil)
   125  
   126  	ctx, cancel := context.WithCancel(context.Background())
   127  	t.Cleanup(cancel)
   128  
   129  	// connect to the peer
   130  	err = mgr.Connect(ctx, *libhost.InfoFromHost(peer))
   131  	require.NoError(t, err)
   132  
   133  	// check to ensure they're actually connected
   134  	connectedness, err := mgr.Connectedness(ctx, peer.ID())
   135  	require.NoError(t, err)
   136  	require.Equal(t, network.Connected, connectedness)
   137  
   138  	// open stream with host
   139  	info, err := mgr.Info(ctx)
   140  	require.NoError(t, err)
   141  	stream, err := peer.NewStream(ctx, info.ID, protoID)
   142  	require.NoError(t, err)
   143  
   144  	// write to stream to increase bandwidth usage get some substantive
   145  	// data to read from the bandwidth counter
   146  	buf := make([]byte, bufSize)
   147  	_, err = rand.Read(buf)
   148  	require.NoError(t, err)
   149  	_, err = stream.Write(buf)
   150  	require.NoError(t, err)
   151  
   152  	_, err = stream.Read(buf)
   153  	require.NoError(t, err)
   154  
   155  	// has to be ~2 seconds for the metrics reporter to collect the stats
   156  	// in the background process
   157  	time.Sleep(time.Second * 2)
   158  
   159  	stats, err := mgr.BandwidthStats(ctx)
   160  	require.NoError(t, err)
   161  	assert.NotNil(t, stats)
   162  
   163  	peerStat, err := mgr.BandwidthForPeer(ctx, peer.ID())
   164  	require.NoError(t, err)
   165  	assert.NotZero(t, peerStat.TotalIn)
   166  	assert.Greater(t, int(peerStat.TotalIn), bufSize) // should be slightly more than buf size due negotiations, etc
   167  
   168  	protoStat, err := mgr.BandwidthForProtocol(ctx, protoID)
   169  	require.NoError(t, err)
   170  	assert.NotZero(t, protoStat.TotalIn)
   171  	assert.Greater(t, int(protoStat.TotalIn), bufSize) // should be slightly more than buf size due negotiations, etc
   172  }
   173  
   174  // TestP2PModule_Pubsub tests P2P Module methods on
   175  // the instance of pubsub.
   176  func TestP2PModule_Pubsub(t *testing.T) {
   177  	net, err := mocknet.FullMeshConnected(5)
   178  	require.NoError(t, err)
   179  
   180  	host := net.Hosts()[0]
   181  
   182  	ctx, cancel := context.WithCancel(context.Background())
   183  	t.Cleanup(cancel)
   184  
   185  	gs, err := pubsub.NewGossipSub(ctx, host)
   186  	require.NoError(t, err)
   187  
   188  	mgr := newModule(host, gs, nil, nil, nil)
   189  
   190  	topicStr := "test-topic"
   191  
   192  	topic, err := gs.Join(topicStr)
   193  	require.NoError(t, err)
   194  
   195  	// also join all peers on mocknet to topic
   196  	for _, p := range net.Hosts()[1:] {
   197  		newGs, err := pubsub.NewGossipSub(ctx, p)
   198  		require.NoError(t, err)
   199  
   200  		tp, err := newGs.Join(topicStr)
   201  		require.NoError(t, err)
   202  		_, err = tp.Subscribe()
   203  		require.NoError(t, err)
   204  	}
   205  
   206  	err = topic.Publish(ctx, []byte("test"))
   207  	require.NoError(t, err)
   208  
   209  	// give for some peers to properly join the topic (this is necessary
   210  	// anywhere where gossipsub is used in tests)
   211  	time.Sleep(1 * time.Second)
   212  
   213  	psPeers, err := mgr.PubSubPeers(context.Background(), topicStr)
   214  	require.NoError(t, err)
   215  	assert.Equal(t, len(topic.ListPeers()), len(psPeers))
   216  }
   217  
   218  // TestP2PModule_ConnGater tests P2P Module methods on
   219  // the instance of ConnectionGater.
   220  func TestP2PModule_ConnGater(t *testing.T) {
   221  	gater, err := connectionGater(datastore.NewMapDatastore())
   222  	require.NoError(t, err)
   223  
   224  	mgr := newModule(nil, nil, gater, nil, nil)
   225  
   226  	ctx := context.Background()
   227  
   228  	assert.NoError(t, mgr.BlockPeer(ctx, "badpeer"))
   229  	blocked, err := mgr.ListBlockedPeers(ctx)
   230  	require.NoError(t, err)
   231  	assert.Len(t, blocked, 1)
   232  
   233  	assert.NoError(t, mgr.UnblockPeer(ctx, "badpeer"))
   234  	blocked, err = mgr.ListBlockedPeers(ctx)
   235  	require.NoError(t, err)
   236  	assert.Len(t, blocked, 0)
   237  }
   238  
   239  // TestP2PModule_ResourceManager tests P2P Module methods on
   240  // the resourceManager.
   241  func TestP2PModule_ResourceManager(t *testing.T) {
   242  	rm, err := rcmgr.NewResourceManager(rcmgr.NewFixedLimiter(rcmgr.DefaultLimits.AutoScale()))
   243  	require.NoError(t, err)
   244  
   245  	mgr := newModule(nil, nil, nil, nil, rm)
   246  
   247  	state, err := mgr.ResourceState(context.Background())
   248  	require.NoError(t, err)
   249  
   250  	assert.NotNil(t, state)
   251  }