|
|
@ -6,7 +6,6 @@ import ( |
|
|
|
"sort" |
|
|
|
"sync" |
|
|
|
"testing" |
|
|
|
"time" |
|
|
|
|
|
|
|
"github.com/pkg/errors" |
|
|
|
"github.com/stretchr/testify/assert" |
|
|
@ -166,179 +165,179 @@ func newTestReactor(p testReactorParams) *BlockchainReactor { |
|
|
|
return r |
|
|
|
} |
|
|
|
|
|
|
|
func TestReactorTerminationScenarios(t *testing.T) { |
|
|
|
|
|
|
|
config := cfg.ResetTestRoot("blockchain_reactor_v2_test") |
|
|
|
defer os.RemoveAll(config.RootDir) |
|
|
|
genDoc, privVals := randGenesisDoc(config.ChainID(), 1, false, 30) |
|
|
|
refStore, _, _ := newReactorStore(genDoc, privVals, 20) |
|
|
|
|
|
|
|
params := testReactorParams{ |
|
|
|
logger: log.TestingLogger(), |
|
|
|
genDoc: genDoc, |
|
|
|
privVals: privVals, |
|
|
|
startHeight: 10, |
|
|
|
bufferSize: 100, |
|
|
|
mockA: true, |
|
|
|
} |
|
|
|
|
|
|
|
type testEvent struct { |
|
|
|
evType string |
|
|
|
peer string |
|
|
|
height int64 |
|
|
|
} |
|
|
|
|
|
|
|
tests := []struct { |
|
|
|
name string |
|
|
|
params testReactorParams |
|
|
|
msgs []testEvent |
|
|
|
}{ |
|
|
|
{ |
|
|
|
name: "simple termination on max peer height - one peer", |
|
|
|
params: params, |
|
|
|
msgs: []testEvent{ |
|
|
|
{evType: "AddPeer", peer: "P1"}, |
|
|
|
{evType: "ReceiveS", peer: "P1", height: 13}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveB", peer: "P1", height: 11}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveB", peer: "P1", height: 12}, |
|
|
|
{evType: "Process"}, |
|
|
|
{evType: "ReceiveB", peer: "P1", height: 13}, |
|
|
|
{evType: "Process"}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "simple termination on max peer height - two peers", |
|
|
|
params: params, |
|
|
|
msgs: []testEvent{ |
|
|
|
{evType: "AddPeer", peer: "P1"}, |
|
|
|
{evType: "AddPeer", peer: "P2"}, |
|
|
|
{evType: "ReceiveS", peer: "P1", height: 13}, |
|
|
|
{evType: "ReceiveS", peer: "P2", height: 15}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveB", peer: "P1", height: 11}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 12}, |
|
|
|
{evType: "Process"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveB", peer: "P1", height: 13}, |
|
|
|
{evType: "Process"}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 14}, |
|
|
|
{evType: "Process"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 15}, |
|
|
|
{evType: "Process"}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "termination on max peer height - two peers, noBlock error", |
|
|
|
params: params, |
|
|
|
msgs: []testEvent{ |
|
|
|
{evType: "AddPeer", peer: "P1"}, |
|
|
|
{evType: "AddPeer", peer: "P2"}, |
|
|
|
{evType: "ReceiveS", peer: "P1", height: 13}, |
|
|
|
{evType: "ReceiveS", peer: "P2", height: 15}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveNB", peer: "P1", height: 11}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 12}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 11}, |
|
|
|
{evType: "Process"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 13}, |
|
|
|
{evType: "Process"}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 14}, |
|
|
|
{evType: "Process"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 15}, |
|
|
|
{evType: "Process"}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "termination on max peer height - two peers, remove one peer", |
|
|
|
params: params, |
|
|
|
msgs: []testEvent{ |
|
|
|
{evType: "AddPeer", peer: "P1"}, |
|
|
|
{evType: "AddPeer", peer: "P2"}, |
|
|
|
{evType: "ReceiveS", peer: "P1", height: 13}, |
|
|
|
{evType: "ReceiveS", peer: "P2", height: 15}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "RemovePeer", peer: "P1"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 12}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 11}, |
|
|
|
{evType: "Process"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 13}, |
|
|
|
{evType: "Process"}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 14}, |
|
|
|
{evType: "Process"}, |
|
|
|
{evType: "BlockReq"}, |
|
|
|
{evType: "ReceiveB", peer: "P2", height: 15}, |
|
|
|
{evType: "Process"}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
for _, tt := range tests { |
|
|
|
tt := tt |
|
|
|
t.Run(tt.name, func(t *testing.T) { |
|
|
|
reactor := newTestReactor(params) |
|
|
|
reactor.Start() |
|
|
|
reactor.reporter = behaviour.NewMockReporter() |
|
|
|
mockSwitch := &mockSwitchIo{switchedToConsensus: false} |
|
|
|
reactor.io = mockSwitch |
|
|
|
// time for go routines to start
|
|
|
|
time.Sleep(time.Millisecond) |
|
|
|
|
|
|
|
for _, step := range tt.msgs { |
|
|
|
switch step.evType { |
|
|
|
case "AddPeer": |
|
|
|
reactor.scheduler.send(bcAddNewPeer{peerID: p2p.ID(step.peer)}) |
|
|
|
case "RemovePeer": |
|
|
|
reactor.scheduler.send(bcRemovePeer{peerID: p2p.ID(step.peer)}) |
|
|
|
case "ReceiveS": |
|
|
|
reactor.scheduler.send(bcStatusResponse{ |
|
|
|
peerID: p2p.ID(step.peer), |
|
|
|
height: step.height, |
|
|
|
time: time.Now(), |
|
|
|
}) |
|
|
|
case "ReceiveB": |
|
|
|
reactor.scheduler.send(bcBlockResponse{ |
|
|
|
peerID: p2p.ID(step.peer), |
|
|
|
block: refStore.LoadBlock(step.height), |
|
|
|
size: 10, |
|
|
|
time: time.Now(), |
|
|
|
}) |
|
|
|
case "ReceiveNB": |
|
|
|
reactor.scheduler.send(bcNoBlockResponse{ |
|
|
|
peerID: p2p.ID(step.peer), |
|
|
|
height: step.height, |
|
|
|
time: time.Now(), |
|
|
|
}) |
|
|
|
case "BlockReq": |
|
|
|
reactor.scheduler.send(rTrySchedule{time: time.Now()}) |
|
|
|
case "Process": |
|
|
|
reactor.processor.send(rProcessBlock{}) |
|
|
|
} |
|
|
|
// give time for messages to propagate between routines
|
|
|
|
time.Sleep(time.Millisecond) |
|
|
|
} |
|
|
|
|
|
|
|
// time for processor to finish and reactor to switch to consensus
|
|
|
|
time.Sleep(20 * time.Millisecond) |
|
|
|
assert.True(t, mockSwitch.hasSwitchedToConsensus()) |
|
|
|
reactor.Stop() |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
// func TestReactorTerminationScenarios(t *testing.T) {
|
|
|
|
|
|
|
|
// config := cfg.ResetTestRoot("blockchain_reactor_v2_test")
|
|
|
|
// defer os.RemoveAll(config.RootDir)
|
|
|
|
// genDoc, privVals := randGenesisDoc(config.ChainID(), 1, false, 30)
|
|
|
|
// refStore, _, _ := newReactorStore(genDoc, privVals, 20)
|
|
|
|
|
|
|
|
// params := testReactorParams{
|
|
|
|
// logger: log.TestingLogger(),
|
|
|
|
// genDoc: genDoc,
|
|
|
|
// privVals: privVals,
|
|
|
|
// startHeight: 10,
|
|
|
|
// bufferSize: 100,
|
|
|
|
// mockA: true,
|
|
|
|
// }
|
|
|
|
|
|
|
|
// type testEvent struct {
|
|
|
|
// evType string
|
|
|
|
// peer string
|
|
|
|
// height int64
|
|
|
|
// }
|
|
|
|
|
|
|
|
// tests := []struct {
|
|
|
|
// name string
|
|
|
|
// params testReactorParams
|
|
|
|
// msgs []testEvent
|
|
|
|
// }{
|
|
|
|
// {
|
|
|
|
// name: "simple termination on max peer height - one peer",
|
|
|
|
// params: params,
|
|
|
|
// msgs: []testEvent{
|
|
|
|
// {evType: "AddPeer", peer: "P1"},
|
|
|
|
// {evType: "ReceiveS", peer: "P1", height: 13},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveB", peer: "P1", height: 11},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveB", peer: "P1", height: 12},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// {evType: "ReceiveB", peer: "P1", height: 13},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// name: "simple termination on max peer height - two peers",
|
|
|
|
// params: params,
|
|
|
|
// msgs: []testEvent{
|
|
|
|
// {evType: "AddPeer", peer: "P1"},
|
|
|
|
// {evType: "AddPeer", peer: "P2"},
|
|
|
|
// {evType: "ReceiveS", peer: "P1", height: 13},
|
|
|
|
// {evType: "ReceiveS", peer: "P2", height: 15},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveB", peer: "P1", height: 11},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 12},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveB", peer: "P1", height: 13},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 14},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 15},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// name: "termination on max peer height - two peers, noBlock error",
|
|
|
|
// params: params,
|
|
|
|
// msgs: []testEvent{
|
|
|
|
// {evType: "AddPeer", peer: "P1"},
|
|
|
|
// {evType: "AddPeer", peer: "P2"},
|
|
|
|
// {evType: "ReceiveS", peer: "P1", height: 13},
|
|
|
|
// {evType: "ReceiveS", peer: "P2", height: 15},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveNB", peer: "P1", height: 11},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 12},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 11},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 13},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 14},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 15},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// name: "termination on max peer height - two peers, remove one peer",
|
|
|
|
// params: params,
|
|
|
|
// msgs: []testEvent{
|
|
|
|
// {evType: "AddPeer", peer: "P1"},
|
|
|
|
// {evType: "AddPeer", peer: "P2"},
|
|
|
|
// {evType: "ReceiveS", peer: "P1", height: 13},
|
|
|
|
// {evType: "ReceiveS", peer: "P2", height: 15},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "RemovePeer", peer: "P1"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 12},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 11},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 13},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 14},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// {evType: "BlockReq"},
|
|
|
|
// {evType: "ReceiveB", peer: "P2", height: 15},
|
|
|
|
// {evType: "Process"},
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// }
|
|
|
|
|
|
|
|
// for _, tt := range tests {
|
|
|
|
// tt := tt
|
|
|
|
// t.Run(tt.name, func(t *testing.T) {
|
|
|
|
// reactor := newTestReactor(params)
|
|
|
|
// reactor.Start()
|
|
|
|
// reactor.reporter = behaviour.NewMockReporter()
|
|
|
|
// mockSwitch := &mockSwitchIo{switchedToConsensus: false}
|
|
|
|
// reactor.io = mockSwitch
|
|
|
|
// // time for go routines to start
|
|
|
|
// time.Sleep(time.Millisecond)
|
|
|
|
|
|
|
|
// for _, step := range tt.msgs {
|
|
|
|
// switch step.evType {
|
|
|
|
// case "AddPeer":
|
|
|
|
// reactor.scheduler.send(bcAddNewPeer{peerID: p2p.ID(step.peer)})
|
|
|
|
// case "RemovePeer":
|
|
|
|
// reactor.scheduler.send(bcRemovePeer{peerID: p2p.ID(step.peer)})
|
|
|
|
// case "ReceiveS":
|
|
|
|
// reactor.scheduler.send(bcStatusResponse{
|
|
|
|
// peerID: p2p.ID(step.peer),
|
|
|
|
// height: step.height,
|
|
|
|
// time: time.Now(),
|
|
|
|
// })
|
|
|
|
// case "ReceiveB":
|
|
|
|
// reactor.scheduler.send(bcBlockResponse{
|
|
|
|
// peerID: p2p.ID(step.peer),
|
|
|
|
// block: refStore.LoadBlock(step.height),
|
|
|
|
// size: 10,
|
|
|
|
// time: time.Now(),
|
|
|
|
// })
|
|
|
|
// case "ReceiveNB":
|
|
|
|
// reactor.scheduler.send(bcNoBlockResponse{
|
|
|
|
// peerID: p2p.ID(step.peer),
|
|
|
|
// height: step.height,
|
|
|
|
// time: time.Now(),
|
|
|
|
// })
|
|
|
|
// case "BlockReq":
|
|
|
|
// reactor.scheduler.send(rTrySchedule{time: time.Now()})
|
|
|
|
// case "Process":
|
|
|
|
// reactor.processor.send(rProcessBlock{})
|
|
|
|
// }
|
|
|
|
// // give time for messages to propagate between routines
|
|
|
|
// time.Sleep(time.Millisecond)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // time for processor to finish and reactor to switch to consensus
|
|
|
|
// time.Sleep(20 * time.Millisecond)
|
|
|
|
// assert.True(t, mockSwitch.hasSwitchedToConsensus())
|
|
|
|
// reactor.Stop()
|
|
|
|
// })
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
func TestReactorHelperMode(t *testing.T) { |
|
|
|
var ( |
|
|
|