github.com/vipernet-xyz/tendermint-core@v0.32.0/p2p/peer_set_test.go (about)

     1  package p2p
     2  
     3  import (
     4  	"net"
     5  	"sync"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  
    10  	"github.com/tendermint/tendermint/crypto/ed25519"
    11  	"github.com/tendermint/tendermint/libs/service"
    12  )
    13  
    14  // mockPeer for testing the PeerSet
    15  type mockPeer struct {
    16  	service.BaseService
    17  	ip net.IP
    18  	id ID
    19  }
    20  
    21  func (mp *mockPeer) FlushStop()                              { mp.Stop() }
    22  func (mp *mockPeer) TrySend(chID byte, msgBytes []byte) bool { return true }
    23  func (mp *mockPeer) Send(chID byte, msgBytes []byte) bool    { return true }
    24  func (mp *mockPeer) NodeInfo() NodeInfo                      { return DefaultNodeInfo{} }
    25  func (mp *mockPeer) Status() ConnectionStatus                { return ConnectionStatus{} }
    26  func (mp *mockPeer) ID() ID                                  { return mp.id }
    27  func (mp *mockPeer) IsOutbound() bool                        { return false }
    28  func (mp *mockPeer) IsPersistent() bool                      { return true }
    29  func (mp *mockPeer) Get(s string) interface{}                { return s }
    30  func (mp *mockPeer) Set(string, interface{})                 {}
    31  func (mp *mockPeer) RemoteIP() net.IP                        { return mp.ip }
    32  func (mp *mockPeer) SocketAddr() *NetAddress                 { return nil }
    33  func (mp *mockPeer) RemoteAddr() net.Addr                    { return &net.TCPAddr{IP: mp.ip, Port: 8800} }
    34  func (mp *mockPeer) CloseConn() error                        { return nil }
    35  func (mp *mockPeer) SetRemovalFailed()                       {}
    36  func (mp *mockPeer) GetRemovalFailed() bool                  { return false }
    37  
    38  // Returns a mock peer
    39  func newMockPeer(ip net.IP) *mockPeer {
    40  	if ip == nil {
    41  		ip = net.IP{127, 0, 0, 1}
    42  	}
    43  	nodeKey := NodeKey{PrivKey: ed25519.GenPrivKey()}
    44  	return &mockPeer{
    45  		ip: ip,
    46  		id: nodeKey.ID(),
    47  	}
    48  }
    49  
    50  func TestPeerSetAddRemoveOne(t *testing.T) {
    51  	t.Parallel()
    52  
    53  	peerSet := NewPeerSet()
    54  
    55  	var peerList []Peer
    56  	for i := 0; i < 5; i++ {
    57  		p := newMockPeer(net.IP{127, 0, 0, byte(i)})
    58  		if err := peerSet.Add(p); err != nil {
    59  			t.Error(err)
    60  		}
    61  		peerList = append(peerList, p)
    62  	}
    63  
    64  	n := len(peerList)
    65  	// 1. Test removing from the front
    66  	for i, peerAtFront := range peerList {
    67  		removed := peerSet.Remove(peerAtFront)
    68  		assert.True(t, removed)
    69  		wantSize := n - i - 1
    70  		for j := 0; j < 2; j++ {
    71  			assert.Equal(t, false, peerSet.Has(peerAtFront.ID()), "#%d Run #%d: failed to remove peer", i, j)
    72  			assert.Equal(t, wantSize, peerSet.Size(), "#%d Run #%d: failed to remove peer and decrement size", i, j)
    73  			// Test the route of removing the now non-existent element
    74  			removed := peerSet.Remove(peerAtFront)
    75  			assert.False(t, removed)
    76  		}
    77  	}
    78  
    79  	// 2. Next we are testing removing the peer at the end
    80  	// a) Replenish the peerSet
    81  	for _, peer := range peerList {
    82  		if err := peerSet.Add(peer); err != nil {
    83  			t.Error(err)
    84  		}
    85  	}
    86  
    87  	// b) In reverse, remove each element
    88  	for i := n - 1; i >= 0; i-- {
    89  		peerAtEnd := peerList[i]
    90  		removed := peerSet.Remove(peerAtEnd)
    91  		assert.True(t, removed)
    92  		assert.Equal(t, false, peerSet.Has(peerAtEnd.ID()), "#%d: failed to remove item at end", i)
    93  		assert.Equal(t, i, peerSet.Size(), "#%d: differing sizes after peerSet.Remove(atEndPeer)", i)
    94  	}
    95  }
    96  
    97  func TestPeerSetAddRemoveMany(t *testing.T) {
    98  	t.Parallel()
    99  	peerSet := NewPeerSet()
   100  
   101  	peers := []Peer{}
   102  	N := 100
   103  	for i := 0; i < N; i++ {
   104  		peer := newMockPeer(net.IP{127, 0, 0, byte(i)})
   105  		if err := peerSet.Add(peer); err != nil {
   106  			t.Errorf("failed to add new peer")
   107  		}
   108  		if peerSet.Size() != i+1 {
   109  			t.Errorf("failed to add new peer and increment size")
   110  		}
   111  		peers = append(peers, peer)
   112  	}
   113  
   114  	for i, peer := range peers {
   115  		removed := peerSet.Remove(peer)
   116  		assert.True(t, removed)
   117  		if peerSet.Has(peer.ID()) {
   118  			t.Errorf("failed to remove peer")
   119  		}
   120  		if peerSet.Size() != len(peers)-i-1 {
   121  			t.Errorf("failed to remove peer and decrement size")
   122  		}
   123  	}
   124  }
   125  
   126  func TestPeerSetAddDuplicate(t *testing.T) {
   127  	t.Parallel()
   128  	peerSet := NewPeerSet()
   129  	peer := newMockPeer(nil)
   130  
   131  	n := 20
   132  	errsChan := make(chan error)
   133  	// Add the same asynchronously to test the
   134  	// concurrent guarantees of our APIs, and
   135  	// our expectation in the end is that only
   136  	// one addition succeeded, but the rest are
   137  	// instances of ErrSwitchDuplicatePeer.
   138  	for i := 0; i < n; i++ {
   139  		go func() {
   140  			errsChan <- peerSet.Add(peer)
   141  		}()
   142  	}
   143  
   144  	// Now collect and tally the results
   145  	errsTally := make(map[string]int)
   146  	for i := 0; i < n; i++ {
   147  		err := <-errsChan
   148  
   149  		switch err.(type) {
   150  		case ErrSwitchDuplicatePeerID:
   151  			errsTally["duplicateID"]++
   152  		default:
   153  			errsTally["other"]++
   154  		}
   155  	}
   156  
   157  	// Our next procedure is to ensure that only one addition
   158  	// succeeded and that the rest are each ErrSwitchDuplicatePeer.
   159  	wantErrCount, gotErrCount := n-1, errsTally["duplicateID"]
   160  	assert.Equal(t, wantErrCount, gotErrCount, "invalid ErrSwitchDuplicatePeer count")
   161  
   162  	wantNilErrCount, gotNilErrCount := 1, errsTally["other"]
   163  	assert.Equal(t, wantNilErrCount, gotNilErrCount, "invalid nil errCount")
   164  }
   165  
   166  func TestPeerSetGet(t *testing.T) {
   167  	t.Parallel()
   168  
   169  	var (
   170  		peerSet = NewPeerSet()
   171  		peer    = newMockPeer(nil)
   172  	)
   173  
   174  	assert.Nil(t, peerSet.Get(peer.ID()), "expecting a nil lookup, before .Add")
   175  
   176  	if err := peerSet.Add(peer); err != nil {
   177  		t.Fatalf("Failed to add new peer: %v", err)
   178  	}
   179  
   180  	var wg sync.WaitGroup
   181  	for i := 0; i < 10; i++ {
   182  		// Add them asynchronously to test the
   183  		// concurrent guarantees of our APIs.
   184  		wg.Add(1)
   185  		go func(i int) {
   186  			defer wg.Done()
   187  			have, want := peerSet.Get(peer.ID()), peer
   188  			assert.Equal(t, have, want, "%d: have %v, want %v", i, have, want)
   189  		}(i)
   190  	}
   191  	wg.Wait()
   192  }