diff --git a/p2p/address_test.go b/p2p/address_test.go index 5f7c66933..eff6afd7a 100644 --- a/p2p/address_test.go +++ b/p2p/address_test.go @@ -43,6 +43,7 @@ func TestNewNodeIDFromPubKey(t *testing.T) { privKey := ed25519.GenPrivKeyFromSecret([]byte("foo")) nodeID := p2p.NodeIDFromPubKey(privKey.PubKey()) require.Equal(t, p2p.NodeID("045f5600654182cfeaccfe6cb19f0642e8a59898"), nodeID) + require.NoError(t, nodeID.Validate()) } func TestNodeID_Bytes(t *testing.T) { diff --git a/p2p/pex/reactor_test.go b/p2p/pex/reactor_test.go index 6db8c0233..e716dfac8 100644 --- a/p2p/pex/reactor_test.go +++ b/p2p/pex/reactor_test.go @@ -2,10 +2,12 @@ package pex_test import ( "context" + "strings" "testing" "time" "github.com/stretchr/testify/require" + dbm "github.com/tendermint/tm-db" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/p2p" @@ -28,7 +30,7 @@ const ( func TestReactorBasic(t *testing.T) { // start a network with one mock reactor and one "real" reactor - testNet := setup(t, testOptions{ + testNet := setupNetwork(t, testOptions{ MockNodes: 1, TotalNodes: 2, }) @@ -45,7 +47,7 @@ func TestReactorBasic(t *testing.T) { } func TestReactorConnectFullNetwork(t *testing.T) { - testNet := setup(t, testOptions{ + testNet := setupNetwork(t, testOptions{ TotalNodes: 8, }) @@ -61,29 +63,34 @@ func TestReactorConnectFullNetwork(t *testing.T) { } func TestReactorSendsRequestsTooOften(t *testing.T) { - testNet := setup(t, testOptions{ - MockNodes: 1, - TotalNodes: 3, - }) - testNet.connectAll(t) - testNet.start(t) + r := setupSingle(t) - // firstNode sends two requests to the secondNode - testNet.sendRequest(t, firstNode, secondNode, true) - testNet.sendRequest(t, firstNode, secondNode, true) + badNode := newNodeID(t, "b") - // assert that the secondNode evicts the first node (although they reconnect - // straight away again) - testNet.listenForPeerUpdate(t, secondNode, firstNode, p2p.PeerStatusDown, shortWait) + r.pexInCh <- p2p.Envelope{ + From: badNode, + Message: &proto.PexRequestV2{}, + } - // firstNode should still receive the address of the thirdNode by the secondNode - expectedAddrs := testNet.getV2AddressesFor([]int{thirdNode}) - testNet.listenForResponse(t, secondNode, firstNode, shortWait, expectedAddrs) + resp := <-r.pexOutCh + msg, ok := resp.Message.(*proto.PexResponseV2) + require.True(t, ok) + require.Empty(t, msg.Addresses) + + r.pexInCh <- p2p.Envelope{ + From: badNode, + Message: &proto.PexRequestV2{}, + } + peerErr := <-r.pexErrCh + require.Error(t, peerErr.Err) + require.Empty(t, r.pexOutCh) + require.Contains(t, peerErr.Err.Error(), "peer sent a request too close after a prior one") + require.Equal(t, badNode, peerErr.NodeID) } func TestReactorSendsResponseWithoutRequest(t *testing.T) { - testNet := setup(t, testOptions{ + testNet := setupNetwork(t, testOptions{ MockNodes: 1, TotalNodes: 3, }) @@ -101,7 +108,7 @@ func TestReactorSendsResponseWithoutRequest(t *testing.T) { } func TestReactorNeverSendsTooManyPeers(t *testing.T) { - testNet := setup(t, testOptions{ + testNet := setupNetwork(t, testOptions{ MockNodes: 1, TotalNodes: 2, }) @@ -121,7 +128,7 @@ func TestReactorNeverSendsTooManyPeers(t *testing.T) { } func TestReactorErrorsOnReceivingTooManyPeers(t *testing.T) { - testNet := setup(t, testOptions{ + testNet := setupNetwork(t, testOptions{ MockNodes: 1, TotalNodes: 2, }) @@ -141,7 +148,7 @@ func TestReactorErrorsOnReceivingTooManyPeers(t *testing.T) { } func TestReactorSmallPeerStoreInALargeNetwork(t *testing.T) { - testNet := setup(t, testOptions{ + testNet := setupNetwork(t, testOptions{ TotalNodes: 16, MaxPeers: 8, MaxConnected: 6, @@ -160,7 +167,7 @@ func TestReactorSmallPeerStoreInALargeNetwork(t *testing.T) { } func TestReactorLargePeerStoreInASmallNetwork(t *testing.T) { - testNet := setup(t, testOptions{ + testNet := setupNetwork(t, testOptions{ TotalNodes: 10, MaxPeers: 100, MaxConnected: 100, @@ -176,7 +183,7 @@ func TestReactorLargePeerStoreInASmallNetwork(t *testing.T) { } func TestReactorWithNetworkGrowth(t *testing.T) { - testNet := setup(t, testOptions{ + testNet := setupNetwork(t, testOptions{ TotalNodes: 5, BufferSize: 5, }) @@ -207,7 +214,7 @@ func TestReactorWithNetworkGrowth(t *testing.T) { } func TestReactorIntegrationWithLegacyHandleRequest(t *testing.T) { - testNet := setup(t, testOptions{ + testNet := setupNetwork(t, testOptions{ MockNodes: 1, TotalNodes: 3, }) @@ -222,7 +229,7 @@ func TestReactorIntegrationWithLegacyHandleRequest(t *testing.T) { } func TestReactorIntegrationWithLegacyHandleResponse(t *testing.T) { - testNet := setup(t, testOptions{ + testNet := setupNetwork(t, testOptions{ MockNodes: 1, TotalNodes: 4, BufferSize: 4, @@ -238,6 +245,53 @@ func TestReactorIntegrationWithLegacyHandleResponse(t *testing.T) { testNet.requireNumberOfPeers(t, secondNode, len(testNet.nodes)-1, shortWait) } +type singleTestReactor struct { + reactor *pex.ReactorV2 + pexInCh chan p2p.Envelope + pexOutCh chan p2p.Envelope + pexErrCh chan p2p.PeerError + pexCh *p2p.Channel +} + +func setupSingle(t *testing.T) *singleTestReactor { + t.Helper() + nodeID := newNodeID(t, "a") + chBuf := 2 + pexInCh := make(chan p2p.Envelope, chBuf) + pexOutCh := make(chan p2p.Envelope, chBuf) + pexErrCh := make(chan p2p.PeerError, chBuf) + pexCh := p2p.NewChannel( + p2p.ChannelID(pex.PexChannel), + new(proto.PexMessage), + pexInCh, + pexOutCh, + pexErrCh, + ) + + peerUpdates := p2p.NewPeerUpdates(make(chan p2p.PeerUpdate), chBuf) + peerManager, err := p2p.NewPeerManager(nodeID, dbm.NewMemDB(), p2p.PeerManagerOptions{}) + require.NoError(t, err) + + reactor := pex.NewReactorV2(log.TestingLogger(), peerManager, pexCh, peerUpdates) + require.NoError(t, reactor.Start()) + t.Cleanup(func() { + err := reactor.Stop() + if err != nil { + t.Fatal(err) + } + pexCh.Close() + peerUpdates.Close() + }) + + return &singleTestReactor{ + reactor: reactor, + pexInCh: pexInCh, + pexOutCh: pexOutCh, + pexErrCh: pexErrCh, + pexCh: pexCh, + } +} + type reactorTestSuite struct { network *p2ptest.Network logger log.Logger @@ -264,7 +318,7 @@ type testOptions struct { // setup setups a test suite with a network of nodes. Mocknodes represent the // hollow nodes that the test can listen and send on -func setup(t *testing.T, opts testOptions) *reactorTestSuite { +func setupNetwork(t *testing.T, opts testOptions) *reactorTestSuite { t.Helper() require.Greater(t, opts.TotalNodes, opts.MockNodes) @@ -720,3 +774,9 @@ func (r *reactorTestSuite) addAddresses(t *testing.T, node int, addrs []int) { require.True(t, added) } } + +func newNodeID(t *testing.T, id string) p2p.NodeID { + nodeID, err := p2p.NewNodeID(strings.Repeat(id, 2*p2p.NodeIDByteLength)) + require.NoError(t, err) + return nodeID +}