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.

173 lines
4.1 KiB

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