Browse Source

evidence: refactor evidence mocks throughout packages (#4787)

Predominantly following the discussions regarding the conventions of using mocks, I have decided to revert back to the previous state where mocks were specialized and stored in the separate packages that used them rather then have a generalized mock in the evidence package.

This also was a problem as the state package were running tests too slow and occasionally timing out unnecessarily.

For the replay file I renamed mockEvidencePool to emptyEvidencePool to illustrate that it was intentionally like this and not give the impression that testing software was being used in production

Closes: #4786
pull/4794/head
Callum Waters 4 years ago
committed by GitHub
parent
commit
47cfadb0aa
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 141 additions and 167 deletions
  1. +1
    -2
      blockchain/v0/reactor_test.go
  2. +1
    -2
      blockchain/v1/reactor_test.go
  3. +2
    -3
      blockchain/v2/reactor_test.go
  4. +1
    -2
      consensus/common_test.go
  5. +9
    -2
      consensus/replay.go
  6. +1
    -2
      consensus/replay_file.go
  7. +1
    -2
      consensus/replay_test.go
  8. +1
    -2
      consensus/wal_generator.go
  9. +0
    -124
      evidence/mock/pool_mock.go
  10. +3
    -4
      state/execution_test.go
  11. +78
    -0
      state/mocks/evidence_pool.go
  12. +10
    -1
      state/services.go
  13. +33
    -21
      state/validation_test.go

+ 1
- 2
blockchain/v0/reactor_test.go View File

@ -13,7 +13,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
cfg "github.com/tendermint/tendermint/config"
evmock "github.com/tendermint/tendermint/evidence/mock"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/mempool/mock"
"github.com/tendermint/tendermint/p2p"
@ -83,7 +82,7 @@ func newBlockchainReactor(
fastSync := true
db := dbm.NewMemDB()
blockExec := sm.NewBlockExecutor(db, log.TestingLogger(), proxyApp.Consensus(),
mock.Mempool{}, evmock.NewDefaultEvidencePool())
mock.Mempool{}, sm.MockEvidencePool{})
sm.SaveState(db, state)
// let's add some blocks in


+ 1
- 2
blockchain/v1/reactor_test.go View File

@ -16,7 +16,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
cfg "github.com/tendermint/tendermint/config"
evmock "github.com/tendermint/tendermint/evidence/mock"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/mempool/mock"
"github.com/tendermint/tendermint/p2p"
@ -113,7 +112,7 @@ func newBlockchainReactor(
fastSync := true
db := dbm.NewMemDB()
blockExec := sm.NewBlockExecutor(db, log.TestingLogger(), proxyApp.Consensus(),
mock.Mempool{}, evmock.NewDefaultEvidencePool())
mock.Mempool{}, sm.MockEvidencePool{})
sm.SaveState(db, state)
// let's add some blocks in


+ 2
- 3
blockchain/v2/reactor_test.go View File

@ -15,7 +15,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/behaviour"
cfg "github.com/tendermint/tendermint/config"
evmock "github.com/tendermint/tendermint/evidence/mock"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/libs/service"
"github.com/tendermint/tendermint/mempool/mock"
@ -153,7 +152,7 @@ func newTestReactor(p testReactorParams) *BlockchainReactor {
panic(errors.Wrap(err, "error start app"))
}
db := dbm.NewMemDB()
appl = sm.NewBlockExecutor(db, p.logger, proxyApp.Consensus(), mock.Mempool{}, evmock.NewDefaultEvidencePool())
appl = sm.NewBlockExecutor(db, p.logger, proxyApp.Consensus(), mock.Mempool{}, sm.MockEvidencePool{})
sm.SaveState(db, state)
}
@ -495,7 +494,7 @@ func newReactorStore(
db := dbm.NewMemDB()
blockExec := sm.NewBlockExecutor(db, log.TestingLogger(), proxyApp.Consensus(),
mock.Mempool{}, evmock.NewDefaultEvidencePool())
mock.Mempool{}, sm.MockEvidencePool{})
sm.SaveState(db, state)
// add blocks in


+ 1
- 2
consensus/common_test.go View File

@ -26,7 +26,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
cfg "github.com/tendermint/tendermint/config"
cstypes "github.com/tendermint/tendermint/consensus/types"
evmock "github.com/tendermint/tendermint/evidence/mock"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
"github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os"
@ -374,7 +373,7 @@ func newStateWithConfigAndBlockStore(
}
// mock the evidence pool
evpool := evmock.NewDefaultEvidencePool()
evpool := emptyEvidencePool{}
// Make State
stateDB := blockDB


+ 9
- 2
consensus/replay.go View File

@ -15,7 +15,6 @@ import (
//auto "github.com/tendermint/tendermint/libs/autofile"
dbm "github.com/tendermint/tm-db"
evmock "github.com/tendermint/tendermint/evidence/mock"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/mempool/mock"
"github.com/tendermint/tendermint/proxy"
@ -474,7 +473,7 @@ func (h *Handshaker) replayBlock(state sm.State, height int64, proxyApp proxy.Ap
block := h.store.LoadBlock(height)
meta := h.store.LoadBlockMeta(height)
blockExec := sm.NewBlockExecutor(h.stateDB, h.logger, proxyApp, mock.Mempool{}, evmock.NewDefaultEvidencePool())
blockExec := sm.NewBlockExecutor(h.stateDB, h.logger, proxyApp, mock.Mempool{}, emptyEvidencePool{})
blockExec.SetEventBus(h.eventBus)
var err error
@ -552,3 +551,11 @@ func (mock *mockProxyApp) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlo
func (mock *mockProxyApp) Commit() abci.ResponseCommit {
return abci.ResponseCommit{Data: mock.appHash}
}
type emptyEvidencePool struct{}
func (ev emptyEvidencePool) PendingEvidence(int64) []types.Evidence { return nil }
func (ev emptyEvidencePool) AddEvidence(types.Evidence) error { return nil }
func (ev emptyEvidencePool) Update(*types.Block, sm.State) {}
func (ev emptyEvidencePool) IsCommitted(types.Evidence) bool { return false }
func (ev emptyEvidencePool) IsPending(types.Evidence) bool { return true }

+ 1
- 2
consensus/replay_file.go View File

@ -13,7 +13,6 @@ import (
dbm "github.com/tendermint/tm-db"
cfg "github.com/tendermint/tendermint/config"
evmock "github.com/tendermint/tendermint/evidence/mock"
"github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os"
"github.com/tendermint/tendermint/mempool/mock"
@ -312,7 +311,7 @@ func newConsensusStateForReplay(config cfg.BaseConfig, csConfig *cfg.ConsensusCo
tmos.Exit(fmt.Sprintf("Error on handshake: %v", err))
}
mempool, evpool := mock.Mempool{}, evmock.NewDefaultEvidencePool()
mempool, evpool := mock.Mempool{}, emptyEvidencePool{}
blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mempool, evpool)
consensusState := NewState(csConfig, state.Copy(), blockExec,


+ 1
- 2
consensus/replay_test.go View File

@ -23,7 +23,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
evmock "github.com/tendermint/tendermint/evidence/mock"
"github.com/tendermint/tendermint/libs/log"
tmrand "github.com/tendermint/tendermint/libs/rand"
mempl "github.com/tendermint/tendermint/mempool"
@ -297,7 +296,7 @@ const (
var (
mempool = mock.Mempool{}
evpool = evmock.NewDefaultEvidencePool()
evpool = emptyEvidencePool{}
sim testSim
)


+ 1
- 2
consensus/wal_generator.go View File

@ -15,7 +15,6 @@ import (
"github.com/tendermint/tendermint/abci/example/kvstore"
cfg "github.com/tendermint/tendermint/config"
evmock "github.com/tendermint/tendermint/evidence/mock"
"github.com/tendermint/tendermint/libs/log"
tmrand "github.com/tendermint/tendermint/libs/rand"
"github.com/tendermint/tendermint/mempool/mock"
@ -74,7 +73,7 @@ func WALGenerateNBlocks(t *testing.T, wr io.Writer, numBlocks int) (err error) {
}
defer eventBus.Stop()
mempool := mock.Mempool{}
evpool := evmock.NewDefaultEvidencePool()
evpool := emptyEvidencePool{}
blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mempool, evpool)
consensusState := NewState(config.Consensus, state.Copy(), blockExec, blockStore, mempool, evpool)
consensusState.SetLogger(logger)


+ 0
- 124
evidence/mock/pool_mock.go View File

@ -1,124 +0,0 @@
package mock
import (
"time"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
)
// A quick and easy in-memory mock implementation of the evidence pool configured with both the standard exposed
// functions and extra helper function to set up, operate and ultimately imitate the evidence pool in a testing
// environment. Note: this mock does no validation. Do not test with large amounts of evidence
type EvidencePool struct {
PendingEvidenceList []types.Evidence
CommittedEvidenceList []types.Evidence
ExpirationAgeTime time.Duration
ExpirationAgeBlock int64
BlockHeight int64
BlockTime time.Time
}
// ------------------------ INSTANTIATION METHODS --------------------------------------
func NewEvidencePool(height, expiryHeight int64, currentTime time.Time, expiryTime time.Duration) *EvidencePool {
return &EvidencePool{
[]types.Evidence{},
[]types.Evidence{},
expiryTime,
expiryHeight,
height,
currentTime,
}
}
func NewDefaultEvidencePool() *EvidencePool {
return NewEvidencePool(1, 1, time.Now(), time.Millisecond)
}
// ----------------------- EVIDENCE POOL PUBLIC METHODS --------------------------------
func (p *EvidencePool) PendingEvidence(maxNum int64) []types.Evidence {
if maxNum == -1 || maxNum >= int64(len(p.PendingEvidenceList)) {
return p.PendingEvidenceList
}
return p.PendingEvidenceList[:maxNum]
}
func (p *EvidencePool) AddEvidence(evidence types.Evidence) error {
p.PendingEvidenceList = append(p.PendingEvidenceList, evidence)
return nil
}
func (p *EvidencePool) Update(block *types.Block, state sm.State) {
p.BlockHeight = block.Height
p.BlockTime = block.Time
p.MarkEvidenceAsCommitted(block.Height, block.Time, block.Evidence.Evidence)
p.RemoveExpiredEvidence()
}
func (p *EvidencePool) MarkEvidenceAsCommitted(height int64, lastBlockTime time.Time, evidence []types.Evidence) {
for _, ev := range evidence {
if p.IsPending(ev) {
p.RemovePendingEvidence(ev)
}
p.CommittedEvidenceList = append(p.CommittedEvidenceList, ev)
}
}
func (p *EvidencePool) IsPending(evidence types.Evidence) bool {
for _, ev := range p.PendingEvidenceList {
if ev.Equal(evidence) {
return true
}
}
return false
}
func (p *EvidencePool) IsCommitted(evidence types.Evidence) bool {
for _, ev := range p.CommittedEvidenceList {
if ev.Equal(evidence) {
return true
}
}
return false
}
func (p *EvidencePool) IsExpired(evidence types.Evidence) bool {
return evidence.Height()+p.ExpirationAgeBlock < p.BlockHeight &&
evidence.Time().Add(p.ExpirationAgeTime).Before(p.BlockTime)
}
// ------------------------------- HELPER METHODS --------------------------------------
func (p *EvidencePool) RemovePendingEvidence(evidence types.Evidence) {
for idx, ev := range p.PendingEvidenceList {
if ev.Equal(evidence) {
p.PendingEvidenceList[idx] = p.PendingEvidenceList[len(p.PendingEvidenceList)-1]
p.PendingEvidenceList = p.PendingEvidenceList[:len(p.PendingEvidenceList)-1]
return
}
}
}
func (p *EvidencePool) RemoveExpiredEvidence() {
for _, evidence := range p.PendingEvidenceList {
if p.IsExpired(evidence) {
p.RemovePendingEvidence(evidence)
}
}
}
func (p *EvidencePool) AddMockEvidence(height int64, address []byte) types.Evidence {
mock := types.MockEvidence{
EvidenceHeight: height,
EvidenceTime: p.BlockTime,
EvidenceAddress: address,
}
_ = p.AddEvidence(mock)
return mock
}
func (p *EvidencePool) CommitEvidence(evidence types.Evidence) {
p.MarkEvidenceAsCommitted(evidence.Height(), evidence.Time(), []types.Evidence{evidence})
}

+ 3
- 4
state/execution_test.go View File

@ -12,7 +12,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
evmock "github.com/tendermint/tendermint/evidence/mock"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/mempool/mock"
"github.com/tendermint/tendermint/proxy"
@ -39,7 +38,7 @@ func TestApplyBlock(t *testing.T) {
state, stateDB, _ := makeState(1, 1)
blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(),
mock.Mempool{}, evmock.NewDefaultEvidencePool())
mock.Mempool{}, sm.MockEvidencePool{})
block := makeBlock(state, 1)
blockID := types.BlockID{Hash: block.Hash(), PartsHeader: block.MakePartSet(testPartSize).Header()}
@ -335,7 +334,7 @@ func TestEndBlockValidatorUpdates(t *testing.T) {
log.TestingLogger(),
proxyApp.Consensus(),
mock.Mempool{},
evmock.NewDefaultEvidencePool(),
sm.MockEvidencePool{},
)
eventBus := types.NewEventBus()
@ -402,7 +401,7 @@ func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) {
log.TestingLogger(),
proxyApp.Consensus(),
mock.Mempool{},
evmock.NewDefaultEvidencePool(),
sm.MockEvidencePool{},
)
block := makeBlock(state, 1)


+ 78
- 0
state/mocks/evidence_pool.go View File

@ -0,0 +1,78 @@
// Code generated by mockery v1.0.0. DO NOT EDIT.
package mocks
import (
mock "github.com/stretchr/testify/mock"
state "github.com/tendermint/tendermint/state"
types "github.com/tendermint/tendermint/types"
)
// EvidencePool is an autogenerated mock type for the EvidencePool type
type EvidencePool struct {
mock.Mock
}
// AddEvidence provides a mock function with given fields: _a0
func (_m *EvidencePool) AddEvidence(_a0 types.Evidence) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(types.Evidence) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// IsCommitted provides a mock function with given fields: _a0
func (_m *EvidencePool) IsCommitted(_a0 types.Evidence) bool {
ret := _m.Called(_a0)
var r0 bool
if rf, ok := ret.Get(0).(func(types.Evidence) bool); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// IsPending provides a mock function with given fields: _a0
func (_m *EvidencePool) IsPending(_a0 types.Evidence) bool {
ret := _m.Called(_a0)
var r0 bool
if rf, ok := ret.Get(0).(func(types.Evidence) bool); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// PendingEvidence provides a mock function with given fields: _a0
func (_m *EvidencePool) PendingEvidence(_a0 int64) []types.Evidence {
ret := _m.Called(_a0)
var r0 []types.Evidence
if rf, ok := ret.Get(0).(func(int64) []types.Evidence); ok {
r0 = rf(_a0)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]types.Evidence)
}
}
return r0
}
// Update provides a mock function with given fields: _a0, _a1
func (_m *EvidencePool) Update(_a0 *types.Block, _a1 state.State) {
_m.Called(_a0, _a1)
}

+ 10
- 1
state/services.go View File

@ -35,13 +35,22 @@ type BlockStore interface {
//-----------------------------------------------------------------------------
// evidence pool
//go:generate mockery -case underscore -name EvidencePool
// EvidencePool defines the EvidencePool interface used by the ConsensusState.
// Get/Set/Commit
type EvidencePool interface {
PendingEvidence(int64) []types.Evidence
AddEvidence(types.Evidence) error
Update(*types.Block, State)
// IsCommitted indicates if this evidence was already marked committed in another block.
IsCommitted(types.Evidence) bool
IsPending(types.Evidence) bool
}
type MockEvidencePool struct{}
func (me MockEvidencePool) PendingEvidence(int64) []types.Evidence { return nil }
func (me MockEvidencePool) AddEvidence(types.Evidence) error { return nil }
func (me MockEvidencePool) Update(*types.Block, State) {}
func (me MockEvidencePool) IsCommitted(types.Evidence) bool { return false }
func (me MockEvidencePool) IsPending(types.Evidence) bool { return false }

+ 33
- 21
state/validation_test.go View File

@ -4,20 +4,23 @@ import (
"testing"
"time"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/tmhash"
evmock "github.com/tendermint/tendermint/evidence/mock"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/mempool/mock"
memmock "github.com/tendermint/tendermint/mempool/mock"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/state/mocks"
"github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
)
const validationTestsStopHeight int64 = 10
var defaultTestTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
func TestValidateBlockHeader(t *testing.T) {
proxyApp := newTestApp()
require.NoError(t, proxyApp.Start())
@ -28,8 +31,8 @@ func TestValidateBlockHeader(t *testing.T) {
stateDB,
log.TestingLogger(),
proxyApp.Consensus(),
mock.Mempool{},
evmock.NewDefaultEvidencePool(),
memmock.Mempool{},
sm.MockEvidencePool{},
)
lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil)
@ -98,8 +101,8 @@ func TestValidateBlockCommit(t *testing.T) {
stateDB,
log.TestingLogger(),
proxyApp.Consensus(),
mock.Mempool{},
evmock.NewDefaultEvidencePool(),
memmock.Mempool{},
sm.MockEvidencePool{},
)
lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil)
wrongSigsCommit := types.NewCommit(1, 0, types.BlockID{}, nil)
@ -205,8 +208,8 @@ func TestValidateBlockEvidence(t *testing.T) {
stateDB,
log.TestingLogger(),
proxyApp.Consensus(),
mock.Mempool{},
evmock.NewDefaultEvidencePool(),
memmock.Mempool{},
sm.MockEvidencePool{},
)
lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil)
@ -259,9 +262,17 @@ func TestValidateBlockEvidence(t *testing.T) {
func TestValidateFailBlockOnCommittedEvidence(t *testing.T) {
var height int64 = 1
state, stateDB, _ := makeState(1, int(height))
state, stateDB, _ := makeState(2, int(height))
addr, _ := state.Validators.GetByIndex(0)
addr2, _ := state.Validators.GetByIndex(1)
ev := types.NewMockEvidence(height, defaultTestTime, addr)
ev2 := types.NewMockEvidence(height, defaultTestTime, addr2)
evpool := &mocks.EvidencePool{}
evpool.On("IsPending", mock.AnythingOfType("types.MockEvidence")).Return(false)
evpool.On("IsCommitted", ev).Return(false)
evpool.On("IsCommitted", ev2).Return(true)
evpool := evmock.NewDefaultEvidencePool()
blockExec := sm.NewBlockExecutor(
stateDB, log.TestingLogger(),
nil,
@ -269,9 +280,7 @@ func TestValidateFailBlockOnCommittedEvidence(t *testing.T) {
evpool)
// A block with a couple pieces of evidence passes.
block := makeBlock(state, height)
addr, _ := state.Validators.GetByIndex(0)
evpool.CommitEvidence(evpool.AddMockEvidence(height, addr))
block.Evidence.Evidence = evpool.CommittedEvidenceList
block.Evidence.Evidence = []types.Evidence{ev, ev2}
block.EvidenceHash = block.Evidence.Hash()
err := blockExec.ValidateBlock(state, block)
@ -282,8 +291,16 @@ func TestValidateFailBlockOnCommittedEvidence(t *testing.T) {
func TestValidateAlreadyPendingEvidence(t *testing.T) {
var height int64 = 1
state, stateDB, _ := makeState(2, int(height))
addr, _ := state.Validators.GetByIndex(0)
addr2, _ := state.Validators.GetByIndex(1)
ev := types.NewMockEvidence(height, defaultTestTime, addr)
ev2 := types.NewMockEvidence(height, defaultTestTime, addr2)
evpool := &mocks.EvidencePool{}
evpool.On("IsPending", ev).Return(false)
evpool.On("IsPending", ev2).Return(true)
evpool.On("IsCommitted", mock.AnythingOfType("types.MockEvidence")).Return(false)
evpool := evmock.NewDefaultEvidencePool()
blockExec := sm.NewBlockExecutor(
stateDB, log.TestingLogger(),
nil,
@ -291,13 +308,8 @@ func TestValidateAlreadyPendingEvidence(t *testing.T) {
evpool)
// A block with a couple pieces of evidence passes.
block := makeBlock(state, height)
addr, _ := state.Validators.GetByIndex(0)
addr2, _ := state.Validators.GetByIndex(0)
// add pending evidence
pendingEv := evpool.AddMockEvidence(height, addr)
// add evidence that hasn't seen before
ev := types.NewMockEvidence(height, time.Now(), addr2)
block.Evidence.Evidence = []types.Evidence{pendingEv, ev}
// add one evidence seen before and one evidence that hasn't
block.Evidence.Evidence = []types.Evidence{ev, ev2}
block.EvidenceHash = block.Evidence.Hash()
err := blockExec.ValidateBlock(state, block)


Loading…
Cancel
Save