rearrange common_test.go; EnsureDir for privVal

This commit is contained in:
Ethan Buchman
2017-01-12 12:37:24 -05:00
parent 1d091bafe9
commit 0525e8ed5c

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"path"
"sort" "sort"
"sync" "sync"
"testing" "testing"
@ -28,6 +29,9 @@ import (
var config cfg.Config // NOTE: must be reset for each _test.go file var config cfg.Config // NOTE: must be reset for each _test.go file
var ensureTimeout = time.Duration(2) var ensureTimeout = time.Duration(2)
//-------------------------------------------------------------------------------
// validator stub (a dummy consensus peer we control)
type validatorStub struct { type validatorStub struct {
Index int // Validator index. NOTE: we don't assume validator set changes. Index int // Validator index. NOTE: we don't assume validator set changes.
Height int Height int
@ -57,9 +61,6 @@ func (vs *validatorStub) signVote(voteType byte, hash []byte, header types.PartS
return vote, err return vote, err
} }
//-------------------------------------------------------------------------------
// Convenience functions
// Sign vote for type/hash/header // Sign vote for type/hash/header
func signVote(vs *validatorStub, voteType byte, hash []byte, header types.PartSetHeader) *types.Vote { func signVote(vs *validatorStub, voteType byte, hash []byte, header types.PartSetHeader) *types.Vote {
v, err := vs.signVote(voteType, hash, header) v, err := vs.signVote(voteType, hash, header)
@ -69,6 +70,34 @@ func signVote(vs *validatorStub, voteType byte, hash []byte, header types.PartSe
return v return v
} }
func signVotes(voteType byte, hash []byte, header types.PartSetHeader, vss ...*validatorStub) []*types.Vote {
votes := make([]*types.Vote, len(vss))
for i, vs := range vss {
votes[i] = signVote(vs, voteType, hash, header)
}
return votes
}
func incrementHeight(vss ...*validatorStub) {
for _, vs := range vss {
vs.Height += 1
}
}
func incrementRound(vss ...*validatorStub) {
for _, vs := range vss {
vs.Round += 1
}
}
//-------------------------------------------------------------------------------
// Functions for transitioning the consensus state
func startTestRound(cs *ConsensusState, height, round int) {
cs.enterNewRound(height, round)
cs.startRoutines(0)
}
// Create proposal block from cs1 but sign it with vs // Create proposal block from cs1 but sign it with vs
func decideProposal(cs1 *ConsensusState, vs *validatorStub, height, round int) (proposal *types.Proposal, block *types.Block) { func decideProposal(cs1 *ConsensusState, vs *validatorStub, height, round int) (proposal *types.Proposal, block *types.Block) {
block, blockParts := cs1.createProposalBlock() block, blockParts := cs1.createProposalBlock()
@ -91,41 +120,11 @@ func addVotes(to *ConsensusState, votes ...*types.Vote) {
} }
} }
func signVotes(voteType byte, hash []byte, header types.PartSetHeader, vss ...*validatorStub) []*types.Vote {
votes := make([]*types.Vote, len(vss))
for i, vs := range vss {
votes[i] = signVote(vs, voteType, hash, header)
}
return votes
}
func signAddVotes(to *ConsensusState, voteType byte, hash []byte, header types.PartSetHeader, vss ...*validatorStub) { func signAddVotes(to *ConsensusState, voteType byte, hash []byte, header types.PartSetHeader, vss ...*validatorStub) {
votes := signVotes(voteType, hash, header, vss...) votes := signVotes(voteType, hash, header, vss...)
addVotes(to, votes...) addVotes(to, votes...)
} }
func ensureNoNewStep(stepCh chan interface{}) {
timeout := time.NewTicker(ensureTimeout * time.Second)
select {
case <-timeout.C:
break
case <-stepCh:
panic("We should be stuck waiting for more votes, not moving to the next step")
}
}
func incrementHeight(vss ...*validatorStub) {
for _, vs := range vss {
vs.Height += 1
}
}
func incrementRound(vss ...*validatorStub) {
for _, vs := range vss {
vs.Round += 1
}
}
func validatePrevote(t *testing.T, cs *ConsensusState, round int, privVal *validatorStub, blockHash []byte) { func validatePrevote(t *testing.T, cs *ConsensusState, round int, privVal *validatorStub, blockHash []byte) {
prevotes := cs.Votes.Prevotes(round) prevotes := cs.Votes.Prevotes(round)
var vote *types.Vote var vote *types.Vote
@ -192,24 +191,39 @@ func validatePrevoteAndPrecommit(t *testing.T, cs *ConsensusState, thisRound, lo
cs.mtx.Unlock() cs.mtx.Unlock()
} }
func fixedConsensusState() *ConsensusState { // genesis
stateDB := dbm.NewMemDB() func subscribeToVoter(cs *ConsensusState, addr []byte) chan interface{} {
state := sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file")) voteCh0 := subscribeToEvent(cs.evsw, "tester", types.EventStringVote(), 1)
privValidatorFile := config.GetString("priv_validator_file") voteCh := make(chan interface{})
privValidator := types.LoadOrGenPrivValidator(privValidatorFile) go func() {
privValidator.Reset() for {
cs := newConsensusState(state, privValidator, counter.NewCounterApplication(true)) v := <-voteCh0
return cs vote := v.(types.EventDataVote)
// we only fire for our own votes
if bytes.Equal(addr, vote.Vote.ValidatorAddress) {
voteCh <- v
}
}
}()
return voteCh
} }
func fixedConsensusStateDummy() *ConsensusState { func readVotes(ch chan interface{}, reads int) chan struct{} {
stateDB := dbm.NewMemDB() wg := make(chan struct{})
state := sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file")) go func() {
privValidatorFile := config.GetString("priv_validator_file") for i := 0; i < reads; i++ {
privValidator := types.LoadOrGenPrivValidator(privValidatorFile) <-ch // read the precommit event
privValidator.Reset() }
cs := newConsensusState(state, privValidator, dummy.NewDummyApplication()) close(wg)
return cs }()
return wg
}
//-------------------------------------------------------------------------------
// consensus states
func newConsensusState(state *sm.State, pv *types.PrivValidator, app tmsp.Application) *ConsensusState {
return newConsensusStateWithConfig(config, state, pv, app)
} }
func newConsensusStateWithConfig(thisConfig cfg.Config, state *sm.State, pv *types.PrivValidator, app tmsp.Application) *ConsensusState { func newConsensusStateWithConfig(thisConfig cfg.Config, state *sm.State, pv *types.PrivValidator, app tmsp.Application) *ConsensusState {
@ -235,8 +249,28 @@ func newConsensusStateWithConfig(thisConfig cfg.Config, state *sm.State, pv *typ
return cs return cs
} }
func newConsensusState(state *sm.State, pv *types.PrivValidator, app tmsp.Application) *ConsensusState { func loadPrivValidator(config cfg.Config) *types.PrivValidator {
return newConsensusStateWithConfig(config, state, pv, app) privValidatorFile := config.GetString("priv_validator_file")
EnsureDir(path.Dir(privValidatorFile), 0700)
privValidator := types.LoadOrGenPrivValidator(privValidatorFile)
privValidator.Reset()
return privValidator
}
func fixedConsensusState() *ConsensusState {
stateDB := dbm.NewMemDB()
state := sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
privValidator := loadPrivValidator(config)
cs := newConsensusState(state, privValidator, counter.NewCounterApplication(true))
return cs
}
func fixedConsensusStateDummy() *ConsensusState {
stateDB := dbm.NewMemDB()
state := sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
privValidator := loadPrivValidator(config)
cs := newConsensusState(state, privValidator, dummy.NewDummyApplication())
return cs
} }
func randConsensusState(nValidators int) (*ConsensusState, []*validatorStub) { func randConsensusState(nValidators int) (*ConsensusState, []*validatorStub) {
@ -256,6 +290,21 @@ func randConsensusState(nValidators int) (*ConsensusState, []*validatorStub) {
return cs, vss return cs, vss
} }
//-------------------------------------------------------------------------------
func ensureNoNewStep(stepCh chan interface{}) {
timeout := time.NewTicker(ensureTimeout * time.Second)
select {
case <-timeout.C:
break
case <-stepCh:
panic("We should be stuck waiting for more votes, not moving to the next step")
}
}
//-------------------------------------------------------------------------------
// consensus nets
func randConsensusNet(nValidators int, testName string, tickerFunc func() TimeoutTicker, appFunc func() tmsp.Application) []*ConsensusState { func randConsensusNet(nValidators int, testName string, tickerFunc func() TimeoutTicker, appFunc func() tmsp.Application) []*ConsensusState {
genDoc, privVals := randGenesisDoc(nValidators, false, 10) genDoc, privVals := randGenesisDoc(nValidators, false, 10)
css := make([]*ConsensusState, nValidators) css := make([]*ConsensusState, nValidators)
@ -296,40 +345,18 @@ func randConsensusNetWithPeers(nValidators, nPeers int, testName string, tickerF
return css return css
} }
func subscribeToVoter(cs *ConsensusState, addr []byte) chan interface{} { func getSwitchIndex(switches []*p2p.Switch, peer *p2p.Peer) int {
voteCh0 := subscribeToEvent(cs.evsw, "tester", types.EventStringVote(), 1) for i, s := range switches {
voteCh := make(chan interface{}) if bytes.Equal(peer.NodeInfo.PubKey.Address(), s.NodeInfo().PubKey.Address()) {
go func() { return i
for {
v := <-voteCh0
vote := v.(types.EventDataVote)
// we only fire for our own votes
if bytes.Equal(addr, vote.Vote.ValidatorAddress) {
voteCh <- v
}
} }
}() }
return voteCh panic("didnt find peer in switches")
return -1
} }
func readVotes(ch chan interface{}, reads int) chan struct{} { //-------------------------------------------------------------------------------
wg := make(chan struct{}) // genesis
go func() {
for i := 0; i < reads; i++ {
<-ch // read the precommit event
}
close(wg)
}()
return wg
}
func randGenesisState(numValidators int, randPower bool, minPower int64) (*sm.State, []*types.PrivValidator) {
genDoc, privValidators := randGenesisDoc(numValidators, randPower, minPower)
db := dbm.NewMemDB()
s0 := sm.MakeGenesisState(db, genDoc)
s0.Save()
return s0, privValidators
}
func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.GenesisDoc, []*types.PrivValidator) { func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.GenesisDoc, []*types.PrivValidator) {
validators := make([]types.GenesisValidator, numValidators) validators := make([]types.GenesisValidator, numValidators)
@ -348,28 +375,18 @@ func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.G
ChainID: config.GetString("chain_id"), ChainID: config.GetString("chain_id"),
Validators: validators, Validators: validators,
}, privValidators }, privValidators
} }
func startTestRound(cs *ConsensusState, height, round int) { func randGenesisState(numValidators int, randPower bool, minPower int64) (*sm.State, []*types.PrivValidator) {
cs.enterNewRound(height, round) genDoc, privValidators := randGenesisDoc(numValidators, randPower, minPower)
cs.startRoutines(0) db := dbm.NewMemDB()
} s0 := sm.MakeGenesisState(db, genDoc)
s0.Save()
//-------------------------------- return s0, privValidators
// reactor stuff
func getSwitchIndex(switches []*p2p.Switch, peer *p2p.Peer) int {
for i, s := range switches {
if bytes.Equal(peer.NodeInfo.PubKey.Address(), s.NodeInfo().PubKey.Address()) {
return i
}
}
panic("didnt find peer in switches")
return -1
} }
//------------------------------------ //------------------------------------
// mock ticker
func newMockTickerFunc(onlyOnce bool) func() TimeoutTicker { func newMockTickerFunc(onlyOnce bool) func() TimeoutTicker {
return func() TimeoutTicker { return func() TimeoutTicker {