TxsAvailable tests

This commit is contained in:
Ethan Buchman 2017-07-13 15:03:19 -04:00
parent 124032e3e9
commit 678a9a2e42
4 changed files with 132 additions and 24 deletions

View File

@ -294,12 +294,22 @@ func randConsensusState(nValidators int) (*ConsensusState, []*validatorStub) {
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
func ensureNoNewStep(stepCh chan interface{}) { func ensureNoNewStep(stepCh chan interface{}) {
timeout := time.NewTicker(ensureTimeout * time.Second) timer := time.NewTimer(ensureTimeout * time.Second)
select { select {
case <-timeout.C: case <-timer.C:
break break
case <-stepCh: case <-stepCh:
panic("We should be stuck waiting for more votes, not moving to the next step") panic("We should be stuck waiting, not moving to the next step")
}
}
func ensureNewStep(stepCh chan interface{}) {
timer := time.NewTimer(ensureTimeout * time.Second)
select {
case <-timer.C:
panic("We shouldnt be stuck waiting")
case <-stepCh:
break
} }
} }

View File

@ -15,6 +15,34 @@ func init() {
config = ResetConfig("consensus_mempool_test") config = ResetConfig("consensus_mempool_test")
} }
func TestTxsAvailable(t *testing.T) {
config := ResetConfig("consensus_mempool_txs_available_test")
config.Consensus.NoEmptyBlocks = true
state, privVals := randGenesisState(1, false, 10)
cs := newConsensusStateWithConfig(config, state, privVals[0], NewCounterApplication())
cs.mempool.FireOnTxsAvailable()
height, round := cs.Height, cs.Round
newBlockCh := subscribeToEvent(cs.evsw, "tester", types.EventStringNewBlock(), 1)
startTestRound(cs, height, round)
// we shouldnt make progress until theres a tx
ensureNoNewStep(newBlockCh)
deliverTxsRange(cs, 0, 100)
ensureNewStep(newBlockCh)
}
func deliverTxsRange(cs *ConsensusState, start, end int) {
// Deliver some txs.
for i := start; i < end; i++ {
txBytes := make([]byte, 8)
binary.BigEndian.PutUint64(txBytes, uint64(i))
err := cs.mempool.CheckTx(txBytes, nil)
if err != nil {
panic(Fmt("Error after CheckTx: %v", err))
}
}
}
func TestTxConcurrentWithCommit(t *testing.T) { func TestTxConcurrentWithCommit(t *testing.T) {
state, privVals := randGenesisState(1, false, 10) state, privVals := randGenesisState(1, false, 10)
@ -22,21 +50,8 @@ func TestTxConcurrentWithCommit(t *testing.T) {
height, round := cs.Height, cs.Round height, round := cs.Height, cs.Round
newBlockCh := subscribeToEvent(cs.evsw, "tester", types.EventStringNewBlock(), 1) newBlockCh := subscribeToEvent(cs.evsw, "tester", types.EventStringNewBlock(), 1)
deliverTxsRange := func(start, end int) {
// Deliver some txs.
for i := start; i < end; i++ {
txBytes := make([]byte, 8)
binary.BigEndian.PutUint64(txBytes, uint64(i))
err := cs.mempool.CheckTx(txBytes, nil)
if err != nil {
panic(Fmt("Error after CheckTx: %v", err))
}
// time.Sleep(time.Microsecond * time.Duration(rand.Int63n(3000)))
}
}
NTxs := 10000 NTxs := 10000
go deliverTxsRange(0, NTxs) go deliverTxsRange(cs, 0, NTxs)
startTestRound(cs, height, round) startTestRound(cs, height, round)
ticker := time.NewTicker(time.Second * 20) ticker := time.NewTicker(time.Second * 20)

View File

@ -1,34 +1,115 @@
package mempool package mempool
import ( import (
"crypto/rand"
"encoding/binary" "encoding/binary"
"testing" "testing"
"time"
"github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/example/counter"
"github.com/tendermint/abci/example/dummy"
"github.com/tendermint/tmlibs/log"
cfg "github.com/tendermint/tendermint/config" cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/proxy"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
"github.com/tendermint/tmlibs/log"
) )
func TestSerialReap(t *testing.T) { func newMempoolWithApp(t *testing.T, cc proxy.ClientCreator) *Mempool {
config := cfg.ResetTestRoot("mempool_test") config := cfg.ResetTestRoot("mempool_test")
app := counter.NewCounterApplication(true)
app.SetOption("serial", "on")
cc := proxy.NewLocalClientCreator(app)
appConnMem, _ := cc.NewABCIClient() appConnMem, _ := cc.NewABCIClient()
appConnMem.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "mempool")) appConnMem.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "mempool"))
if _, err := appConnMem.Start(); err != nil { if _, err := appConnMem.Start(); err != nil {
t.Fatalf("Error starting ABCI client: %v", err.Error()) t.Fatalf("Error starting ABCI client: %v", err.Error())
} }
mempool := NewMempool(config.Mempool, appConnMem)
mempool.SetLogger(log.TestingLogger())
return mempool
}
func ensureNoFire(t *testing.T, ch chan struct{}, timeoutMS int) {
timer := time.NewTimer(time.Duration(timeoutMS) * time.Millisecond)
select {
case <-ch:
t.Fatal("Expected not to fire")
case <-timer.C:
}
}
func ensureFire(t *testing.T, ch chan struct{}, timeoutMS int) {
timer := time.NewTimer(time.Duration(timeoutMS) * time.Millisecond)
select {
case <-ch:
case <-timer.C:
t.Fatal("Expected to fire")
}
}
func sendTxs(t *testing.T, mempool *Mempool, count int) types.Txs {
txs := make(types.Txs, count)
for i := 0; i < count; i++ {
txBytes := make([]byte, 20)
txs[i] = txBytes
rand.Read(txBytes)
err := mempool.CheckTx(txBytes, nil)
if err != nil {
t.Fatal("Error after CheckTx: %v", err)
}
}
return txs
}
func TestTxsAvailable(t *testing.T) {
app := dummy.NewDummyApplication()
cc := proxy.NewLocalClientCreator(app)
mempool := newMempoolWithApp(t, cc)
mempool.FireOnTxsAvailable()
timeoutMS := 500
// with no txs, it shouldnt fire
ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
// send a bunch of txs, it should only fire once
txs := sendTxs(t, mempool, 100)
ensureFire(t, mempool.TxsAvailable(), timeoutMS)
ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
// call update with half the txs.
// it should fire once now for the new height
// since there are still txs left
committedTxs, txs := txs[:50], txs[50:]
mempool.Update(1, committedTxs)
ensureFire(t, mempool.TxsAvailable(), timeoutMS)
ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
// send a bunch more txs. we already fired for this height so it shouldnt fire again
moreTxs := sendTxs(t, mempool, 50)
ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
// now call update with all the txs. it should not fire as there are no txs left
committedTxs = append(txs, moreTxs...)
mempool.Update(2, committedTxs)
ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
// send a bunch more txs, it should only fire once
sendTxs(t, mempool, 100)
ensureFire(t, mempool.TxsAvailable(), timeoutMS)
ensureNoFire(t, mempool.TxsAvailable(), timeoutMS)
}
func TestSerialReap(t *testing.T) {
app := counter.NewCounterApplication(true)
app.SetOption("serial", "on")
cc := proxy.NewLocalClientCreator(app)
mempool := newMempoolWithApp(t, cc)
appConnCon, _ := cc.NewABCIClient() appConnCon, _ := cc.NewABCIClient()
appConnCon.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "consensus")) appConnCon.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "consensus"))
if _, err := appConnCon.Start(); err != nil { if _, err := appConnCon.Start(); err != nil {
t.Fatalf("Error starting ABCI client: %v", err.Error()) t.Fatalf("Error starting ABCI client: %v", err.Error())
} }
mempool := NewMempool(config.Mempool, appConnMem)
mempool.SetLogger(log.TestingLogger())
deliverTxsRange := func(start, end int) { deliverTxsRange := func(start, end int) {
// Deliver some txs. // Deliver some txs.

View File

@ -25,6 +25,7 @@ type Mempool interface {
Flush() Flush()
TxsAvailable() chan struct{} TxsAvailable() chan struct{}
FireOnTxsAvailable()
} }
type MockMempool struct { type MockMempool struct {
@ -38,6 +39,7 @@ func (m MockMempool) Reap(n int) Txs { return Txs{
func (m MockMempool) Update(height int, txs Txs) {} func (m MockMempool) Update(height int, txs Txs) {}
func (m MockMempool) Flush() {} func (m MockMempool) Flush() {}
func (m MockMempool) TxsAvailable() chan struct{} { return make(chan struct{}) } func (m MockMempool) TxsAvailable() chan struct{} { return make(chan struct{}) }
func (m MockMempool) FireOnTxsAvailable() {}
//------------------------------------------------------ //------------------------------------------------------
// blockstore // blockstore