use typed mocks

This commit is contained in:
Evgeny Danienko 2022-06-03 12:31:48 +03:00
parent b19d5e109b
commit c9a3b9971b
7 changed files with 154 additions and 134 deletions

View file

@ -64,6 +64,9 @@ devtools:
env GOBIN= go install github.com/fjl/gencodec@latest
env GOBIN= go install github.com/golang/protobuf/protoc-gen-go@latest
env GOBIN= go install ./cmd/abigen
PATH=$(GOBIN):$(PATH) go generate ./common
PATH=$(GOBIN):$(PATH) go generate ./core/types
PATH=$(GOBIN):$(PATH) go generate ./consensus/bor
@type "solc" 2> /dev/null || echo 'Please install solc'
@type "protoc" 2> /dev/null || echo 'Please install protoc'

View file

@ -35,6 +35,7 @@ type Checkpoint struct {
Timestamp uint64 `json:"timestamp"`
}
//go:generate mockgen -destination=../../tests/bor/mocks/IHeimdallClient.go -package=mocks . IHeimdallClient
type IHeimdallClient interface {
Fetch(path string, query string) (*ResponseWithHeight, error)
FetchWithRetry(path string, query string) (*ResponseWithHeight, error)

3
go.mod
View file

@ -28,6 +28,7 @@ require (
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/go-stack/stack v1.8.0
github.com/golang-jwt/jwt/v4 v4.3.0
github.com/golang/mock v1.3.1
github.com/golang/protobuf v1.5.2
github.com/golang/snappy v0.0.4
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa
@ -83,5 +84,5 @@ require (
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6
gopkg.in/urfave/cli.v1 v1.20.0
gotest.tools v2.2.0+incompatible // indirect
gotest.tools v2.2.0+incompatible
)

1
go.sum
View file

@ -194,6 +194,7 @@ github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=

View file

@ -8,6 +8,10 @@ import (
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"golang.org/x/crypto/sha3"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/bor"
"github.com/ethereum/go-ethereum/consensus/ethash"
@ -19,9 +23,6 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/tests/bor/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"golang.org/x/crypto/sha3"
)
var (
@ -32,13 +33,12 @@ var (
func TestInsertingSpanSizeBlocks(t *testing.T) {
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
chain := init.ethereum.BlockChain()
engine := init.ethereum.Engine()
_bor := engine.(*bor.Bor)
h, heimdallSpan := getMockedHeimdallClient(t)
h, heimdallSpan, ctrl := getMockedHeimdallClient(t)
defer ctrl.Finish()
_bor.SetHeimdallClient(h)
@ -52,7 +52,6 @@ func TestInsertingSpanSizeBlocks(t *testing.T) {
insertNewBlock(t, chain, block)
}
assert.True(t, h.AssertCalled(t, "FetchWithRetry", spanPath, ""))
validators, err := _bor.GetCurrentValidators(block.Hash(), spanSize) // check validator set at the first block of new span
if err != nil {
t.Fatalf("%s", err)
@ -74,7 +73,6 @@ func TestFetchStateSyncEvents(t *testing.T) {
// A. Insert blocks for 0th sprint
db := init.ethereum.ChainDb()
block := init.genesis.ToBlock(db)
// Insert sprintSize # of blocks so that span is fetched at the start of a new sprint
for i := uint64(1); i < sprintSize; i++ {
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
@ -82,8 +80,13 @@ func TestFetchStateSyncEvents(t *testing.T) {
}
// B. Before inserting 1st block of the next sprint, mock heimdall deps
// B.1 Mock /bor/span/1
res, _ := loadSpanFromFile(t)
// B.1 /bor/span/1
ctrl := gomock.NewController(t)
defer ctrl.Finish()
h := mocks.NewMockIHeimdallClient(ctrl)
// B.2 Mock State Sync events
fromID := uint64(1)
@ -96,18 +99,12 @@ func TestFetchStateSyncEvents(t *testing.T) {
eventRecords := generateFakeStateSyncEvents(sample, eventCount)
// Mock
res, _ := loadSpanFromFile(t)
h := &mocks.IHeimdallClient{}
h.On("FetchWithRetry", spanPath, "").Return(res, nil)
h.On("FetchLatestCheckpoint").Maybe().Return(mock.Anything, nil)
h.On("FetchStateSyncEvents", fromID, to).Return(eventRecords, nil)
h.EXPECT().FetchWithRetry(spanPath, "").Return(res, nil).AnyTimes()
h.EXPECT().FetchStateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
_bor.SetHeimdallClient(h)
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
insertNewBlock(t, chain, block)
assert.True(t, h.AssertCalled(t, "FetchWithRetry", spanPath, ""))
assert.True(t, h.AssertCalled(t, "FetchStateSyncEvents", fromID, to))
}
func TestFetchStateSyncEvents_2(t *testing.T) {
@ -118,9 +115,12 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
// Mock /bor/span/1
res, _ := loadSpanFromFile(t)
h := &mocks.IHeimdallClient{}
h.On("FetchWithRetry", spanPath, "").Return(res, nil)
h.On("FetchLatestCheckpoint").Maybe().Return(mock.Anything, nil)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
h := mocks.NewMockIHeimdallClient(ctrl)
h.EXPECT().FetchWithRetry(spanPath, "").Return(res, nil).AnyTimes()
// Mock State Sync events
// at # sprintSize, events are fetched for [fromID, (block-sprint).Time)
@ -139,7 +139,7 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
buildStateEvent(sample, 6, 4), // id = 6, time = 4
}
h.On("FetchStateSyncEvents", fromID, to).Return(eventRecords, nil)
h.EXPECT().FetchStateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
_bor.SetHeimdallClient(h)
// Insert blocks for 0th sprint
@ -150,9 +150,6 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
insertNewBlock(t, chain, block)
}
assert.True(t, h.AssertCalled(t, "FetchWithRetry", spanPath, ""))
assert.True(t, h.AssertCalled(t, "FetchStateSyncEvents", fromID, to))
lastStateID, _ := _bor.GenesisContractsClient.LastStateId(sprintSize)
// state 6 was not written
@ -166,13 +163,13 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
buildStateEvent(sample, 6, 4),
}
h.On("FetchStateSyncEvents", fromID, to).Return(eventRecords, nil)
h.EXPECT().FetchStateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
for i := sprintSize + 1; i <= spanSize; i++ {
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
insertNewBlock(t, chain, block)
}
assert.True(t, h.AssertCalled(t, "FetchStateSyncEvents", fromID, to))
lastStateID, _ = _bor.GenesisContractsClient.LastStateId(spanSize)
assert.Equal(t, uint64(6), lastStateID.Uint64())
}
@ -181,9 +178,11 @@ func TestOutOfTurnSigning(t *testing.T) {
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
chain := init.ethereum.BlockChain()
engine := init.ethereum.Engine()
_bor := engine.(*bor.Bor)
h, _ := getMockedHeimdallClient(t)
h, _, ctrl := getMockedHeimdallClient(t)
defer ctrl.Finish()
_bor.SetHeimdallClient(h)
db := init.ethereum.ChainDb()
@ -212,7 +211,6 @@ func TestOutOfTurnSigning(t *testing.T) {
header := block.Header()
header.Time += (bor.CalcProducerDelay(header.Number.Uint64(), expectedSuccessionNumber, init.genesis.Config.Bor) -
bor.CalcProducerDelay(header.Number.Uint64(), 0, init.genesis.Config.Bor))
sign(t, header, signerKey, init.genesis.Config.Bor)
block = types.NewBlockWithHeader(header)
@ -233,9 +231,11 @@ func TestSignerNotFound(t *testing.T) {
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
chain := init.ethereum.BlockChain()
engine := init.ethereum.Engine()
_bor := engine.(*bor.Bor)
h, _ := getMockedHeimdallClient(t)
h, _, ctrl := getMockedHeimdallClient(t)
defer ctrl.Finish()
_bor.SetHeimdallClient(h)
db := init.ethereum.ChainDb()
@ -254,17 +254,16 @@ func TestSignerNotFound(t *testing.T) {
bor.UnauthorizedSignerError{Number: 0, Signer: addr.Bytes()})
}
func getMockedHeimdallClient(t *testing.T) (*mocks.IHeimdallClient, *bor.HeimdallSpan) {
res, heimdallSpan := loadSpanFromFile(t)
h := &mocks.IHeimdallClient{}
h.On("FetchWithRetry", "bor/span/1", "").Return(res, nil)
h.On(
"FetchStateSyncEvents",
mock.AnythingOfType("uint64"),
mock.AnythingOfType("int64")).Return([]*bor.EventRecordWithTime{getSampleEventRecord(t)}, nil)
h.On("FetchLatestCheckpoint").Maybe().Return(mock.Anything, nil)
func getMockedHeimdallClient(t *testing.T) (*mocks.MockIHeimdallClient, *bor.HeimdallSpan, *gomock.Controller) {
ctrl := gomock.NewController(t)
h := mocks.NewMockIHeimdallClient(ctrl)
return h, heimdallSpan
res, heimdallSpan := loadSpanFromFile(t)
h.EXPECT().FetchWithRetry(spanPath, "").Return(res, nil).AnyTimes()
h.EXPECT().FetchStateSyncEvents(gomock.Any(), gomock.Any()).Return(getEventRecords(t), nil).AnyTimes()
return h, heimdallSpan, ctrl
}
func generateFakeStateSyncEvents(sample *bor.EventRecordWithTime, count int) []*bor.EventRecordWithTime {
@ -299,6 +298,16 @@ func getSampleEventRecord(t *testing.T) *bor.EventRecordWithTime {
return _eventRecords[0]
}
func getEventRecords(t *testing.T) []*bor.EventRecordWithTime {
res := stateSyncEventsPayload(t)
var _eventRecords []*bor.EventRecordWithTime
if err := json.Unmarshal(res.Result, &_eventRecords); err != nil {
t.Fatalf("%s", err)
}
return _eventRecords
}
// TestEIP1559Transition tests the following:
//
// 1. A transaction whose gasFeeCap is greater than the baseFee is valid.
@ -503,6 +512,7 @@ func TestEIP1559Transition(t *testing.T) {
tx, _ = types.SignTx(tx, signer, key3)
b.AddTx(tx)
})
if n, err := chain.InsertChain(blocks); err != nil {

View file

@ -1,110 +1,107 @@
// Code generated by mockery v2.10.0. DO NOT EDIT.
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/ethereum/go-ethereum/consensus/bor (interfaces: IHeimdallClient)
// Package mocks is a generated GoMock package.
package mocks
import (
reflect "reflect"
bor "github.com/ethereum/go-ethereum/consensus/bor"
mock "github.com/stretchr/testify/mock"
gomock "github.com/golang/mock/gomock"
)
// IHeimdallClient is an autogenerated mock type for the IHeimdallClient type
type IHeimdallClient struct {
mock.Mock
// MockIHeimdallClient is a mock of IHeimdallClient interface.
type MockIHeimdallClient struct {
ctrl *gomock.Controller
recorder *MockIHeimdallClientMockRecorder
}
// Close provides a mock function with given fields:
func (_m *IHeimdallClient) Close() {
_m.Called()
// MockIHeimdallClientMockRecorder is the mock recorder for MockIHeimdallClient.
type MockIHeimdallClientMockRecorder struct {
mock *MockIHeimdallClient
}
// Fetch provides a mock function with given fields: path, query
func (_m *IHeimdallClient) Fetch(path string, query string) (*bor.ResponseWithHeight, error) {
ret := _m.Called(path, query)
var r0 *bor.ResponseWithHeight
if rf, ok := ret.Get(0).(func(string, string) *bor.ResponseWithHeight); ok {
r0 = rf(path, query)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*bor.ResponseWithHeight)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string) error); ok {
r1 = rf(path, query)
} else {
r1 = ret.Error(1)
}
return r0, r1
// NewMockIHeimdallClient creates a new mock instance.
func NewMockIHeimdallClient(ctrl *gomock.Controller) *MockIHeimdallClient {
mock := &MockIHeimdallClient{ctrl: ctrl}
mock.recorder = &MockIHeimdallClientMockRecorder{mock}
return mock
}
// FetchLatestCheckpoint provides a mock function with given fields:
func (_m *IHeimdallClient) FetchLatestCheckpoint() (*bor.Checkpoint, error) {
ret := _m.Called()
var r0 *bor.Checkpoint
if rf, ok := ret.Get(0).(func() *bor.Checkpoint); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*bor.Checkpoint)
}
}
var r1 error
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockIHeimdallClient) EXPECT() *MockIHeimdallClientMockRecorder {
return m.recorder
}
// FetchStateSyncEvents provides a mock function with given fields: fromID, to
func (_m *IHeimdallClient) FetchStateSyncEvents(fromID uint64, to int64) ([]*bor.EventRecordWithTime, error) {
ret := _m.Called(fromID, to)
var r0 []*bor.EventRecordWithTime
if rf, ok := ret.Get(0).(func(uint64, int64) []*bor.EventRecordWithTime); ok {
r0 = rf(fromID, to)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*bor.EventRecordWithTime)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(uint64, int64) error); ok {
r1 = rf(fromID, to)
} else {
r1 = ret.Error(1)
}
return r0, r1
// Close mocks base method.
func (m *MockIHeimdallClient) Close() {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Close")
}
// FetchWithRetry provides a mock function with given fields: path, query
func (_m *IHeimdallClient) FetchWithRetry(path string, query string) (*bor.ResponseWithHeight, error) {
ret := _m.Called(path, query)
var r0 *bor.ResponseWithHeight
if rf, ok := ret.Get(0).(func(string, string) *bor.ResponseWithHeight); ok {
r0 = rf(path, query)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*bor.ResponseWithHeight)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string) error); ok {
r1 = rf(path, query)
} else {
r1 = ret.Error(1)
}
return r0, r1
// Close indicates an expected call of Close.
func (mr *MockIHeimdallClientMockRecorder) Close() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockIHeimdallClient)(nil).Close))
}
// Fetch mocks base method.
func (m *MockIHeimdallClient) Fetch(arg0, arg1 string) (*bor.ResponseWithHeight, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Fetch", arg0, arg1)
ret0, _ := ret[0].(*bor.ResponseWithHeight)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Fetch indicates an expected call of Fetch.
func (mr *MockIHeimdallClientMockRecorder) Fetch(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fetch", reflect.TypeOf((*MockIHeimdallClient)(nil).Fetch), arg0, arg1)
}
// FetchLatestCheckpoint mocks base method.
func (m *MockIHeimdallClient) FetchLatestCheckpoint() (*bor.Checkpoint, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchLatestCheckpoint")
ret0, _ := ret[0].(*bor.Checkpoint)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// FetchLatestCheckpoint indicates an expected call of FetchLatestCheckpoint.
func (mr *MockIHeimdallClientMockRecorder) FetchLatestCheckpoint() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchLatestCheckpoint", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchLatestCheckpoint))
}
// FetchStateSyncEvents mocks base method.
func (m *MockIHeimdallClient) FetchStateSyncEvents(arg0 uint64, arg1 int64) ([]*bor.EventRecordWithTime, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchStateSyncEvents", arg0, arg1)
ret0, _ := ret[0].([]*bor.EventRecordWithTime)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// FetchStateSyncEvents indicates an expected call of FetchStateSyncEvents.
func (mr *MockIHeimdallClientMockRecorder) FetchStateSyncEvents(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchStateSyncEvents", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchStateSyncEvents), arg0, arg1)
}
// FetchWithRetry mocks base method.
func (m *MockIHeimdallClient) FetchWithRetry(arg0, arg1 string) (*bor.ResponseWithHeight, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchWithRetry", arg0, arg1)
ret0, _ := ret[0].(*bor.ResponseWithHeight)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// FetchWithRetry indicates an expected call of FetchWithRetry.
func (mr *MockIHeimdallClientMockRecorder) FetchWithRetry(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchWithRetry", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchWithRetry), arg0, arg1)
}

7
tests/deps/fake.go Normal file
View file

@ -0,0 +1,7 @@
package deps
// it is a fake file to lock deps
//nolint:typecheck
import (
_ "github.com/golang/mock/mockgen/model"
)