Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(halo/evmstaking2): unit tests for unhappy paths #2591

Merged
merged 7 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 71 additions & 87 deletions halo/evmstaking2/keeper/keeper_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"
"testing"

"github.com/omni-network/omni/halo/evmstaking2/testutil"
"github.com/omni-network/omni/halo/evmstaking2/types"
"github.com/omni-network/omni/lib/ethclient"
"github.com/omni-network/omni/lib/netconf"
Expand All @@ -21,6 +22,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
stypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
)

//nolint:paralleltest // Asserting insertion ids of sequential writes
Expand Down Expand Up @@ -51,7 +53,7 @@ func TestInsertAndDeleteEVMEvents(t *testing.T) {

deliverInterval := int64(5)

keeper, ctx := setupKeeper(t, deliverInterval, nil, nil, nil, nil, nil)
keeper, ctx := setupKeeper(t, deliverInterval, nil, nil)

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
Expand Down Expand Up @@ -101,9 +103,14 @@ func TestDeliveryWithBrokenServer(t *testing.T) {
ethclient.WithMockSelfDelegation(privKey.PubKey(), ethStake),
)
require.NoError(t, err)
sServer := brokenMsgServerStub{errors.New("unconditional error")}

keeper, ctx := setupKeeper(t, deliverInterval, ethClientMock, new(authKeeperStub), new(bankKeeperStub), new(stakingKeeperStub), &sServer)
ctrl := gomock.NewController(t)
sServerMock := testutil.NewMockStakingMsgServer(ctrl)
err = errors.New("unconditional error")
sServerMock.EXPECT().CreateValidator(gomock.Any(), gomock.Any()).AnyTimes().Return(nil, err)
sServerMock.EXPECT().Delegate(gomock.Any(), gomock.Any()).AnyTimes().Return(nil, err)

keeper, ctx := setupKeeper(t, deliverInterval, ethClientMock, sServerMock)

var hash common.Hash
events, err := keeper.Prepare(ctx, hash)
Expand All @@ -117,7 +124,7 @@ func TestDeliveryWithBrokenServer(t *testing.T) {

for _, event := range events {
err := keeper.parseAndDeliver(ctx, &event)
require.Contains(t, err.Error(), sServer.err.Error())
require.Contains(t, err.Error(), "unconditional error")
}
}

Expand All @@ -135,7 +142,12 @@ func TestDeliveryOfInvalidEvents(t *testing.T) {
)
require.NoError(t, err)

keeper, ctx := setupKeeper(t, deliverInterval, ethClientMock, new(authKeeperStub), new(bankKeeperStub), new(stakingKeeperStub), new(msgServerStub))
ctrl := gomock.NewController(t)
sServerMock := testutil.NewMockStakingMsgServer(ctrl)
sServerMock.EXPECT().CreateValidator(gomock.Any(), gomock.Any()).AnyTimes().Return(nil, nil)
sServerMock.EXPECT().Delegate(gomock.Any(), gomock.Any()).AnyTimes().Return(nil, nil)

keeper, ctx := setupKeeper(t, deliverInterval, ethClientMock, sServerMock)

var hash common.Hash
events, err := keeper.Prepare(ctx, hash)
Expand Down Expand Up @@ -197,9 +209,25 @@ func TestHappyPathDelivery(t *testing.T) {
)
require.NoError(t, err)

sServer := new(msgServerStub)

keeper, ctx := setupKeeper(t, deliverInterval, ethClientMock, new(authKeeperStub), new(bankKeeperStub), new(stakingKeeperStub), sServer)
var delegateMsgBuffer []*stypes.MsgDelegate
var createValidatorMsgBuffer []*stypes.MsgCreateValidator

ctrl := gomock.NewController(t)
sServerMock := testutil.NewMockStakingMsgServer(ctrl)
sServerMock.EXPECT().
CreateValidator(gomock.Any(), gomock.Any()).
AnyTimes().Do(func(ctx context.Context, msg *stypes.MsgCreateValidator) {
createValidatorMsgBuffer = append(createValidatorMsgBuffer, msg)
}).
Return(new(stypes.MsgCreateValidatorResponse), nil)
sServerMock.EXPECT().
Delegate(gomock.Any(), gomock.Any()).
AnyTimes().Do(func(ctx context.Context, msg *stypes.MsgDelegate) {
delegateMsgBuffer = append(delegateMsgBuffer, msg)
}).
Return(new(stypes.MsgDelegateResponse), nil)

keeper, ctx := setupKeeper(t, deliverInterval, ethClientMock, sServerMock)

var hash common.Hash
events, err := keeper.Prepare(ctx, hash)
Expand Down Expand Up @@ -231,8 +259,8 @@ func TestHappyPathDelivery(t *testing.T) {
}

// Assert that the message was delivered to the msg server.
require.Len(t, sServer.delegateMsgBuffer, 1)
msg := sServer.delegateMsgBuffer[0]
require.Len(t, delegateMsgBuffer, 1)
msg := delegateMsgBuffer[0]
// Sanity check of addresses
require.Len(t, msg.DelegatorAddress, 45)
require.Len(t, msg.ValidatorAddress, 52)
Expand All @@ -241,8 +269,8 @@ func TestHappyPathDelivery(t *testing.T) {
stake := sdk.NewInt64Coin("stake", ethStake*1000000000000000000)
require.Equal(t, msg.Amount, stake)

require.Len(t, sServer.createValidatorMsgBuffer, 1)
msg2 := sServer.createValidatorMsgBuffer[0]
require.Len(t, createValidatorMsgBuffer, 1)
msg2 := createValidatorMsgBuffer[0]
// Sanity check of addresses
require.Len(t, msg2.ValidatorAddress, 52)
require.True(t, strings.HasPrefix(msg2.ValidatorAddress, "cosmosvaloper"), msg.ValidatorAddress)
Expand All @@ -268,9 +296,6 @@ func setupKeeper(
t *testing.T,
deliverInterval int64,
ethCl ethclient.EngineClient,
aKeeper types.AuthKeeper,
bKeeper types.BankKeeper,
sKeeper types.StakingKeeper,
sServer types.StakingMsgServer,
) (*Keeper, sdk.Context) {
t.Helper()
Expand All @@ -281,85 +306,44 @@ func setupKeeper(
ctx = ctx.WithBlockHeight(1)
ctx = ctx.WithChainID(netconf.Simnet.Static().OmniConsensusChainIDStr())

ctrl := gomock.NewController(t)

authKeeperMock := testutil.NewMockAuthKeeper(ctrl)
authKeeperMock.EXPECT().HasAccount(gomock.Any(), gomock.Any()).AnyTimes().Return(true)
authKeeperMock.EXPECT().NewAccountWithAddress(gomock.Any(), gomock.Any()).AnyTimes().Return(nil)

bKeeperMock := testutil.NewMockBankKeeper(ctrl)
bKeeperMock.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil)
bKeeperMock.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil)

sKeeperMock := testutil.NewMockStakingKeeper(ctrl)
var seenValidators map[string]bool
sKeeperMock.EXPECT().GetValidator(gomock.Any(), gomock.Any()).AnyTimes().
DoAndReturn(func(_ context.Context, addr sdk.ValAddress) (stypes.Validator, error) {
if seenValidators == nil {
seenValidators = make(map[string]bool)
}

hexAddr := string(addr)

if _, found := seenValidators[hexAddr]; found {
return stypes.Validator{}, nil
}
seenValidators[hexAddr] = true

return stypes.Validator{}, errors.New("validator does not exist")
})

k, err := NewKeeper(
storeSvc,
ethCl,
aKeeper,
bKeeper,
sKeeper,
authKeeperMock,
bKeeperMock,
sKeeperMock,
sServer,
deliverInterval,
)
require.NoError(t, err, "new keeper")

return k, ctx
}

type stakingKeeperStub struct {
validators map[string]bool
}

// GetValidator tracks accessed addresses, returning an error for unseen addresses.
func (m *stakingKeeperStub) GetValidator(_ context.Context, addr sdk.ValAddress) (stypes.Validator, error) {
if m.validators == nil {
m.validators = make(map[string]bool)
}

hexAddr := string(addr)

if _, found := m.validators[hexAddr]; found {
return stypes.Validator{}, nil
}
m.validators[hexAddr] = true

return stypes.Validator{}, errors.New("validator does not exist")
}

type authKeeperStub struct{}

func (authKeeperStub) HasAccount(context.Context, sdk.AccAddress) bool {
return true
}

func (authKeeperStub) NewAccountWithAddress(context.Context, sdk.AccAddress) sdk.AccountI {
return nil
}

func (authKeeperStub) SetAccount(context.Context, sdk.AccountI) {}

type bankKeeperStub struct{}

func (bankKeeperStub) MintCoins(context.Context, string, sdk.Coins) error {
return nil
}

func (bankKeeperStub) SendCoinsFromModuleToAccount(context.Context, string, sdk.AccAddress, sdk.Coins) error {
return nil
}

type msgServerStub struct {
createValidatorMsgBuffer []*stypes.MsgCreateValidator
delegateMsgBuffer []*stypes.MsgDelegate
}

func (s *msgServerStub) CreateValidator(ctx context.Context, msg *stypes.MsgCreateValidator) (*stypes.MsgCreateValidatorResponse, error) {
s.createValidatorMsgBuffer = append(s.createValidatorMsgBuffer, msg)
return new(stypes.MsgCreateValidatorResponse), nil
}

func (s *msgServerStub) Delegate(ctx context.Context, msg *stypes.MsgDelegate) (*stypes.MsgDelegateResponse, error) {
s.delegateMsgBuffer = append(s.delegateMsgBuffer, msg)
return new(stypes.MsgDelegateResponse), nil
}

type brokenMsgServerStub struct {
err error
}

func (s *brokenMsgServerStub) CreateValidator(ctx context.Context, msg *stypes.MsgCreateValidator) (*stypes.MsgCreateValidatorResponse, error) {
return nil, s.err
}

func (s *brokenMsgServerStub) Delegate(ctx context.Context, msg *stypes.MsgDelegate) (*stypes.MsgDelegateResponse, error) {
return nil, s.err
}
Loading
Loading