diff --git a/api/coreservice_test.go b/api/coreservice_test.go index 5c05c7e6dd..27277e4914 100644 --- a/api/coreservice_test.go +++ b/api/coreservice_test.go @@ -13,22 +13,29 @@ import ( "testing" "time" + . "github.com/agiledragon/gomonkey/v2" "github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/golang/mock/gomock" - "github.com/iotexproject/iotex-proto/golang/iotexapi" "github.com/pkg/errors" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" + "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-core/action" "github.com/iotexproject/iotex-core/actpool" "github.com/iotexproject/iotex-core/api/logfilter" "github.com/iotexproject/iotex-core/blockchain" + "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" "github.com/iotexproject/iotex-core/test/identityset" + "github.com/iotexproject/iotex-core/test/mock/mock_blockdao" "github.com/iotexproject/iotex-core/test/mock/mock_blockindex" + "github.com/iotexproject/iotex-core/test/mock/mock_envelope" "github.com/iotexproject/iotex-core/testutil" + "github.com/iotexproject/iotex-proto/golang/iotexapi" + "github.com/iotexproject/iotex-proto/golang/iotextypes" ) func TestLogsInRange(t *testing.T) { @@ -387,3 +394,94 @@ func TestProofAndCompareReverseActions(t *testing.T) { }) } } + +func TestReverseActionsInBlock(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + var ( + blkDAO = mock_blockdao.NewMockBlockDAO(ctrl) + envelope = mock_envelope.NewMockEnvelope(ctrl) + core = &coreService{dao: blkDAO} + blk = &block.Block{ + Header: block.Header{}, + Body: block.Body{ + Actions: []*action.SealedEnvelope{&action.SealedEnvelope{Envelope: envelope}}, + }, + Footer: block.Footer{}, + Receipts: nil, + } + receiptes = []*action.Receipt{ + &action.Receipt{ + ActionHash: hash.ZeroHash256, + }, + } + ) + + t.Run("CheckParams", func(t *testing.T) { + t.Run("ReverseStartGreaterThanSize", func(t *testing.T) { + actions := core.reverseActionsInBlock(blk, 2, 1) + require.Empty(actions) + }) + + t.Run("CountIsZero", func(t *testing.T) { + actions := core.reverseActionsInBlock(blk, 1, 0) + require.Empty(actions) + }) + }) + + t.Run("FailedToGetReceiptFromDAO", func(t *testing.T) { + blkDAO.EXPECT().GetReceipts(gomock.Any()).Return(nil, errors.New(t.Name())).Times(1) + actions := core.reverseActionsInBlock(blk, 0, 1) + require.Empty(actions) + }) + + t.Run("ForeachActions", func(t *testing.T) { + t.Run("FailedToHash", func(t *testing.T) { + p := NewPatches() + defer p.Reset() + + p = p.ApplyMethodReturn(&action.SealedEnvelope{}, "Hash", nil, errors.New(t.Name())) + + blkDAO.EXPECT().GetReceipts(gomock.Any()).Return(receiptes, nil).Times(1) + + actions := core.reverseActionsInBlock(blk, 0, 1) + require.Empty(actions) + }) + + t.Run("FailedToGetReceiptFromMap", func(t *testing.T) { + p := NewPatches() + defer p.Reset() + + p = p.ApplyMethodReturn(&action.SealedEnvelope{}, "Hash", hash.BytesToHash256([]byte("test")), nil) + + blkDAO.EXPECT().GetReceipts(gomock.Any()).Return(receiptes, nil).Times(1) + + actions := core.reverseActionsInBlock(blk, 0, 1) + require.Empty(actions) + }) + + t.Run("ReverseActionsInBlockSuccess", func(t *testing.T) { + p := NewPatches() + defer p.Reset() + + p = p.ApplyMethodReturn(&action.SealedEnvelope{}, "Hash", hash.ZeroHash256, nil) + p = p.ApplyMethodReturn(&action.SealedEnvelope{}, "SenderAddress", identityset.Address(1)) + p = p.ApplyMethodReturn(&action.SealedEnvelope{}, "Proto", &iotextypes.Action{}) + p = p.ApplyMethodReturn(&block.Header{}, "BlockHeaderCoreProto", &iotextypes.BlockHeaderCore{Timestamp: timestamppb.Now()}) + + blkDAO.EXPECT().GetReceipts(gomock.Any()).Return(receiptes, nil).Times(1) + envelope.EXPECT().GasPrice().Return(big.NewInt(1)).Times(1) + actions := core.reverseActionsInBlock(blk, 0, 1) + require.Equal(1, len(actions)) + }) + }) + + t.Run("StartIsNotZero", func(t *testing.T) { + blkDAO.EXPECT().GetReceipts(gomock.Any()).Return(nil, errors.New(t.Name())).Times(1) + blk.Actions = append(blk.Actions, &action.SealedEnvelope{}) + actions := core.reverseActionsInBlock(blk, 0, 1) + require.Empty(actions) + }) +} diff --git a/test/mock/mock_envelope/mock_envelope.go b/test/mock/mock_envelope/mock_envelope.go new file mode 100644 index 0000000000..243baf2a40 --- /dev/null +++ b/test/mock/mock_envelope/mock_envelope.go @@ -0,0 +1,218 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: action/Envelope.go + +// Package mock_envelope is a generated GoMock package. +package mock_envelope + +import ( + big "math/big" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + action "github.com/iotexproject/iotex-core/action" + iotextypes "github.com/iotexproject/iotex-proto/golang/iotextypes" +) + +// MockEnvelope is a mock of Envelope interface. +type MockEnvelope struct { + ctrl *gomock.Controller + recorder *MockEnvelopeMockRecorder +} + +// MockEnvelopeMockRecorder is the mock recorder for MockEnvelope. +type MockEnvelopeMockRecorder struct { + mock *MockEnvelope +} + +// NewMockEnvelope creates a new mock instance. +func NewMockEnvelope(ctrl *gomock.Controller) *MockEnvelope { + mock := &MockEnvelope{ctrl: ctrl} + mock.recorder = &MockEnvelopeMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockEnvelope) EXPECT() *MockEnvelopeMockRecorder { + return m.recorder +} + +// Action mocks base method. +func (m *MockEnvelope) Action() action.Action { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Action") + ret0, _ := ret[0].(action.Action) + return ret0 +} + +// Action indicates an expected call of Action. +func (mr *MockEnvelopeMockRecorder) Action() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Action", reflect.TypeOf((*MockEnvelope)(nil).Action)) +} + +// ChainID mocks base method. +func (m *MockEnvelope) ChainID() uint32 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChainID") + ret0, _ := ret[0].(uint32) + return ret0 +} + +// ChainID indicates an expected call of ChainID. +func (mr *MockEnvelopeMockRecorder) ChainID() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainID", reflect.TypeOf((*MockEnvelope)(nil).ChainID)) +} + +// Cost mocks base method. +func (m *MockEnvelope) Cost() (*big.Int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Cost") + ret0, _ := ret[0].(*big.Int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Cost indicates an expected call of Cost. +func (mr *MockEnvelopeMockRecorder) Cost() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Cost", reflect.TypeOf((*MockEnvelope)(nil).Cost)) +} + +// Destination mocks base method. +func (m *MockEnvelope) Destination() (string, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Destination") + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// Destination indicates an expected call of Destination. +func (mr *MockEnvelopeMockRecorder) Destination() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Destination", reflect.TypeOf((*MockEnvelope)(nil).Destination)) +} + +// GasLimit mocks base method. +func (m *MockEnvelope) GasLimit() uint64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GasLimit") + ret0, _ := ret[0].(uint64) + return ret0 +} + +// GasLimit indicates an expected call of GasLimit. +func (mr *MockEnvelopeMockRecorder) GasLimit() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GasLimit", reflect.TypeOf((*MockEnvelope)(nil).GasLimit)) +} + +// GasPrice mocks base method. +func (m *MockEnvelope) GasPrice() *big.Int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GasPrice") + ret0, _ := ret[0].(*big.Int) + return ret0 +} + +// GasPrice indicates an expected call of GasPrice. +func (mr *MockEnvelopeMockRecorder) GasPrice() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GasPrice", reflect.TypeOf((*MockEnvelope)(nil).GasPrice)) +} + +// IntrinsicGas mocks base method. +func (m *MockEnvelope) IntrinsicGas() (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IntrinsicGas") + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IntrinsicGas indicates an expected call of IntrinsicGas. +func (mr *MockEnvelopeMockRecorder) IntrinsicGas() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IntrinsicGas", reflect.TypeOf((*MockEnvelope)(nil).IntrinsicGas)) +} + +// LoadProto mocks base method. +func (m *MockEnvelope) LoadProto(pbAct *iotextypes.ActionCore) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadProto", pbAct) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadProto indicates an expected call of LoadProto. +func (mr *MockEnvelopeMockRecorder) LoadProto(pbAct interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadProto", reflect.TypeOf((*MockEnvelope)(nil).LoadProto), pbAct) +} + +// Nonce mocks base method. +func (m *MockEnvelope) Nonce() uint64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Nonce") + ret0, _ := ret[0].(uint64) + return ret0 +} + +// Nonce indicates an expected call of Nonce. +func (mr *MockEnvelopeMockRecorder) Nonce() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Nonce", reflect.TypeOf((*MockEnvelope)(nil).Nonce)) +} + +// Proto mocks base method. +func (m *MockEnvelope) Proto() *iotextypes.ActionCore { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Proto") + ret0, _ := ret[0].(*iotextypes.ActionCore) + return ret0 +} + +// Proto indicates an expected call of Proto. +func (mr *MockEnvelopeMockRecorder) Proto() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Proto", reflect.TypeOf((*MockEnvelope)(nil).Proto)) +} + +// SetChainID mocks base method. +func (m *MockEnvelope) SetChainID(chainID uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetChainID", chainID) +} + +// SetChainID indicates an expected call of SetChainID. +func (mr *MockEnvelopeMockRecorder) SetChainID(chainID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetChainID", reflect.TypeOf((*MockEnvelope)(nil).SetChainID), chainID) +} + +// SetNonce mocks base method. +func (m *MockEnvelope) SetNonce(n uint64) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetNonce", n) +} + +// SetNonce indicates an expected call of SetNonce. +func (mr *MockEnvelopeMockRecorder) SetNonce(n interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNonce", reflect.TypeOf((*MockEnvelope)(nil).SetNonce), n) +} + +// Version mocks base method. +func (m *MockEnvelope) Version() uint32 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Version") + ret0, _ := ret[0].(uint32) + return ret0 +} + +// Version indicates an expected call of Version. +func (mr *MockEnvelopeMockRecorder) Version() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Version", reflect.TypeOf((*MockEnvelope)(nil).Version)) +}