You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
5.1 KiB

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