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.

172 lines
4.1 KiB

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