Browse Source

consensus: test reactor

pull/314/head
Ethan Buchman 8 years ago
parent
commit
f837252ff1
4 changed files with 97 additions and 3 deletions
  1. +1
    -1
      consensus/common.go
  2. +13
    -1
      consensus/common_test.go
  3. +82
    -0
      consensus/reactor_test.go
  4. +1
    -1
      consensus/state_test.go

+ 1
- 1
consensus/common.go View File

@ -6,7 +6,7 @@ import (
// NOTE: this is blocking // NOTE: this is blocking
func subscribeToEvent(evsw types.EventSwitch, receiver, eventID string, chanCap int) chan interface{} { func subscribeToEvent(evsw types.EventSwitch, receiver, eventID string, chanCap int) chan interface{} {
// listen for new round
// listen for event
ch := make(chan interface{}, chanCap) ch := make(chan interface{}, chanCap)
types.AddListenerForEvent(evsw, receiver, eventID, func(data types.TMEventData) { types.AddListenerForEvent(evsw, receiver, eventID, func(data types.TMEventData) {
ch <- data ch <- data


+ 13
- 1
consensus/common_test.go View File

@ -246,6 +246,18 @@ func randConsensusState(nValidators int) (*ConsensusState, []*validatorStub) {
return cs, vss return cs, vss
} }
func randConsensusNet(nValidators int) []*ConsensusState {
genDoc, privVals := randGenesisDoc(nValidators, false, 10)
css := make([]*ConsensusState, nValidators)
for i := 0; i < nValidators; i++ {
db := dbm.NewMemDB() // each state needs its own db
state := sm.MakeGenesisState(db, genDoc)
state.Save()
css[i] = newConsensusState(state, privVals[i], counter.NewCounterApplication(true))
}
return css
}
func subscribeToVoter(cs *ConsensusState, addr []byte) chan interface{} { func subscribeToVoter(cs *ConsensusState, addr []byte) chan interface{} {
voteCh0 := subscribeToEvent(cs.evsw, "tester", types.EventStringVote(), 1) voteCh0 := subscribeToEvent(cs.evsw, "tester", types.EventStringVote(), 1)
voteCh := make(chan interface{}) voteCh := make(chan interface{})
@ -274,8 +286,8 @@ func readVotes(ch chan interface{}, reads int) chan struct{} {
} }
func randGenesisState(numValidators int, randPower bool, minPower int64) (*sm.State, []*types.PrivValidator) { func randGenesisState(numValidators int, randPower bool, minPower int64) (*sm.State, []*types.PrivValidator) {
db := dbm.NewMemDB()
genDoc, privValidators := randGenesisDoc(numValidators, randPower, minPower) genDoc, privValidators := randGenesisDoc(numValidators, randPower, minPower)
db := dbm.NewMemDB()
s0 := sm.MakeGenesisState(db, genDoc) s0 := sm.MakeGenesisState(db, genDoc)
s0.Save() s0.Save()
return s0, privValidators return s0, privValidators


+ 82
- 0
consensus/reactor_test.go View File

@ -0,0 +1,82 @@
package consensus
import (
"net"
"sync"
"testing"
"time"
"github.com/tendermint/tendermint/config/tendermint_test"
. "github.com/tendermint/go-common"
dbm "github.com/tendermint/go-db"
"github.com/tendermint/go-events"
"github.com/tendermint/go-p2p"
bc "github.com/tendermint/tendermint/blockchain"
"github.com/tendermint/tendermint/types"
)
func init() {
config = tendermint_test.ResetConfig("consensus_reactor_test")
}
func resetConfigTimeouts() {
config.Set("log_level", "notice")
config.Set("timeout_propose", 2000)
// config.Set("timeout_propose_delta", 500)
// config.Set("timeout_prevote", 1000)
// config.Set("timeout_prevote_delta", 500)
// config.Set("timeout_precommit", 1000)
// config.Set("timeout_precommit_delta", 500)
// config.Set("timeout_commit", 1000)
}
func TestReactor(t *testing.T) {
resetConfigTimeouts()
N := 4
css := randConsensusNet(N)
reactors := make([]*ConsensusReactor, N)
eventChans := make([]chan interface{}, N)
for i := 0; i < N; i++ {
blockStoreDB := dbm.NewDB(Fmt("blockstore%d", i), config.GetString("db_backend"), config.GetString("db_dir"))
blockStore := bc.NewBlockStore(blockStoreDB)
reactors[i] = NewConsensusReactor(css[i], blockStore, false)
reactors[i].SetPrivValidator(css[i].privValidator)
eventSwitch := events.NewEventSwitch()
_, err := eventSwitch.Start()
if err != nil {
t.Fatalf("Failed to start switch: %v", err)
}
reactors[i].SetEventSwitch(eventSwitch)
eventChans[i] = subscribeToEvent(eventSwitch, "tester", types.EventStringNewBlock(), 1)
}
p2p.MakeConnectedSwitches(N, func(i int, s *p2p.Switch) *p2p.Switch {
s.AddReactor("CONSENSUS", reactors[i])
return s
}, net.Pipe)
// wait till everyone makes the first new block
wg := new(sync.WaitGroup)
wg.Add(N)
for i := 0; i < N; i++ {
go func(j int) {
<-eventChans[j]
wg.Done()
}(i)
}
done := make(chan struct{})
go func() {
wg.Wait()
close(done)
}()
tick := time.NewTicker(time.Second * 3)
select {
case <-done:
case <-tick.C:
t.Fatalf("Timed out waiting for all validators to commit first block")
}
}

+ 1
- 1
consensus/state_test.go View File

@ -30,7 +30,7 @@ x * TestBadProposal - 2 vals, bad proposal (bad block state hash), should prevot
FullRoundSuite FullRoundSuite
x * TestFullRound1 - 1 val, full successful round x * TestFullRound1 - 1 val, full successful round
x * TestFullRoundNil - 1 val, full round of nil x * TestFullRoundNil - 1 val, full round of nil
x * TestFullRound2 - 2 vals, both required for fuill round
x * TestFullRound2 - 2 vals, both required for full round
LockSuite LockSuite
x * TestLockNoPOL - 2 vals, 4 rounds. one val locked, precommits nil every round except first. x * TestLockNoPOL - 2 vals, 4 rounds. one val locked, precommits nil every round except first.
x * TestLockPOLRelock - 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka x * TestLockPOLRelock - 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka


Loading…
Cancel
Save