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.

182 lines
3.6 KiB

7 years ago
7 years ago
9 years ago
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package blockchain
  2. import (
  3. "testing"
  4. "time"
  5. cmn "github.com/tendermint/tendermint/libs/common"
  6. "github.com/tendermint/tendermint/libs/log"
  7. "github.com/tendermint/tendermint/p2p"
  8. "github.com/tendermint/tendermint/types"
  9. )
  10. func init() {
  11. peerTimeout = 2 * time.Second
  12. }
  13. type testPeer struct {
  14. id p2p.ID
  15. height int64
  16. inputChan chan inputData //make sure each peer's data is sequential
  17. }
  18. type inputData struct {
  19. t *testing.T
  20. pool *BlockPool
  21. request BlockRequest
  22. }
  23. func (p testPeer) runInputRoutine() {
  24. go func() {
  25. for input := range p.inputChan {
  26. p.simulateInput(input)
  27. }
  28. }()
  29. }
  30. // Request desired, pretend like we got the block immediately.
  31. func (p testPeer) simulateInput(input inputData) {
  32. block := &types.Block{Header: types.Header{Height: input.request.Height}}
  33. input.pool.AddBlock(input.request.PeerID, block, 123)
  34. input.t.Logf("Added block from peer %v (height: %v)", input.request.PeerID, input.request.Height)
  35. }
  36. type testPeers map[p2p.ID]testPeer
  37. func (ps testPeers) start() {
  38. for _, v := range ps {
  39. v.runInputRoutine()
  40. }
  41. }
  42. func (ps testPeers) stop() {
  43. for _, v := range ps {
  44. close(v.inputChan)
  45. }
  46. }
  47. func makePeers(numPeers int, minHeight, maxHeight int64) testPeers {
  48. peers := make(testPeers, numPeers)
  49. for i := 0; i < numPeers; i++ {
  50. peerID := p2p.ID(cmn.RandStr(12))
  51. height := minHeight + cmn.RandInt63n(maxHeight-minHeight)
  52. peers[peerID] = testPeer{peerID, height, make(chan inputData, 10)}
  53. }
  54. return peers
  55. }
  56. func TestBasic(t *testing.T) {
  57. start := int64(42)
  58. peers := makePeers(10, start+1, 1000)
  59. errorsCh := make(chan peerError, 1000)
  60. requestsCh := make(chan BlockRequest, 1000)
  61. pool := NewBlockPool(start, requestsCh, errorsCh)
  62. pool.SetLogger(log.TestingLogger())
  63. err := pool.Start()
  64. if err != nil {
  65. t.Error(err)
  66. }
  67. defer pool.Stop()
  68. peers.start()
  69. defer peers.stop()
  70. // Introduce each peer.
  71. go func() {
  72. for _, peer := range peers {
  73. pool.SetPeerHeight(peer.id, peer.height)
  74. }
  75. }()
  76. // Start a goroutine to pull blocks
  77. go func() {
  78. for {
  79. if !pool.IsRunning() {
  80. return
  81. }
  82. first, second := pool.PeekTwoBlocks()
  83. if first != nil && second != nil {
  84. pool.PopRequest()
  85. } else {
  86. time.Sleep(1 * time.Second)
  87. }
  88. }
  89. }()
  90. // Pull from channels
  91. for {
  92. select {
  93. case err := <-errorsCh:
  94. t.Error(err)
  95. case request := <-requestsCh:
  96. t.Logf("Pulled new BlockRequest %v", request)
  97. if request.Height == 300 {
  98. return // Done!
  99. }
  100. peers[request.PeerID].inputChan <- inputData{t, pool, request}
  101. }
  102. }
  103. }
  104. func TestTimeout(t *testing.T) {
  105. start := int64(42)
  106. peers := makePeers(10, start+1, 1000)
  107. errorsCh := make(chan peerError, 1000)
  108. requestsCh := make(chan BlockRequest, 1000)
  109. pool := NewBlockPool(start, requestsCh, errorsCh)
  110. pool.SetLogger(log.TestingLogger())
  111. err := pool.Start()
  112. if err != nil {
  113. t.Error(err)
  114. }
  115. defer pool.Stop()
  116. for _, peer := range peers {
  117. t.Logf("Peer %v", peer.id)
  118. }
  119. // Introduce each peer.
  120. go func() {
  121. for _, peer := range peers {
  122. pool.SetPeerHeight(peer.id, peer.height)
  123. }
  124. }()
  125. // Start a goroutine to pull blocks
  126. go func() {
  127. for {
  128. if !pool.IsRunning() {
  129. return
  130. }
  131. first, second := pool.PeekTwoBlocks()
  132. if first != nil && second != nil {
  133. pool.PopRequest()
  134. } else {
  135. time.Sleep(1 * time.Second)
  136. }
  137. }
  138. }()
  139. // Pull from channels
  140. counter := 0
  141. timedOut := map[p2p.ID]struct{}{}
  142. for {
  143. select {
  144. case err := <-errorsCh:
  145. t.Log(err)
  146. // consider error to be always timeout here
  147. if _, ok := timedOut[err.peerID]; !ok {
  148. counter++
  149. if counter == len(peers) {
  150. return // Done!
  151. }
  152. }
  153. case request := <-requestsCh:
  154. t.Logf("Pulled new BlockRequest %+v", request)
  155. }
  156. }
  157. }