2015-03-22 19:00:08 -07:00
|
|
|
package blockchain
|
2015-03-22 12:46:53 -07:00
|
|
|
|
|
|
|
import (
|
|
|
|
"math/rand"
|
|
|
|
"testing"
|
2015-03-22 19:20:54 -07:00
|
|
|
"time"
|
2015-03-22 12:46:53 -07:00
|
|
|
|
2015-04-01 17:30:16 -07:00
|
|
|
"github.com/tendermint/tendermint/types"
|
2017-10-04 16:40:45 -04:00
|
|
|
cmn "github.com/tendermint/tmlibs/common"
|
2017-05-02 11:53:32 +04:00
|
|
|
"github.com/tendermint/tmlibs/log"
|
2015-03-22 12:46:53 -07:00
|
|
|
)
|
|
|
|
|
2016-02-29 16:15:23 -05:00
|
|
|
func init() {
|
|
|
|
peerTimeoutSeconds = time.Duration(2)
|
|
|
|
}
|
|
|
|
|
2015-03-22 12:46:53 -07:00
|
|
|
type testPeer struct {
|
|
|
|
id string
|
2015-06-25 20:28:34 -07:00
|
|
|
height int
|
2015-03-22 12:46:53 -07:00
|
|
|
}
|
|
|
|
|
2015-06-25 20:28:34 -07:00
|
|
|
func makePeers(numPeers int, minHeight, maxHeight int) map[string]testPeer {
|
2015-03-22 12:46:53 -07:00
|
|
|
peers := make(map[string]testPeer, numPeers)
|
|
|
|
for i := 0; i < numPeers; i++ {
|
2017-10-04 16:40:45 -04:00
|
|
|
peerID := cmn.RandStr(12)
|
2015-06-25 20:28:34 -07:00
|
|
|
height := minHeight + rand.Intn(maxHeight-minHeight)
|
2015-08-18 10:51:55 -07:00
|
|
|
peers[peerID] = testPeer{peerID, height}
|
2015-03-22 12:46:53 -07:00
|
|
|
}
|
|
|
|
return peers
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBasic(t *testing.T) {
|
2015-06-25 20:28:34 -07:00
|
|
|
start := 42
|
2015-09-09 21:44:48 -07:00
|
|
|
peers := makePeers(10, start+1, 1000)
|
2015-03-22 16:23:24 -07:00
|
|
|
timeoutsCh := make(chan string, 100)
|
|
|
|
requestsCh := make(chan BlockRequest, 100)
|
2015-03-24 11:02:30 -07:00
|
|
|
pool := NewBlockPool(start, requestsCh, timeoutsCh)
|
2017-05-02 11:53:32 +04:00
|
|
|
pool.SetLogger(log.TestingLogger())
|
2017-09-06 11:50:43 -04:00
|
|
|
|
|
|
|
_, err := pool.Start()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
2017-01-19 13:33:58 +04:00
|
|
|
defer pool.Stop()
|
2015-03-22 12:46:53 -07:00
|
|
|
|
|
|
|
// Introduce each peer.
|
|
|
|
go func() {
|
|
|
|
for _, peer := range peers {
|
2015-03-24 11:02:30 -07:00
|
|
|
pool.SetPeerHeight(peer.id, peer.height)
|
2015-03-22 12:46:53 -07:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2015-03-24 11:02:30 -07:00
|
|
|
// Start a goroutine to pull blocks
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
if !pool.IsRunning() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
first, second := pool.PeekTwoBlocks()
|
|
|
|
if first != nil && second != nil {
|
|
|
|
pool.PopRequest()
|
|
|
|
} else {
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
2015-03-22 12:46:53 -07:00
|
|
|
|
|
|
|
// Pull from channels
|
|
|
|
for {
|
|
|
|
select {
|
2015-08-18 10:51:55 -07:00
|
|
|
case peerID := <-timeoutsCh:
|
|
|
|
t.Errorf("timeout: %v", peerID)
|
2015-03-22 12:46:53 -07:00
|
|
|
case request := <-requestsCh:
|
2017-05-02 11:53:32 +04:00
|
|
|
t.Logf("Pulled new BlockRequest %v", request)
|
2015-03-24 11:02:30 -07:00
|
|
|
if request.Height == 300 {
|
|
|
|
return // Done!
|
|
|
|
}
|
|
|
|
// Request desired, pretend like we got the block immediately.
|
2015-03-22 12:46:53 -07:00
|
|
|
go func() {
|
2015-03-22 19:00:08 -07:00
|
|
|
block := &types.Block{Header: &types.Header{Height: request.Height}}
|
2015-08-18 10:51:55 -07:00
|
|
|
pool.AddBlock(request.PeerID, block, 123)
|
2017-05-02 11:53:32 +04:00
|
|
|
t.Logf("Added block from peer %v (height: %v)", request.PeerID, request.Height)
|
2015-03-22 12:46:53 -07:00
|
|
|
}()
|
|
|
|
}
|
|
|
|
}
|
2015-03-22 16:23:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTimeout(t *testing.T) {
|
2015-06-25 20:28:34 -07:00
|
|
|
start := 42
|
2015-09-09 21:44:48 -07:00
|
|
|
peers := makePeers(10, start+1, 1000)
|
2015-03-24 11:02:30 -07:00
|
|
|
timeoutsCh := make(chan string, 100)
|
|
|
|
requestsCh := make(chan BlockRequest, 100)
|
|
|
|
pool := NewBlockPool(start, requestsCh, timeoutsCh)
|
2017-05-02 11:53:32 +04:00
|
|
|
pool.SetLogger(log.TestingLogger())
|
2017-09-06 11:50:43 -04:00
|
|
|
_, err := pool.Start()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
2017-01-19 13:33:58 +04:00
|
|
|
defer pool.Stop()
|
2015-03-22 16:23:24 -07:00
|
|
|
|
2015-09-09 21:44:48 -07:00
|
|
|
for _, peer := range peers {
|
2017-05-12 17:40:57 +02:00
|
|
|
t.Logf("Peer %v", peer.id)
|
2015-09-09 21:44:48 -07:00
|
|
|
}
|
|
|
|
|
2015-03-22 16:23:24 -07:00
|
|
|
// Introduce each peer.
|
|
|
|
go func() {
|
|
|
|
for _, peer := range peers {
|
2015-03-24 11:02:30 -07:00
|
|
|
pool.SetPeerHeight(peer.id, peer.height)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Start a goroutine to pull blocks
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
if !pool.IsRunning() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
first, second := pool.PeekTwoBlocks()
|
|
|
|
if first != nil && second != nil {
|
|
|
|
pool.PopRequest()
|
|
|
|
} else {
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
}
|
2015-03-22 16:23:24 -07:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Pull from channels
|
2015-03-24 11:02:30 -07:00
|
|
|
counter := 0
|
|
|
|
timedOut := map[string]struct{}{}
|
2015-03-22 16:23:24 -07:00
|
|
|
for {
|
|
|
|
select {
|
2015-08-18 10:51:55 -07:00
|
|
|
case peerID := <-timeoutsCh:
|
2017-05-12 17:40:57 +02:00
|
|
|
t.Logf("Peer %v timeouted", peerID)
|
2015-08-18 10:51:55 -07:00
|
|
|
if _, ok := timedOut[peerID]; !ok {
|
2015-03-24 11:02:30 -07:00
|
|
|
counter++
|
|
|
|
if counter == len(peers) {
|
|
|
|
return // Done!
|
|
|
|
}
|
2015-03-22 16:23:24 -07:00
|
|
|
}
|
2015-03-24 11:02:30 -07:00
|
|
|
case request := <-requestsCh:
|
2017-05-12 17:40:57 +02:00
|
|
|
t.Logf("Pulled new BlockRequest %+v", request)
|
2015-03-22 16:23:24 -07:00
|
|
|
}
|
|
|
|
}
|
2015-03-22 12:46:53 -07:00
|
|
|
}
|