You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
3.7 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. package consensus
  2. import (
  3. "encoding/binary"
  4. "testing"
  5. "time"
  6. abci "github.com/tendermint/abci/types"
  7. "github.com/tendermint/tendermint/types"
  8. . "github.com/tendermint/tmlibs/common"
  9. )
  10. func init() {
  11. config = ResetConfig("consensus_mempool_test")
  12. }
  13. func TestTxConcurrentWithCommit(t *testing.T) {
  14. state, privVals := randGenesisState(1, false, 10)
  15. cs := newConsensusState(state, privVals[0], NewCounterApplication())
  16. height, round := cs.Height, cs.Round
  17. newBlockCh := subscribeToEvent(cs.evsw, "tester", types.EventStringNewBlock(), 1)
  18. deliverTxsRange := func(start, end int) {
  19. // Deliver some txs.
  20. for i := start; i < end; i++ {
  21. txBytes := make([]byte, 8)
  22. binary.BigEndian.PutUint64(txBytes, uint64(i))
  23. err := cs.mempool.CheckTx(txBytes, nil)
  24. if err != nil {
  25. panic(Fmt("Error after CheckTx: %v", err))
  26. }
  27. // time.Sleep(time.Microsecond * time.Duration(rand.Int63n(3000)))
  28. }
  29. }
  30. NTxs := 10000
  31. go deliverTxsRange(0, NTxs)
  32. startTestRound(cs, height, round)
  33. ticker := time.NewTicker(time.Second * 20)
  34. for nTxs := 0; nTxs < NTxs; {
  35. select {
  36. case b := <-newBlockCh:
  37. nTxs += b.(types.TMEventData).Unwrap().(types.EventDataNewBlock).Block.Header.NumTxs
  38. case <-ticker.C:
  39. panic("Timed out waiting to commit blocks with transactions")
  40. }
  41. }
  42. }
  43. func TestRmBadTx(t *testing.T) {
  44. state, privVals := randGenesisState(1, false, 10)
  45. app := NewCounterApplication()
  46. cs := newConsensusState(state, privVals[0], app)
  47. // increment the counter by 1
  48. txBytes := make([]byte, 8)
  49. binary.BigEndian.PutUint64(txBytes, uint64(0))
  50. app.DeliverTx(txBytes)
  51. app.Commit()
  52. ch := make(chan struct{})
  53. cbCh := make(chan struct{})
  54. go func() {
  55. // Try to send the tx through the mempool.
  56. // CheckTx should not err, but the app should return a bad abci code
  57. // and the tx should get removed from the pool
  58. err := cs.mempool.CheckTx(txBytes, func(r *abci.Response) {
  59. if r.GetCheckTx().Code != abci.CodeType_BadNonce {
  60. t.Fatalf("expected checktx to return bad nonce, got %v", r)
  61. }
  62. cbCh <- struct{}{}
  63. })
  64. if err != nil {
  65. t.Fatal("Error after CheckTx: %v", err)
  66. }
  67. // check for the tx
  68. for {
  69. time.Sleep(time.Second)
  70. txs := cs.mempool.Reap(1)
  71. if len(txs) == 0 {
  72. ch <- struct{}{}
  73. return
  74. }
  75. }
  76. }()
  77. // Wait until the tx returns
  78. ticker := time.After(time.Second * 5)
  79. select {
  80. case <-cbCh:
  81. // success
  82. case <-ticker:
  83. t.Fatalf("Timed out waiting for tx to return")
  84. }
  85. // Wait until the tx is removed
  86. ticker = time.After(time.Second * 5)
  87. select {
  88. case <-ch:
  89. // success
  90. case <-ticker:
  91. t.Fatalf("Timed out waiting for tx to be removed")
  92. }
  93. }
  94. // CounterApplication that maintains a mempool state and resets it upon commit
  95. type CounterApplication struct {
  96. abci.BaseApplication
  97. txCount int
  98. mempoolTxCount int
  99. }
  100. func NewCounterApplication() *CounterApplication {
  101. return &CounterApplication{}
  102. }
  103. func (app *CounterApplication) Info() abci.ResponseInfo {
  104. return abci.ResponseInfo{Data: Fmt("txs:%v", app.txCount)}
  105. }
  106. func (app *CounterApplication) DeliverTx(tx []byte) abci.Result {
  107. return runTx(tx, &app.txCount)
  108. }
  109. func (app *CounterApplication) CheckTx(tx []byte) abci.Result {
  110. return runTx(tx, &app.mempoolTxCount)
  111. }
  112. func runTx(tx []byte, countPtr *int) abci.Result {
  113. count := *countPtr
  114. tx8 := make([]byte, 8)
  115. copy(tx8[len(tx8)-len(tx):], tx)
  116. txValue := binary.BigEndian.Uint64(tx8)
  117. if txValue != uint64(count) {
  118. return abci.ErrBadNonce.AppendLog(Fmt("Invalid nonce. Expected %v, got %v", count, txValue))
  119. }
  120. *countPtr += 1
  121. return abci.OK
  122. }
  123. func (app *CounterApplication) Commit() abci.Result {
  124. app.mempoolTxCount = app.txCount
  125. if app.txCount == 0 {
  126. return abci.OK
  127. } else {
  128. hash := make([]byte, 8)
  129. binary.BigEndian.PutUint64(hash, uint64(app.txCount))
  130. return abci.NewResultOK(hash, "")
  131. }
  132. }