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 }