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