diff --git a/Makefile b/Makefile index 6469b8510f..b283928b81 100644 --- a/Makefile +++ b/Makefile @@ -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' diff --git a/consensus/bor/rest.go b/consensus/bor/rest.go index 9bec44c62f..86f6146e77 100644 --- a/consensus/bor/rest.go +++ b/consensus/bor/rest.go @@ -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) diff --git a/go.mod b/go.mod index edd6d6887a..176df53a40 100644 --- a/go.mod +++ b/go.mod @@ -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 ) diff --git a/go.sum b/go.sum index 19a6002886..ec2f200044 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/tests/bor/bor_test.go b/tests/bor/bor_test.go index 460b296f31..b922ff9c41 100644 --- a/tests/bor/bor_test.go +++ b/tests/bor/bor_test.go @@ -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 { diff --git a/tests/bor/mocks/IHeimdallClient.go b/tests/bor/mocks/IHeimdallClient.go index 3ee599bb2e..9420c261fb 100644 --- a/tests/bor/mocks/IHeimdallClient.go +++ b/tests/bor/mocks/IHeimdallClient.go @@ -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) } diff --git a/tests/deps/fake.go b/tests/deps/fake.go new file mode 100644 index 0000000000..cd04ffa070 --- /dev/null +++ b/tests/deps/fake.go @@ -0,0 +1,7 @@ +package deps + +// it is a fake file to lock deps +//nolint:typecheck +import ( + _ "github.com/golang/mock/mockgen/model" +)