tendermint/consensus/state_test.go

209 lines
6.1 KiB
Go
Raw Normal View History

2014-10-18 01:42:33 -07:00
package consensus
import (
2014-12-17 01:37:13 -08:00
"bytes"
2014-10-18 01:42:33 -07:00
"testing"
2015-04-01 17:30:16 -07:00
"github.com/tendermint/tendermint/types"
2014-10-18 01:42:33 -07:00
)
func TestSetupRound(t *testing.T) {
cs, privValidators := randConsensusState()
2014-12-17 01:37:13 -08:00
val0 := privValidators[0]
// Add a vote, precommit, and commit by val0.
voteTypes := []byte{types.VoteTypePrevote, types.VoteTypePrecommit, types.VoteTypeCommit}
for _, voteType := range voteTypes {
vote := &types.Vote{Height: 1, Round: 0, Type: voteType} // nil vote
err := val0.SignVote(vote)
if err != nil {
t.Error("Error signing vote: %v", err)
}
2014-12-17 01:37:13 -08:00
cs.AddVote(val0.Address, vote)
}
// Ensure that vote appears in RoundState.
rs0 := cs.GetRoundState()
if vote := rs0.Prevotes.GetByAddress(val0.Address); vote == nil || vote.Type != types.VoteTypePrevote {
2014-10-21 01:18:46 -07:00
t.Errorf("Expected to find prevote but got %v", vote)
}
if vote := rs0.Precommits.GetByAddress(val0.Address); vote == nil || vote.Type != types.VoteTypePrecommit {
2014-10-21 01:18:46 -07:00
t.Errorf("Expected to find precommit but got %v", vote)
}
if vote := rs0.Commits.GetByAddress(val0.Address); vote == nil || vote.Type != types.VoteTypeCommit {
2014-10-21 01:18:46 -07:00
t.Errorf("Expected to find commit but got %v", vote)
}
// Setup round 1 (next round)
2014-10-30 03:32:09 -07:00
cs.SetupNewRound(1, 1)
<-cs.NewStepCh()
// Now the commit should be copied over to prevotes and precommits.
rs1 := cs.GetRoundState()
if vote := rs1.Prevotes.GetByAddress(val0.Address); vote == nil || vote.Type != types.VoteTypeCommit {
2014-10-21 01:18:46 -07:00
t.Errorf("Expected to find commit but got %v", vote)
}
if vote := rs1.Precommits.GetByAddress(val0.Address); vote == nil || vote.Type != types.VoteTypeCommit {
2014-10-21 01:18:46 -07:00
t.Errorf("Expected to find commit but got %v", vote)
}
if vote := rs1.Commits.GetByAddress(val0.Address); vote == nil || vote.Type != types.VoteTypeCommit {
2014-10-21 01:18:46 -07:00
t.Errorf("Expected to find commit but got %v", vote)
}
}
2014-10-21 01:18:46 -07:00
func TestRunActionProposeNoPrivValidator(t *testing.T) {
cs, _ := randConsensusState()
2014-10-21 01:18:46 -07:00
cs.RunActionPropose(1, 0)
2014-10-18 01:42:33 -07:00
rs := cs.GetRoundState()
if rs.Proposal != nil {
t.Error("Expected to make no proposal, since no privValidator")
2014-10-18 01:42:33 -07:00
}
}
2014-10-21 01:18:46 -07:00
func TestRunActionPropose(t *testing.T) {
cs, privValidators := randConsensusState()
2014-12-17 01:37:13 -08:00
val0 := privValidators[0]
cs.SetPrivValidator(val0)
2014-10-21 01:18:46 -07:00
cs.RunActionPropose(1, 0)
rs := cs.GetRoundState()
2014-10-26 13:26:27 -07:00
// Check that Proposal, ProposalBlock, ProposalBlockParts are set.
2014-10-21 01:18:46 -07:00
if rs.Proposal == nil {
t.Error("rs.Proposal should be set")
}
if rs.ProposalBlock == nil {
t.Error("rs.ProposalBlock should be set")
}
2014-10-26 13:26:27 -07:00
if rs.ProposalBlockParts.Total() == 0 {
t.Error("rs.ProposalBlockParts should be set")
2014-10-21 01:18:46 -07:00
}
}
2014-10-31 18:35:38 -07:00
func checkRoundState(t *testing.T, rs *RoundState,
height uint, round uint, step RoundStepType) {
2014-10-21 01:18:46 -07:00
if rs.Height != height {
2014-10-31 18:35:38 -07:00
t.Errorf("rs.Height should be %v, got %v", height, rs.Height)
2014-10-21 01:18:46 -07:00
}
if rs.Round != round {
2014-10-31 18:35:38 -07:00
t.Errorf("rs.Round should be %v, got %v", round, rs.Round)
2014-10-21 01:18:46 -07:00
}
if rs.Step != step {
2014-10-31 18:35:38 -07:00
t.Errorf("rs.Step should be %v, got %v", step, rs.Step)
2014-10-21 01:18:46 -07:00
}
}
func TestRunActionPrecommitCommitFinalize(t *testing.T) {
cs, privValidators := randConsensusState()
2014-12-17 01:37:13 -08:00
val0 := privValidators[0]
cs.SetPrivValidator(val0)
2014-10-21 01:18:46 -07:00
2014-10-30 03:32:09 -07:00
cs.RunActionPrecommit(1, 0)
<-cs.NewStepCh() // TODO: test this value too.
2014-12-17 01:37:13 -08:00
if cs.Precommits.GetByAddress(val0.Address) != nil {
t.Errorf("RunActionPrecommit should return nil without a proposal")
2014-10-21 01:18:46 -07:00
}
cs.RunActionPropose(1, 0)
2014-10-30 03:32:09 -07:00
<-cs.NewStepCh() // TODO: test this value too.
2014-10-21 01:18:46 -07:00
2014-10-30 03:32:09 -07:00
cs.RunActionPrecommit(1, 0)
<-cs.NewStepCh() // TODO: test this value too.
2014-12-17 01:37:13 -08:00
if cs.Precommits.GetByAddress(val0.Address) != nil {
t.Errorf("RunActionPrecommit should return nil, not enough prevotes")
2014-10-21 01:18:46 -07:00
}
// Add at least +2/3 prevotes.
for i := 0; i < 7; i++ {
vote := &types.Vote{
2014-10-30 03:32:09 -07:00
Height: 1,
Round: 0,
Type: types.VoteTypePrevote,
2014-10-30 03:32:09 -07:00
BlockHash: cs.ProposalBlock.Hash(),
BlockParts: cs.ProposalBlockParts.Header(),
2014-10-21 01:18:46 -07:00
}
err := privValidators[i].SignVote(vote)
if err != nil {
t.Error("Error signing vote: %v", err)
}
2014-12-17 01:37:13 -08:00
cs.AddVote(privValidators[i].Address, vote)
2014-10-21 01:18:46 -07:00
}
// Test RunActionPrecommit success:
2014-10-30 03:32:09 -07:00
cs.RunActionPrecommit(1, 0)
<-cs.NewStepCh() // TODO: test this value too.
2014-12-17 01:37:13 -08:00
if cs.Precommits.GetByAddress(val0.Address) == nil {
2014-10-21 01:18:46 -07:00
t.Errorf("RunActionPrecommit should have succeeded")
}
2014-10-31 18:35:38 -07:00
checkRoundState(t, cs.GetRoundState(), 1, 0, RoundStepPrecommit)
2014-10-21 01:18:46 -07:00
// Add at least +2/3 precommits.
for i := 0; i < 7; i++ {
2014-12-17 01:37:13 -08:00
if bytes.Equal(privValidators[i].Address, val0.Address) {
if cs.Precommits.GetByAddress(val0.Address) == nil {
t.Errorf("Proposer should already have signed a precommit vote")
}
continue
}
vote := &types.Vote{
2014-10-30 03:32:09 -07:00
Height: 1,
Round: 0,
Type: types.VoteTypePrecommit,
2014-10-30 03:32:09 -07:00
BlockHash: cs.ProposalBlock.Hash(),
BlockParts: cs.ProposalBlockParts.Header(),
2014-10-21 01:18:46 -07:00
}
err := privValidators[i].SignVote(vote)
if err != nil {
t.Error("Error signing vote: %v", err)
}
2014-12-17 01:37:13 -08:00
added, _, err := cs.AddVote(privValidators[i].Address, vote)
if !added || err != nil {
t.Errorf("Error adding precommit: %v", err)
}
2014-10-21 01:18:46 -07:00
}
// Test RunActionCommit success:
2014-10-30 03:32:09 -07:00
cs.RunActionCommit(1)
<-cs.NewStepCh() // TODO: test this value too.
2014-12-17 01:37:13 -08:00
if cs.Commits.GetByAddress(val0.Address) == nil {
2014-10-21 01:18:46 -07:00
t.Errorf("RunActionCommit should have succeeded")
}
2014-10-31 18:35:38 -07:00
checkRoundState(t, cs.GetRoundState(), 1, 0, RoundStepCommit)
2014-10-21 01:18:46 -07:00
// cs.CommitTime should still be zero
if !cs.CommitTime.IsZero() {
t.Errorf("Expected CommitTime to yet be zero")
}
// Add at least +2/3 commits.
for i := 0; i < 7; i++ {
2014-12-17 01:37:13 -08:00
if bytes.Equal(privValidators[i].Address, val0.Address) {
if cs.Commits.GetByAddress(val0.Address) == nil {
t.Errorf("Proposer should already have signed a commit vote")
}
continue
}
vote := &types.Vote{
2014-10-30 03:32:09 -07:00
Height: 1,
2014-12-17 01:37:13 -08:00
Round: uint(i), // Doesn't matter what round
Type: types.VoteTypeCommit,
2014-10-30 03:32:09 -07:00
BlockHash: cs.ProposalBlock.Hash(),
BlockParts: cs.ProposalBlockParts.Header(),
}
err := privValidators[i].SignVote(vote)
if err != nil {
t.Error("Error signing vote: %v", err)
}
2014-12-17 01:37:13 -08:00
added, _, err := cs.AddVote(privValidators[i].Address, vote)
if !added || err != nil {
t.Errorf("Error adding commit: %v", err)
}
}
2014-10-30 03:32:09 -07:00
// Test TryFinalizeCommit:
cs.TryFinalizeCommit(1)
<-cs.NewStepCh() // TODO: test this value too.
2014-10-31 18:35:38 -07:00
checkRoundState(t, cs.GetRoundState(), 2, 0, RoundStepNewHeight)
}