go-ethereum/eth/bfter/bft_test.go
Liam a1b77f3ca8 Implement BFT Message receiver (#13)
* fix or skip tests due to PR-136 changes

* add bft receiver functions

* add bft receiver functions

* rename tc to TimeoutCert

* implement more functions

* New struct in consensus/XDPoS/utils/types.go, util functions, and test. (#14)

* define vote, timeout, sync info, qc, tc, extra fields in types.go, add test in types_test.go

* add json tag in types.go, refine encoder decoder of extra fields

* refactor types.go utils.go

* re-write types, comments

* add Hash SigHash for types, and tests

* define Round type

* remove unnecessary logs

* add temp functions

* add v2 engine functions placeholder

* typo fix on the consensus v2 function placeholders

* add countdown timer

* make initilised private to countdown

* push verify function

* add test on receiving vote

* revert type change

* add async on broadcast function

* add quit initial

* fix test

Co-authored-by: Jianrong <wjrjerome@gmail.com>
Co-authored-by: wgr523 <wgr523@gmail.com>
2021-12-30 11:00:20 +11:00

118 lines
3.1 KiB
Go

package bfter
import (
"fmt"
"sync/atomic"
"testing"
"time"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/engines/engine_v2"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
)
// make different votes based on Signatures
func makeVotes(n int) []utils.Vote {
var votes []utils.Vote
for i := 0; i < n; i++ {
votes = append(votes, utils.Vote{Signature: []byte{byte(i)}})
}
return votes
}
// bfterTester is a test simulator for mocking out bfter worker.
type bfterTester struct {
bfter *Bfter
}
// newTester creates a new bft fetcher test mocker.
func newTester() *bfterTester {
testConsensus := &XDPoS.XDPoS{EngineV2: &engine_v2.XDPoS_v2{}}
broadcasts := BroadcastFns{}
tester := &bfterTester{}
tester.bfter = New(broadcasts)
tester.bfter.SetConsensusFuns(testConsensus)
tester.bfter.broadcastCh = make(chan interface{})
tester.bfter.Start()
return tester
}
// Tests that a bfter accepts vote and process verfiy and broadcast
func TestSequentialVotes(t *testing.T) {
tester := newTester()
verifyCounter := uint32(0)
broadcastCounter := uint32(0)
targetVotes := 10
tester.bfter.consensus.verifyVote = func(vote utils.Vote) error {
atomic.AddUint32(&verifyCounter, 1)
return nil
}
tester.bfter.broadcast.Vote = func(utils.Vote) {
atomic.AddUint32(&broadcastCounter, 1)
}
votes := makeVotes(targetVotes)
for _, vote := range votes {
tester.bfter.Vote(vote)
}
time.Sleep(50 * time.Millisecond)
if int(verifyCounter) != targetVotes || int(broadcastCounter) != targetVotes {
t.Fatalf("count mismatch: have %v on verify and have %v on broadcast, want %v", verifyCounter, broadcastCounter, targetVotes)
}
}
// Tests that vote already being retrieved will not be duplicated.
func TestDuplicateVotes(t *testing.T) {
tester := newTester()
verifyCounter := uint32(0)
broadcastCounter := uint32(0)
targetVotes := 1
tester.bfter.consensus.verifyVote = func(vote utils.Vote) error {
atomic.AddUint32(&verifyCounter, 1)
return nil
}
tester.bfter.broadcast.Vote = func(utils.Vote) {
atomic.AddUint32(&broadcastCounter, 1)
}
vote := utils.Vote{}
// send twice
tester.bfter.Vote(vote)
tester.bfter.Vote(vote)
time.Sleep(50 * time.Millisecond)
if int(verifyCounter) != targetVotes || int(broadcastCounter) != targetVotes {
t.Fatalf("count mismatch: have %v on verify and have %v on broadcast, want %v", verifyCounter, broadcastCounter, targetVotes)
}
}
// Test that avoid boardcast if there is bad vote
func TestNotBoardcastInvalidVote(t *testing.T) {
tester := newTester()
broadcastCounter := uint32(0)
targetVotes := 0
tester.bfter.consensus.verifyVote = func(vote utils.Vote) error {
return fmt.Errorf("This is invalid vote")
}
tester.bfter.broadcast.Vote = func(utils.Vote) {
atomic.AddUint32(&broadcastCounter, 1)
}
vote := utils.Vote{}
tester.bfter.Vote(vote)
time.Sleep(50 * time.Millisecond)
if int(broadcastCounter) != targetVotes {
t.Fatalf("count mismatch: have %v on broadcast, want %v", broadcastCounter, targetVotes)
}
}
// TODO: SyncInfo and Timeout Test, should be same as Vote.
// Once all test on vote covered, then duplicate to others