github.com/lazyledger/lazyledger-core@v0.35.0-dev.0.20210613111200-4c651f053571/p2p/pex/pex_reactor_test.go (about)

     1  package pex
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/gogo/protobuf/proto"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  
    16  	"github.com/lazyledger/lazyledger-core/config"
    17  	"github.com/lazyledger/lazyledger-core/libs/log"
    18  	"github.com/lazyledger/lazyledger-core/p2p"
    19  	"github.com/lazyledger/lazyledger-core/p2p/mock"
    20  	tmp2p "github.com/lazyledger/lazyledger-core/proto/tendermint/p2p"
    21  )
    22  
    23  var (
    24  	cfg *config.P2PConfig
    25  )
    26  
    27  func init() {
    28  	cfg = config.DefaultP2PConfig()
    29  	cfg.PexReactor = true
    30  	cfg.AllowDuplicateIP = true
    31  }
    32  
    33  func TestPEXReactorBasic(t *testing.T) {
    34  	r, _ := createReactor(t, &ReactorConfig{})
    35  
    36  	assert.NotNil(t, r)
    37  	assert.NotEmpty(t, r.GetChannels())
    38  }
    39  
    40  func TestPEXReactorAddRemovePeer(t *testing.T) {
    41  	r, book := createReactor(t, &ReactorConfig{})
    42  
    43  	size := book.Size()
    44  	peer := p2p.CreateRandomPeer(false)
    45  
    46  	r.AddPeer(peer)
    47  	assert.Equal(t, size+1, book.Size())
    48  
    49  	r.RemovePeer(peer, "peer not available")
    50  
    51  	outboundPeer := p2p.CreateRandomPeer(true)
    52  
    53  	r.AddPeer(outboundPeer)
    54  	assert.Equal(t, size+1, book.Size(), "outbound peers should not be added to the address book")
    55  
    56  	r.RemovePeer(outboundPeer, "peer not available")
    57  }
    58  
    59  // --- FAIL: TestPEXReactorRunning (11.10s)
    60  // 				pex_reactor_test.go:411: expected all switches to be connected to at
    61  // 				least one peer (switches: 0 => {outbound: 1, inbound: 0}, 1 =>
    62  // 				{outbound: 0, inbound: 1}, 2 => {outbound: 0, inbound: 0}, )
    63  //
    64  // EXPLANATION: peers are getting rejected because in switch#addPeer we check
    65  // if any peer (who we already connected to) has the same IP. Even though local
    66  // peers have different IP addresses, they all have the same underlying remote
    67  // IP: 127.0.0.1.
    68  //
    69  func TestPEXReactorRunning(t *testing.T) {
    70  	N := 3
    71  	switches := make([]*p2p.Switch, N)
    72  
    73  	// directory to store address books
    74  	dir := tempDir(t)
    75  
    76  	books := make([]AddrBook, N)
    77  	logger := log.TestingLogger()
    78  
    79  	// create switches
    80  	for i := 0; i < N; i++ {
    81  		switches[i] = p2p.MakeSwitch(cfg, i, "testing", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch {
    82  			books[i] = NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", i)), false)
    83  			books[i].SetLogger(logger.With("pex", i))
    84  			sw.SetAddrBook(books[i])
    85  
    86  			sw.SetLogger(logger.With("pex", i))
    87  
    88  			r := NewReactor(books[i], &ReactorConfig{})
    89  			r.SetLogger(logger.With("pex", i))
    90  			r.SetEnsurePeersPeriod(250 * time.Millisecond)
    91  			sw.AddReactor("pex", r)
    92  
    93  			return sw
    94  		})
    95  	}
    96  
    97  	addOtherNodeAddrToAddrBook := func(switchIndex, otherSwitchIndex int) {
    98  		addr := switches[otherSwitchIndex].NetAddress()
    99  		err := books[switchIndex].AddAddress(addr, addr)
   100  		require.NoError(t, err)
   101  	}
   102  
   103  	addOtherNodeAddrToAddrBook(0, 1)
   104  	addOtherNodeAddrToAddrBook(1, 0)
   105  	addOtherNodeAddrToAddrBook(2, 1)
   106  
   107  	for _, sw := range switches {
   108  		err := sw.Start() // start switch and reactors
   109  		require.Nil(t, err)
   110  	}
   111  
   112  	assertPeersWithTimeout(t, switches, 10*time.Millisecond, 10*time.Second, N-1)
   113  
   114  	// stop them
   115  	for _, s := range switches {
   116  		err := s.Stop()
   117  		require.NoError(t, err)
   118  	}
   119  }
   120  
   121  func TestPEXReactorReceive(t *testing.T) {
   122  	r, book := createReactor(t, &ReactorConfig{})
   123  	peer := p2p.CreateRandomPeer(false)
   124  
   125  	// we have to send a request to receive responses
   126  	r.RequestAddrs(peer)
   127  
   128  	size := book.Size()
   129  	msg := mustEncode(&tmp2p.PexAddrs{Addrs: []tmp2p.NetAddress{peer.SocketAddr().ToProto()}})
   130  	r.Receive(PexChannel, peer, msg)
   131  	assert.Equal(t, size+1, book.Size())
   132  
   133  	msg = mustEncode(&tmp2p.PexRequest{})
   134  	r.Receive(PexChannel, peer, msg) // should not panic.
   135  }
   136  
   137  func TestPEXReactorRequestMessageAbuse(t *testing.T) {
   138  	r, book := createReactor(t, &ReactorConfig{})
   139  	sw := createSwitchAndAddReactors(r)
   140  	sw.SetAddrBook(book)
   141  
   142  	peer := mock.NewPeer(nil)
   143  	peerAddr := peer.SocketAddr()
   144  	p2p.AddPeerToSwitchPeerSet(sw, peer)
   145  	assert.True(t, sw.Peers().Has(peer.ID()))
   146  	err := book.AddAddress(peerAddr, peerAddr)
   147  	require.NoError(t, err)
   148  	require.True(t, book.HasAddress(peerAddr))
   149  
   150  	id := string(peer.ID())
   151  	msg := mustEncode(&tmp2p.PexRequest{})
   152  
   153  	// first time creates the entry
   154  	r.Receive(PexChannel, peer, msg)
   155  	assert.True(t, r.lastReceivedRequests.Has(id))
   156  	assert.True(t, sw.Peers().Has(peer.ID()))
   157  
   158  	// next time sets the last time value
   159  	r.Receive(PexChannel, peer, msg)
   160  	assert.True(t, r.lastReceivedRequests.Has(id))
   161  	assert.True(t, sw.Peers().Has(peer.ID()))
   162  
   163  	// third time is too many too soon - peer is removed
   164  	r.Receive(PexChannel, peer, msg)
   165  	assert.False(t, r.lastReceivedRequests.Has(id))
   166  	assert.False(t, sw.Peers().Has(peer.ID()))
   167  	assert.True(t, book.IsBanned(peerAddr))
   168  }
   169  
   170  func TestPEXReactorAddrsMessageAbuse(t *testing.T) {
   171  	r, book := createReactor(t, &ReactorConfig{})
   172  	sw := createSwitchAndAddReactors(r)
   173  	sw.SetAddrBook(book)
   174  
   175  	peer := mock.NewPeer(nil)
   176  	p2p.AddPeerToSwitchPeerSet(sw, peer)
   177  	assert.True(t, sw.Peers().Has(peer.ID()))
   178  
   179  	id := string(peer.ID())
   180  
   181  	// request addrs from the peer
   182  	r.RequestAddrs(peer)
   183  	assert.True(t, r.requestsSent.Has(id))
   184  	assert.True(t, sw.Peers().Has(peer.ID()))
   185  
   186  	msg := mustEncode(&tmp2p.PexAddrs{Addrs: []tmp2p.NetAddress{peer.SocketAddr().ToProto()}})
   187  
   188  	// receive some addrs. should clear the request
   189  	r.Receive(PexChannel, peer, msg)
   190  	assert.False(t, r.requestsSent.Has(id))
   191  	assert.True(t, sw.Peers().Has(peer.ID()))
   192  
   193  	// receiving more unsolicited addrs causes a disconnect and ban
   194  	r.Receive(PexChannel, peer, msg)
   195  	assert.False(t, sw.Peers().Has(peer.ID()))
   196  	assert.True(t, book.IsBanned(peer.SocketAddr()))
   197  }
   198  
   199  func TestCheckSeeds(t *testing.T) {
   200  	// directory to store address books
   201  	dir := tempDir(t)
   202  
   203  	// 1. test creating peer with no seeds works
   204  	peerSwitch := testCreateDefaultPeer(dir, 0)
   205  	require.Nil(t, peerSwitch.Start())
   206  	peerSwitch.Stop() // nolint:errcheck // ignore for tests
   207  
   208  	// 2. create seed
   209  	seed := testCreateSeed(dir, 1, []*p2p.NetAddress{}, []*p2p.NetAddress{})
   210  
   211  	// 3. test create peer with online seed works
   212  	peerSwitch = testCreatePeerWithSeed(dir, 2, seed)
   213  	require.Nil(t, peerSwitch.Start())
   214  	peerSwitch.Stop() // nolint:errcheck // ignore for tests
   215  
   216  	// 4. test create peer with all seeds having unresolvable DNS fails
   217  	badPeerConfig := &ReactorConfig{
   218  		Seeds: []string{"ed3dfd27bfc4af18f67a49862f04cc100696e84d@bad.network.addr:26657",
   219  			"d824b13cb5d40fa1d8a614e089357c7eff31b670@anotherbad.network.addr:26657"},
   220  	}
   221  	peerSwitch = testCreatePeerWithConfig(dir, 2, badPeerConfig)
   222  	require.Error(t, peerSwitch.Start())
   223  	peerSwitch.Stop() // nolint:errcheck // ignore for tests
   224  
   225  	// 5. test create peer with one good seed address succeeds
   226  	badPeerConfig = &ReactorConfig{
   227  		Seeds: []string{"ed3dfd27bfc4af18f67a49862f04cc100696e84d@bad.network.addr:26657",
   228  			"d824b13cb5d40fa1d8a614e089357c7eff31b670@anotherbad.network.addr:26657",
   229  			seed.NetAddress().String()},
   230  	}
   231  	peerSwitch = testCreatePeerWithConfig(dir, 2, badPeerConfig)
   232  	require.Nil(t, peerSwitch.Start())
   233  	peerSwitch.Stop() // nolint:errcheck // ignore for tests
   234  }
   235  
   236  func TestPEXReactorUsesSeedsIfNeeded(t *testing.T) {
   237  	// directory to store address books
   238  	dir := tempDir(t)
   239  
   240  	// 1. create seed
   241  	seed := testCreateSeed(dir, 0, []*p2p.NetAddress{}, []*p2p.NetAddress{})
   242  	require.Nil(t, seed.Start())
   243  	t.Cleanup(func() { _ = seed.Stop() })
   244  
   245  	// 2. create usual peer with only seed configured.
   246  	peer := testCreatePeerWithSeed(dir, 1, seed)
   247  	require.Nil(t, peer.Start())
   248  	t.Cleanup(func() { _ = peer.Stop() })
   249  
   250  	// 3. check that the peer connects to seed immediately
   251  	assertPeersWithTimeout(t, []*p2p.Switch{peer}, 10*time.Millisecond, 3*time.Second, 1)
   252  }
   253  
   254  func TestConnectionSpeedForPeerReceivedFromSeed(t *testing.T) {
   255  	// directory to store address books
   256  	dir := tempDir(t)
   257  
   258  	// 1. create peer
   259  	peerSwitch := testCreateDefaultPeer(dir, 1)
   260  	require.Nil(t, peerSwitch.Start())
   261  	t.Cleanup(func() { _ = peerSwitch.Stop() })
   262  
   263  	// 2. Create seed which knows about the peer
   264  	peerAddr := peerSwitch.NetAddress()
   265  	seed := testCreateSeed(dir, 2, []*p2p.NetAddress{peerAddr}, []*p2p.NetAddress{peerAddr})
   266  	require.Nil(t, seed.Start())
   267  	t.Cleanup(func() { _ = seed.Stop() })
   268  
   269  	// 3. create another peer with only seed configured.
   270  	secondPeer := testCreatePeerWithSeed(dir, 3, seed)
   271  	require.Nil(t, secondPeer.Start())
   272  	t.Cleanup(func() { _ = secondPeer.Stop() })
   273  
   274  	// 4. check that the second peer connects to seed immediately
   275  	assertPeersWithTimeout(t, []*p2p.Switch{secondPeer}, 10*time.Millisecond, 3*time.Second, 1)
   276  
   277  	// 5. check that the second peer connects to the first peer immediately
   278  	assertPeersWithTimeout(t, []*p2p.Switch{secondPeer}, 10*time.Millisecond, 1*time.Second, 2)
   279  }
   280  
   281  func TestPEXReactorSeedMode(t *testing.T) {
   282  	// directory to store address books
   283  	dir := tempDir(t)
   284  
   285  	pexRConfig := &ReactorConfig{SeedMode: true, SeedDisconnectWaitPeriod: 10 * time.Millisecond}
   286  	pexR, book := createReactor(t, pexRConfig)
   287  	sw := createSwitchAndAddReactors(pexR)
   288  
   289  	sw.SetAddrBook(book)
   290  	require.NoError(t, sw.Start())
   291  	t.Cleanup(func() { _ = sw.Stop() })
   292  
   293  	assert.Zero(t, sw.Peers().Size())
   294  
   295  	peerSwitch := testCreateDefaultPeer(dir, 1)
   296  	require.NoError(t, peerSwitch.Start())
   297  	t.Cleanup(func() { _ = peerSwitch.Stop() })
   298  
   299  	// 1. Test crawlPeers dials the peer
   300  	pexR.crawlPeers([]*p2p.NetAddress{peerSwitch.NetAddress()})
   301  	assert.Equal(t, 1, sw.Peers().Size())
   302  	assert.True(t, sw.Peers().Has(peerSwitch.NodeInfo().ID()))
   303  
   304  	// 2. attemptDisconnects should not disconnect because of wait period
   305  	pexR.attemptDisconnects()
   306  	assert.Equal(t, 1, sw.Peers().Size())
   307  
   308  	// sleep for SeedDisconnectWaitPeriod
   309  	time.Sleep(pexRConfig.SeedDisconnectWaitPeriod + 1*time.Millisecond)
   310  
   311  	// 3. attemptDisconnects should disconnect after wait period
   312  	pexR.attemptDisconnects()
   313  	assert.Equal(t, 0, sw.Peers().Size())
   314  }
   315  
   316  func TestPEXReactorDoesNotDisconnectFromPersistentPeerInSeedMode(t *testing.T) {
   317  	// directory to store address books
   318  	dir := tempDir(t)
   319  
   320  	pexRConfig := &ReactorConfig{SeedMode: true, SeedDisconnectWaitPeriod: 1 * time.Millisecond}
   321  	pexR, book := createReactor(t, pexRConfig)
   322  	sw := createSwitchAndAddReactors(pexR)
   323  
   324  	sw.SetAddrBook(book)
   325  	require.NoError(t, sw.Start())
   326  	t.Cleanup(func() { _ = sw.Stop() })
   327  
   328  	assert.Zero(t, sw.Peers().Size())
   329  
   330  	peerSwitch := testCreateDefaultPeer(dir, 1)
   331  	require.NoError(t, peerSwitch.Start())
   332  	t.Cleanup(func() { _ = peerSwitch.Stop() })
   333  
   334  	require.NoError(t, sw.AddPersistentPeers([]string{peerSwitch.NetAddress().String()}))
   335  
   336  	// 1. Test crawlPeers dials the peer
   337  	pexR.crawlPeers([]*p2p.NetAddress{peerSwitch.NetAddress()})
   338  	assert.Equal(t, 1, sw.Peers().Size())
   339  	assert.True(t, sw.Peers().Has(peerSwitch.NodeInfo().ID()))
   340  
   341  	// sleep for SeedDisconnectWaitPeriod
   342  	time.Sleep(pexRConfig.SeedDisconnectWaitPeriod + 1*time.Millisecond)
   343  
   344  	// 2. attemptDisconnects should not disconnect because the peer is persistent
   345  	pexR.attemptDisconnects()
   346  	assert.Equal(t, 1, sw.Peers().Size())
   347  }
   348  
   349  func TestPEXReactorDialsPeerUpToMaxAttemptsInSeedMode(t *testing.T) {
   350  	// directory to store address books
   351  	pexR, book := createReactor(t, &ReactorConfig{SeedMode: true})
   352  	sw := createSwitchAndAddReactors(pexR)
   353  
   354  	sw.SetAddrBook(book)
   355  	// No need to start sw since crawlPeers is called manually here.
   356  
   357  	peer := mock.NewPeer(nil)
   358  	addr := peer.SocketAddr()
   359  
   360  	require.NoError(t, book.AddAddress(addr, addr))
   361  
   362  	assert.True(t, book.HasAddress(addr))
   363  
   364  	// imitate maxAttemptsToDial reached
   365  	pexR.attemptsToDial.Store(addr.DialString(), _attemptsToDial{maxAttemptsToDial + 1, time.Now()})
   366  	pexR.crawlPeers([]*p2p.NetAddress{addr})
   367  
   368  	assert.False(t, book.HasAddress(addr))
   369  }
   370  
   371  // connect a peer to a seed, wait a bit, then stop it.
   372  // this should give it time to request addrs and for the seed
   373  // to call FlushStop, and allows us to test calling Stop concurrently
   374  // with FlushStop. Before a fix, this non-deterministically reproduced
   375  // https://github.com/tendermint/tendermint/issues/3231.
   376  func TestPEXReactorSeedModeFlushStop(t *testing.T) {
   377  	N := 2
   378  	switches := make([]*p2p.Switch, N)
   379  
   380  	// directory to store address books
   381  	dir := tempDir(t)
   382  
   383  	books := make([]AddrBook, N)
   384  	logger := log.TestingLogger()
   385  
   386  	// create switches
   387  	for i := 0; i < N; i++ {
   388  		switches[i] = p2p.MakeSwitch(cfg, i, "testing", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch {
   389  			books[i] = NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", i)), false)
   390  			books[i].SetLogger(logger.With("pex", i))
   391  			sw.SetAddrBook(books[i])
   392  
   393  			sw.SetLogger(logger.With("pex", i))
   394  
   395  			config := &ReactorConfig{}
   396  			if i == 0 {
   397  				// first one is a seed node
   398  				config = &ReactorConfig{SeedMode: true}
   399  			}
   400  			r := NewReactor(books[i], config)
   401  			r.SetLogger(logger.With("pex", i))
   402  			r.SetEnsurePeersPeriod(250 * time.Millisecond)
   403  			sw.AddReactor("pex", r)
   404  
   405  			return sw
   406  		})
   407  	}
   408  
   409  	for _, sw := range switches {
   410  		err := sw.Start() // start switch and reactors
   411  		require.Nil(t, err)
   412  	}
   413  
   414  	reactor := switches[0].Reactors()["pex"].(*Reactor)
   415  	peerID := switches[1].NodeInfo().ID()
   416  
   417  	assert.NoError(t, switches[1].DialPeerWithAddress(switches[0].NetAddress()))
   418  
   419  	// sleep up to a second while waiting for the peer to send us a message.
   420  	// this isn't perfect since it's possible the peer sends us a msg and we FlushStop
   421  	// before this loop catches it. but non-deterministically it works pretty well.
   422  	for i := 0; i < 1000; i++ {
   423  		v := reactor.lastReceivedRequests.Get(string(peerID))
   424  		if v != nil {
   425  			break
   426  		}
   427  		time.Sleep(time.Millisecond)
   428  	}
   429  
   430  	// by now the FlushStop should have happened. Try stopping the peer.
   431  	// it should be safe to do this.
   432  	peers := switches[0].Peers().List()
   433  	for _, peer := range peers {
   434  		err := peer.Stop()
   435  		require.NoError(t, err)
   436  	}
   437  
   438  	// stop the switches
   439  	for _, s := range switches {
   440  		err := s.Stop()
   441  		require.NoError(t, err)
   442  	}
   443  }
   444  
   445  func TestPEXReactorDoesNotAddPrivatePeersToAddrBook(t *testing.T) {
   446  	peer := p2p.CreateRandomPeer(false)
   447  
   448  	pexR, book := createReactor(t, &ReactorConfig{})
   449  	book.AddPrivateIDs([]string{string(peer.NodeInfo().ID())})
   450  
   451  	// we have to send a request to receive responses
   452  	pexR.RequestAddrs(peer)
   453  
   454  	size := book.Size()
   455  	msg := mustEncode(&tmp2p.PexAddrs{Addrs: []tmp2p.NetAddress{peer.SocketAddr().ToProto()}})
   456  	pexR.Receive(PexChannel, peer, msg)
   457  	assert.Equal(t, size, book.Size())
   458  
   459  	pexR.AddPeer(peer)
   460  	assert.Equal(t, size, book.Size())
   461  }
   462  
   463  func TestPEXReactorDialPeer(t *testing.T) {
   464  	pexR, book := createReactor(t, &ReactorConfig{})
   465  	sw := createSwitchAndAddReactors(pexR)
   466  
   467  	sw.SetAddrBook(book)
   468  
   469  	peer := mock.NewPeer(nil)
   470  	addr := peer.SocketAddr()
   471  
   472  	assert.Equal(t, 0, pexR.AttemptsToDial(addr))
   473  
   474  	// 1st unsuccessful attempt
   475  	err := pexR.dialPeer(addr)
   476  	require.Error(t, err)
   477  
   478  	assert.Equal(t, 1, pexR.AttemptsToDial(addr))
   479  
   480  	// 2nd unsuccessful attempt
   481  	err = pexR.dialPeer(addr)
   482  	require.Error(t, err)
   483  
   484  	// must be skipped because it is too early
   485  	assert.Equal(t, 1, pexR.AttemptsToDial(addr))
   486  
   487  	if !testing.Short() {
   488  		time.Sleep(3 * time.Second)
   489  
   490  		// 3rd attempt
   491  		err = pexR.dialPeer(addr)
   492  		require.Error(t, err)
   493  
   494  		assert.Equal(t, 2, pexR.AttemptsToDial(addr))
   495  	}
   496  }
   497  
   498  func assertPeersWithTimeout(
   499  	t *testing.T,
   500  	switches []*p2p.Switch,
   501  	checkPeriod, timeout time.Duration,
   502  	nPeers int,
   503  ) {
   504  	var (
   505  		ticker    = time.NewTicker(checkPeriod)
   506  		remaining = timeout
   507  	)
   508  
   509  	for {
   510  		select {
   511  		case <-ticker.C:
   512  			// check peers are connected
   513  			allGood := true
   514  			for _, s := range switches {
   515  				outbound, inbound, _ := s.NumPeers()
   516  				if outbound+inbound < nPeers {
   517  					allGood = false
   518  					break
   519  				}
   520  			}
   521  			remaining -= checkPeriod
   522  			if remaining < 0 {
   523  				remaining = 0
   524  			}
   525  			if allGood {
   526  				return
   527  			}
   528  		case <-time.After(remaining):
   529  			numPeersStr := ""
   530  			for i, s := range switches {
   531  				outbound, inbound, _ := s.NumPeers()
   532  				numPeersStr += fmt.Sprintf("%d => {outbound: %d, inbound: %d}, ", i, outbound, inbound)
   533  			}
   534  			t.Errorf(
   535  				"expected all switches to be connected to at least %d peer(s) (switches: %s)",
   536  				nPeers, numPeersStr,
   537  			)
   538  			return
   539  		}
   540  	}
   541  }
   542  
   543  // Creates a peer with the provided config
   544  func testCreatePeerWithConfig(dir string, id int, config *ReactorConfig) *p2p.Switch {
   545  	peer := p2p.MakeSwitch(
   546  		cfg,
   547  		id,
   548  		"127.0.0.1",
   549  		"123.123.123",
   550  		func(i int, sw *p2p.Switch) *p2p.Switch {
   551  			book := NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", id)), false)
   552  			book.SetLogger(log.TestingLogger())
   553  			sw.SetAddrBook(book)
   554  
   555  			sw.SetLogger(log.TestingLogger())
   556  
   557  			r := NewReactor(
   558  				book,
   559  				config,
   560  			)
   561  			r.SetLogger(log.TestingLogger())
   562  			sw.AddReactor("pex", r)
   563  			return sw
   564  		},
   565  	)
   566  	return peer
   567  }
   568  
   569  // Creates a peer with the default config
   570  func testCreateDefaultPeer(dir string, id int) *p2p.Switch {
   571  	return testCreatePeerWithConfig(dir, id, &ReactorConfig{})
   572  }
   573  
   574  // Creates a seed which knows about the provided addresses / source address pairs.
   575  // Starting and stopping the seed is left to the caller
   576  func testCreateSeed(dir string, id int, knownAddrs, srcAddrs []*p2p.NetAddress) *p2p.Switch {
   577  	seed := p2p.MakeSwitch(
   578  		cfg,
   579  		id,
   580  		"127.0.0.1",
   581  		"123.123.123",
   582  		func(i int, sw *p2p.Switch) *p2p.Switch {
   583  			book := NewAddrBook(filepath.Join(dir, "addrbookSeed.json"), false)
   584  			book.SetLogger(log.TestingLogger())
   585  			for j := 0; j < len(knownAddrs); j++ {
   586  				book.AddAddress(knownAddrs[j], srcAddrs[j]) // nolint:errcheck // ignore for tests
   587  				book.MarkGood(knownAddrs[j].ID)
   588  			}
   589  			sw.SetAddrBook(book)
   590  
   591  			sw.SetLogger(log.TestingLogger())
   592  
   593  			r := NewReactor(book, &ReactorConfig{})
   594  			r.SetLogger(log.TestingLogger())
   595  			sw.AddReactor("pex", r)
   596  			return sw
   597  		},
   598  	)
   599  	return seed
   600  }
   601  
   602  // Creates a peer which knows about the provided seed.
   603  // Starting and stopping the peer is left to the caller
   604  func testCreatePeerWithSeed(dir string, id int, seed *p2p.Switch) *p2p.Switch {
   605  	conf := &ReactorConfig{
   606  		Seeds: []string{seed.NetAddress().String()},
   607  	}
   608  	return testCreatePeerWithConfig(dir, id, conf)
   609  }
   610  
   611  func createReactor(t *testing.T, conf *ReactorConfig) (r *Reactor, book AddrBook) {
   612  	// directory to store address book
   613  	book = NewAddrBook(filepath.Join(tempDir(t), "addrbook.json"), true)
   614  	book.SetLogger(log.TestingLogger())
   615  
   616  	r = NewReactor(book, conf)
   617  	r.SetLogger(log.TestingLogger())
   618  	return
   619  }
   620  
   621  func createSwitchAndAddReactors(reactors ...p2p.Reactor) *p2p.Switch {
   622  	sw := p2p.MakeSwitch(cfg, 0, "127.0.0.1", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { return sw })
   623  	sw.SetLogger(log.TestingLogger())
   624  	for _, r := range reactors {
   625  		sw.AddReactor(r.String(), r)
   626  		r.SetSwitch(sw)
   627  	}
   628  	return sw
   629  }
   630  
   631  func TestPexVectors(t *testing.T) {
   632  	addr := tmp2p.NetAddress{
   633  		ID:   "1",
   634  		IP:   "127.0.0.1",
   635  		Port: 9090,
   636  	}
   637  
   638  	testCases := []struct {
   639  		testName string
   640  		msg      proto.Message
   641  		expBytes string
   642  	}{
   643  		{"PexRequest", &tmp2p.PexRequest{}, "0a00"},
   644  		{"PexAddrs", &tmp2p.PexAddrs{Addrs: []tmp2p.NetAddress{addr}}, "12130a110a013112093132372e302e302e31188247"},
   645  	}
   646  
   647  	for _, tc := range testCases {
   648  		tc := tc
   649  
   650  		bz := mustEncode(tc.msg)
   651  
   652  		require.Equal(t, tc.expBytes, hex.EncodeToString(bz), tc.testName)
   653  	}
   654  }
   655  
   656  // FIXME: This function is used in place of testing.TB.TempDir()
   657  // as the latter seems to cause test cases to fail when it is
   658  // unable to remove the temporary directory once  the test case
   659  // execution terminates. This seems to  happen often with pex
   660  // reactor test cases.
   661  //
   662  // References:
   663  // https://github.com/tendermint/tendermint/pull/5733
   664  // https://github.com/tendermint/tendermint/issues/5732
   665  func tempDir(t *testing.T) string {
   666  	t.Helper()
   667  	dir, err := ioutil.TempDir("", "")
   668  	require.NoError(t, err)
   669  	t.Cleanup(func() { _ = os.RemoveAll(dir) })
   670  	return dir
   671  }