From f79a66b493474562edc20ab5131685f8c2c26e6c Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Thu, 11 Aug 2022 18:19:40 -0700 Subject: [PATCH 01/24] dummies and keeper construction --- x/ccv/provider/keeper/common_test.go | 212 +++++++++++++++++++++++++++ x/ccv/provider/keeper/keeper_test.go | 23 +-- x/ccv/types/keys.go | 6 + 3 files changed, 230 insertions(+), 11 deletions(-) create mode 100644 x/ccv/provider/keeper/common_test.go diff --git a/x/ccv/provider/keeper/common_test.go b/x/ccv/provider/keeper/common_test.go new file mode 100644 index 0000000000..f041819c61 --- /dev/null +++ b/x/ccv/provider/keeper/common_test.go @@ -0,0 +1,212 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/store" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + auth "github.com/cosmos/cosmos-sdk/x/auth/types" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + conntypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" + "github.com/cosmos/interchain-security/x/ccv/provider/keeper" + "github.com/cosmos/interchain-security/x/ccv/types" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmdb "github.com/tendermint/tm-db" +) + +// Constructs a keeper and context object for unit tests, backed by an in-memory db. +func getKeeperAndCtx(t testing.TB) (keeper.Keeper, sdk.Context) { + + cdc, storeKey, paramsSubspace, stateStore := setupInMemKeeper(t) + + k := keeper.NewKeeper( + cdc, + storeKey, + paramsSubspace, + capabilitykeeper.ScopedKeeper{}, + DummyChannelKeeper{}, + DummyPortKeeper{}, + DummyConnectionKeeper{}, + DummyClientKeeper{}, + DummyStakingKeeper{}, + DummySlashingKeeper{}, + DummyAccountKeeper{}, + "", + ) + ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) + return k, ctx +} + +// Constructs a keeper and context object for unit tests, backed by an in-memory db, with ability to pass mocked keepers. +// Note: Use the dummy types defined in this file for keepers you don't wish to mock. +func getKeeperAndCtxWithMocks(t testing.TB, + capabilityKeeper capabilitykeeper.ScopedKeeper, + channelKeeper types.ChannelKeeper, + portKeeper types.PortKeeper, + connectionKeeper types.ConnectionKeeper, + clientKeeper types.ClientKeeper, + stakingKeeper types.StakingKeeper, + slashingKeeper types.SlashingKeeper, + accountKeeper types.AccountKeeper, +) (keeper.Keeper, sdk.Context) { + + cdc, storeKey, paramsSubspace, stateStore := setupInMemKeeper(t) + + k := keeper.NewKeeper( + cdc, + storeKey, + paramsSubspace, + capabilityKeeper, + channelKeeper, + portKeeper, + connectionKeeper, + clientKeeper, + stakingKeeper, + slashingKeeper, + accountKeeper, + "", + ) + ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) + return k, ctx +} + +func setupInMemKeeper(t testing.TB) (*codec.ProtoCodec, *storetypes.KVStoreKey, paramstypes.Subspace, storetypes.CommitMultiStore) { + storeKey := sdk.NewKVStoreKey(types.StoreKey) + memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) + + db := tmdb.NewMemDB() + stateStore := store.NewCommitMultiStore(db) + stateStore.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db) + stateStore.MountStoreWithDB(memStoreKey, sdk.StoreTypeMemory, nil) + require.NoError(t, stateStore.LoadLatestVersion()) + + registry := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(registry) + + paramsSubspace := paramstypes.NewSubspace(cdc, + codec.NewLegacyAmino(), + storeKey, + memStoreKey, + paramstypes.ModuleName, + ) + return cdc, storeKey, paramsSubspace, stateStore +} + +// TODO: add this to readme, not here. +// These are Dummy and not mock structs being we're not injecting any functionality, +// just satisfying constructors. if one wishes to mock functionality, it's still possible +// to replace one of the keepers with a mocked one + +type DummyChannelKeeper struct{} + +func (DummyChannelKeeper) GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) { + return channel, found +} +func (DummyChannelKeeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) { + return 0, false +} +func (DummyChannelKeeper) SendPacket(ctx sdk.Context, channelCap *capabilitytypes.Capability, packet ibcexported.PacketI) error { + return nil +} +func (DummyChannelKeeper) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, acknowledgement ibcexported.Acknowledgement) error { + return nil +} +func (DummyChannelKeeper) ChanCloseInit(ctx sdk.Context, portID, channelID string, chanCap *capabilitytypes.Capability) error { + return nil +} + +type DummyPortKeeper struct{} + +func (DummyPortKeeper) BindPort(ctx sdk.Context, portID string) *capabilitytypes.Capability { + return &capabilitytypes.Capability{} +} + +type DummyConnectionKeeper struct{} + +func (DummyConnectionKeeper) GetConnection(ctx sdk.Context, connectionID string) (conntypes.ConnectionEnd, bool) { + return conntypes.ConnectionEnd{}, false +} + +type DummyClientKeeper struct{} + +func (d DummyClientKeeper) CreateClient(ctx sdk.Context, clientState ibcexported.ClientState, consensusState ibcexported.ConsensusState) (string, error) { + return "", nil +} +func (d DummyClientKeeper) GetClientState(ctx sdk.Context, clientID string) (ibcexported.ClientState, bool) { + return nil, false +} +func (d DummyClientKeeper) GetLatestClientConsensusState(ctx sdk.Context, clientID string) (ibcexported.ConsensusState, bool) { + return nil, false +} +func (d DummyClientKeeper) GetSelfConsensusState(ctx sdk.Context, height ibcexported.Height) (ibcexported.ConsensusState, error) { + return nil, nil +} + +type DummyStakingKeeper struct{} + +func (m DummyStakingKeeper) GetValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate { + return nil +} +func (m DummyStakingKeeper) UnbondingCanComplete(ctx sdk.Context, id uint64) error { + return nil +} +func (m DummyStakingKeeper) UnbondingTime(ctx sdk.Context) time.Duration { + return 0 +} +func (m DummyStakingKeeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator stakingtypes.Validator, found bool) { + return stakingtypes.Validator{}, false +} +func (m DummyStakingKeeper) Jail(sdk.Context, sdk.ConsAddress) { +} +func (m DummyStakingKeeper) Slash(sdk.Context, sdk.ConsAddress, int64, int64, sdk.Dec, stakingtypes.InfractionType) { +} +func (m DummyStakingKeeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, found bool) { + return stakingtypes.Validator{}, false +} +func (m DummyStakingKeeper) IterateLastValidatorPowers(ctx sdk.Context, cb func(addr sdk.ValAddress, power int64) (stop bool)) { +} +func (m DummyStakingKeeper) PowerReduction(ctx sdk.Context) sdk.Int { + return sdk.ZeroInt() +} +func (m DummyStakingKeeper) PutUnbondingOnHold(ctx sdk.Context, id uint64) error { + return nil +} + +type DummySlashingKeeper struct{} + +func (d DummySlashingKeeper) JailUntil(sdk.Context, sdk.ConsAddress, time.Time) {} +func (d DummySlashingKeeper) GetValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress) (info slashingtypes.ValidatorSigningInfo, found bool) { + return slashingtypes.ValidatorSigningInfo{}, false +} +func (d DummySlashingKeeper) DowntimeJailDuration(sdk.Context) time.Duration { + return 0 +} +func (d DummySlashingKeeper) SlashFractionDowntime(sdk.Context) sdk.Dec { + return sdk.Dec{} +} +func (d DummySlashingKeeper) SlashFractionDoubleSign(ctx sdk.Context) (res sdk.Dec) { + return res +} +func (d DummySlashingKeeper) Tombstone(sdk.Context, sdk.ConsAddress) {} +func (d DummySlashingKeeper) IsTombstoned(sdk.Context, sdk.ConsAddress) bool { + return false +} + +type DummyAccountKeeper struct{} + +func (d DummyAccountKeeper) GetModuleAccount(ctx sdk.Context, name string) auth.ModuleAccountI { + return nil +} diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 98186e81e0..bbe33d01df 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -31,6 +31,7 @@ import ( tmprotocrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" tmtypes "github.com/tendermint/tendermint/types" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" ) @@ -531,21 +532,21 @@ func (suite *KeeperTestSuite) TestIterateOverUnbondingOpIndex() { suite.Require().Equal(len(unbondingOpIndex), i) } -func (suite *KeeperTestSuite) TestMaturedUnbondingOps() { - providerKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper +func TestMaturedUnbondingOps(t *testing.T) { + keeper, ctx := getKeeperAndCtx(t) - ids, err := providerKeeper.GetMaturedUnbondingOps(suite.providerChain.GetContext()) - suite.Require().NoError(err) - suite.Require().Nil(ids) + ids, err := keeper.GetMaturedUnbondingOps(ctx) + require.NoError(t, err) + require.Nil(t, ids) unbondingOpIds := []uint64{0, 1, 2, 3, 4, 5, 6} - err = providerKeeper.AppendMaturedUnbondingOps(suite.providerChain.GetContext(), unbondingOpIds) - suite.Require().NoError(err) + err = keeper.AppendMaturedUnbondingOps(ctx, unbondingOpIds) + require.NoError(t, err) - ids, err = providerKeeper.EmptyMaturedUnbondingOps(suite.providerChain.GetContext()) - suite.Require().NoError(err) - suite.Require().Equal(len(unbondingOpIds), len(ids)) + ids, err = keeper.EmptyMaturedUnbondingOps(ctx) + require.NoError(t, err) + require.Equal(t, len(unbondingOpIds), len(ids)) for i := 0; i < len(unbondingOpIds); i++ { - suite.Require().Equal(unbondingOpIds[i], ids[i]) + require.Equal(t, unbondingOpIds[i], ids[i]) } } diff --git a/x/ccv/types/keys.go b/x/ccv/types/keys.go index 00b0e47d28..91521fb0b8 100644 --- a/x/ccv/types/keys.go +++ b/x/ccv/types/keys.go @@ -9,4 +9,10 @@ const ( Version = "1" RouterKey = ModuleName + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // MemStoreKey defines the in-memory store key + MemStoreKey = "mem_ccv" ) From d30ca2f59ed52002770b17abd724daf576279c21 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Thu, 11 Aug 2022 18:20:52 -0700 Subject: [PATCH 02/24] cleans --- x/ccv/provider/keeper/common_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/x/ccv/provider/keeper/common_test.go b/x/ccv/provider/keeper/common_test.go index f041819c61..9dea218109 100644 --- a/x/ccv/provider/keeper/common_test.go +++ b/x/ccv/provider/keeper/common_test.go @@ -105,11 +105,6 @@ func setupInMemKeeper(t testing.TB) (*codec.ProtoCodec, *storetypes.KVStoreKey, return cdc, storeKey, paramsSubspace, stateStore } -// TODO: add this to readme, not here. -// These are Dummy and not mock structs being we're not injecting any functionality, -// just satisfying constructors. if one wishes to mock functionality, it's still possible -// to replace one of the keepers with a mocked one - type DummyChannelKeeper struct{} func (DummyChannelKeeper) GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) { From f815819b9e27e506792a492e09376ad50b05d6b3 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Fri, 12 Aug 2022 10:35:20 -0700 Subject: [PATCH 03/24] dun works --- testutil/keeper/ccv.go | 1 - .../keeper/unit_test_helpers.go | 33 ++++++------- x/ccv/provider/keeper/keeper_test.go | 3 +- x/ccv/provider/keeper/params_test.go | 46 +++++++++++++++---- 4 files changed, 57 insertions(+), 26 deletions(-) delete mode 100644 testutil/keeper/ccv.go rename x/ccv/provider/keeper/common_test.go => testutil/keeper/unit_test_helpers.go (89%) diff --git a/testutil/keeper/ccv.go b/testutil/keeper/ccv.go deleted file mode 100644 index b55569d4a4..0000000000 --- a/testutil/keeper/ccv.go +++ /dev/null @@ -1 +0,0 @@ -package keeper diff --git a/x/ccv/provider/keeper/common_test.go b/testutil/keeper/unit_test_helpers.go similarity index 89% rename from x/ccv/provider/keeper/common_test.go rename to testutil/keeper/unit_test_helpers.go index 9dea218109..2e6a398716 100644 --- a/x/ccv/provider/keeper/common_test.go +++ b/testutil/keeper/unit_test_helpers.go @@ -1,4 +1,4 @@ -package keeper_test +package keeper import ( "testing" @@ -18,7 +18,7 @@ import ( conntypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" - "github.com/cosmos/interchain-security/x/ccv/provider/keeper" + providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" "github.com/cosmos/interchain-security/x/ccv/types" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" @@ -28,11 +28,11 @@ import ( ) // Constructs a keeper and context object for unit tests, backed by an in-memory db. -func getKeeperAndCtx(t testing.TB) (keeper.Keeper, sdk.Context) { +func GetProviderKeeperAndCtx(t testing.TB) (providerkeeper.Keeper, sdk.Context) { - cdc, storeKey, paramsSubspace, stateStore := setupInMemKeeper(t) + cdc, storeKey, paramsSubspace, ctx := SetupInMemKeeper(t) - k := keeper.NewKeeper( + k := providerkeeper.NewKeeper( cdc, storeKey, paramsSubspace, @@ -46,13 +46,16 @@ func getKeeperAndCtx(t testing.TB) (keeper.Keeper, sdk.Context) { DummyAccountKeeper{}, "", ) - ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) return k, ctx } -// Constructs a keeper and context object for unit tests, backed by an in-memory db, with ability to pass mocked keepers. +// Constructs a keeper for unit tests, backed by an in-memory db, with ability to pass mocked or otherwise manipulated parameters. // Note: Use the dummy types defined in this file for keepers you don't wish to mock. -func getKeeperAndCtxWithMocks(t testing.TB, +func GetProviderKeeperWithMocks(t testing.TB, + cdc *codec.ProtoCodec, + storeKey *storetypes.KVStoreKey, + paramsSubspace paramstypes.Subspace, + ctx sdk.Context, capabilityKeeper capabilitykeeper.ScopedKeeper, channelKeeper types.ChannelKeeper, portKeeper types.PortKeeper, @@ -61,11 +64,9 @@ func getKeeperAndCtxWithMocks(t testing.TB, stakingKeeper types.StakingKeeper, slashingKeeper types.SlashingKeeper, accountKeeper types.AccountKeeper, -) (keeper.Keeper, sdk.Context) { - - cdc, storeKey, paramsSubspace, stateStore := setupInMemKeeper(t) +) providerkeeper.Keeper { - k := keeper.NewKeeper( + k := providerkeeper.NewKeeper( cdc, storeKey, paramsSubspace, @@ -79,11 +80,10 @@ func getKeeperAndCtxWithMocks(t testing.TB, accountKeeper, "", ) - ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) - return k, ctx + return k } -func setupInMemKeeper(t testing.TB) (*codec.ProtoCodec, *storetypes.KVStoreKey, paramstypes.Subspace, storetypes.CommitMultiStore) { +func SetupInMemKeeper(t testing.TB) (*codec.ProtoCodec, *storetypes.KVStoreKey, paramstypes.Subspace, sdk.Context) { storeKey := sdk.NewKVStoreKey(types.StoreKey) memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) @@ -102,7 +102,8 @@ func setupInMemKeeper(t testing.TB) (*codec.ProtoCodec, *storetypes.KVStoreKey, memStoreKey, paramstypes.ModuleName, ) - return cdc, storeKey, paramsSubspace, stateStore + ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) + return cdc, storeKey, paramsSubspace, ctx } type DummyChannelKeeper struct{} diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index bbe33d01df..5b44733333 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -21,6 +21,7 @@ import ( appConsumer "github.com/cosmos/interchain-security/app/consumer" appProvider "github.com/cosmos/interchain-security/app/provider" + testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/testutil/simapp" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" @@ -533,7 +534,7 @@ func (suite *KeeperTestSuite) TestIterateOverUnbondingOpIndex() { } func TestMaturedUnbondingOps(t *testing.T) { - keeper, ctx := getKeeperAndCtx(t) + keeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) ids, err := keeper.GetMaturedUnbondingOps(ctx) require.NoError(t, err) diff --git a/x/ccv/provider/keeper/params_test.go b/x/ccv/provider/keeper/params_test.go index 3e3d594ad2..171315c0ab 100644 --- a/x/ccv/provider/keeper/params_test.go +++ b/x/ccv/provider/keeper/params_test.go @@ -1,24 +1,54 @@ package keeper_test import ( + "testing" "time" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" commitmenttypes "github.com/cosmos/ibc-go/v3/modules/core/23-commitment/types" ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" - appProvider "github.com/cosmos/interchain-security/app/provider" + testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/x/ccv/provider/types" + "github.com/stretchr/testify/require" ) -func (suite *KeeperTestSuite) TestParams() { - expParams := types.DefaultParams() +func TestParams(t *testing.T) { + defaultParams := types.DefaultParams() - params := suite.providerChain.App.(*appProvider.App).ProviderKeeper.GetParams(suite.providerChain.GetContext()) - suite.Require().Equal(expParams, params) + // Constuct our own params subspace + cdc, storeKey, paramsSubspace, ctx := testkeeper.SetupInMemKeeper(t) + keyTable := paramstypes.NewKeyTable(paramstypes.NewParamSetPair(types.KeyTemplateClient, &ibctmtypes.ClientState{}, func(value interface{}) error { return nil })) + paramsSubspace = paramsSubspace.WithKeyTable(keyTable) + + expectedClientState := + ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*10, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"upgrade", "upgradedIBCState"}, true, true) + + paramsSubspace.Set(ctx, types.KeyTemplateClient, expectedClientState) + + providerKeeper := testkeeper.GetProviderKeeperWithMocks(t, + cdc, + storeKey, + paramsSubspace, + ctx, + capabilitykeeper.ScopedKeeper{}, + testkeeper.DummyChannelKeeper{}, + testkeeper.DummyPortKeeper{}, + testkeeper.DummyConnectionKeeper{}, + testkeeper.DummyClientKeeper{}, + testkeeper.DummyStakingKeeper{}, + testkeeper.DummySlashingKeeper{}, + testkeeper.DummyAccountKeeper{}, + ) + + params := providerKeeper.GetParams(ctx) + require.Equal(t, defaultParams, params) newParams := types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false)) - suite.providerChain.App.(*appProvider.App).ProviderKeeper.SetParams(suite.providerChain.GetContext(), newParams) - params = suite.providerChain.App.(*appProvider.App).ProviderKeeper.GetParams(suite.providerChain.GetContext()) - suite.Require().Equal(newParams, params) + providerKeeper.SetParams(ctx, newParams) + params = providerKeeper.GetParams(ctx) + require.Equal(t, newParams, params) } From b1ab28d2486738e5ed56af0ad64fd858a3ef15c3 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Fri, 12 Aug 2022 13:35:18 -0700 Subject: [PATCH 04/24] comment and progress save --- testutil/keeper/unit_test_helpers.go | 6 ++-- x/ccv/provider/keeper/proposal.go | 41 ++++++++++++++++++-------- x/ccv/provider/keeper/proposal_test.go | 28 +++++++++++------- 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go index 2e6a398716..11eb8ed615 100644 --- a/testutil/keeper/unit_test_helpers.go +++ b/testutil/keeper/unit_test_helpers.go @@ -49,8 +49,10 @@ func GetProviderKeeperAndCtx(t testing.TB) (providerkeeper.Keeper, sdk.Context) return k, ctx } -// Constructs a keeper for unit tests, backed by an in-memory db, with ability to pass mocked or otherwise manipulated parameters. -// Note: Use the dummy types defined in this file for keepers you don't wish to mock. +// Constructs a keeper for unit tests, backed by an in-memory db, +// with ability to pass mocked or otherwise manipulated parameters. +// Note: Use the dummy types defined in this file for keepers you don't wish to mock, +// and SetupInMemKeeper() for other parameters you don't wish to manipulate. func GetProviderKeeperWithMocks(t testing.TB, cdc *codec.ProtoCodec, storeKey *storetypes.KVStoreKey, diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go index b601ba4f72..4e515eb26f 100644 --- a/x/ccv/provider/keeper/proposal.go +++ b/x/ccv/provider/keeper/proposal.go @@ -251,15 +251,32 @@ func (k Keeper) PendingCreateProposalIterator(ctx sdk.Context) sdk.Iterator { // IteratePendingCreateProposal iterates over the pending proposals to create consumer chain clients in order // and creates the consumer client if the spawn time has passed, otherwise it will break out of loop and return. func (k Keeper) IteratePendingCreateProposal(ctx sdk.Context) { + propsToExecute := k.ClientsFromProposals(ctx) + + for _, prop := range propsToExecute { + err := k.CreateConsumerClient(ctx, prop.ChainId, prop.InitialHeight, prop.LockUnbondingOnTimeout) + if err != nil { + panic(fmt.Errorf("consumer client could not be created: %w", err)) + } + } +} + +// ClientsFromProposals iterates over the pending proposals in order and returns consumer clients to be created. +// A client is included in the returned list (and its proposal is deleted) if its proposed spawn time has passed, +// otherwise the method will break out of loop and return. +// +// Note: this method is separated from IteratePendingCreateProposal to be easily unit tested. +func (k Keeper) ClientsFromProposals(ctx sdk.Context) []types.CreateConsumerChainProposal { iterator := k.PendingCreateProposalIterator(ctx) defer iterator.Close() + // store the (to be) executed proposals in order + propsToExecute := []types.CreateConsumerChainProposal{} + if !iterator.Valid() { - return + return propsToExecute // TODO: panic instead? } - // store the executed proposals in order - execProposals := []types.CreateConsumerChainProposal{} for ; iterator.Valid(); iterator.Next() { key := iterator.Key() @@ -268,23 +285,21 @@ func (k Keeper) IteratePendingCreateProposal(ctx sdk.Context) { panic(fmt.Errorf("failed to parse pending client key: %w", err)) } - var clientInfo types.CreateConsumerChainProposal - k.cdc.MustUnmarshal(iterator.Value(), &clientInfo) + var prop types.CreateConsumerChainProposal + k.cdc.MustUnmarshal(iterator.Value(), &prop) + prop.ChainId = chainID + prop.SpawnTime = spawnTime if !ctx.BlockTime().Before(spawnTime) { - err := k.CreateConsumerClient(ctx, chainID, clientInfo.InitialHeight, clientInfo.LockUnbondingOnTimeout) - if err != nil { - panic(fmt.Errorf("consumer client could not be created: %w", err)) - } - execProposals = append(execProposals, - types.CreateConsumerChainProposal{ChainId: chainID, SpawnTime: spawnTime}) + propsToExecute = append(propsToExecute, prop) } else { break } } - // delete the proposals executed - k.DeletePendingCreateProposal(ctx, execProposals...) + // delete the proposals to be executed + k.DeletePendingCreateProposal(ctx, propsToExecute...) + return propsToExecute } // DeletePendingCreateProposal deletes the given create consumer proposals diff --git a/x/ccv/provider/keeper/proposal_test.go b/x/ccv/provider/keeper/proposal_test.go index c605d36f63..c0e4fe0a78 100644 --- a/x/ccv/provider/keeper/proposal_test.go +++ b/x/ccv/provider/keeper/proposal_test.go @@ -2,18 +2,22 @@ package keeper_test import ( "encoding/json" + "testing" "time" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" appProvider "github.com/cosmos/interchain-security/app/provider" + testkeeper "github.com/cosmos/interchain-security/testutil/keeper" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" "github.com/cosmos/interchain-security/x/ccv/provider/types" abci "github.com/tendermint/tendermint/abci/types" crypto "github.com/tendermint/tendermint/proto/tendermint/crypto" ) +// TODO: This is an e2e test to be moved. func (suite *KeeperTestSuite) TestMakeConsumerGenesis() { suite.SetupTest() @@ -41,6 +45,7 @@ func (suite *KeeperTestSuite) TestMakeConsumerGenesis() { suite.Require().Equal(actualGenesis, expectedGenesis, "consumer chain genesis created incorrectly") } +// TODO: This is an e2e test to be moved. func (suite *KeeperTestSuite) TestCreateConsumerChainProposal() { var ( ctx sdk.Context @@ -148,7 +153,7 @@ func (suite *KeeperTestSuite) TestIteratePendingStopProposal() { } } -func (suite *KeeperTestSuite) TestIteratePendingClientInfo() { +func TestIteratePendingCreateProposals(t *testing.T) { testCases := []struct { types.CreateConsumerChainProposal @@ -163,23 +168,26 @@ func (suite *KeeperTestSuite) TestIteratePendingClientInfo() { ExpDeleted: false, }, } + providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) for _, tc := range testCases { - err := suite.providerChain.App.(*appProvider.App).ProviderKeeper.SetPendingCreateProposal( - suite.providerChain.GetContext(), &tc.CreateConsumerChainProposal) - suite.Require().NoError(err) + err := providerKeeper.SetPendingCreateProposal(ctx, &tc.CreateConsumerChainProposal) + require.NoError(t, err) } - ctx := suite.providerChain.GetContext().WithBlockTime(testCases[0].SpawnTime) - - suite.providerChain.App.(*appProvider.App).ProviderKeeper.IteratePendingCreateProposal(ctx) + ctx = ctx.WithBlockTime(testCases[0].SpawnTime) + propsToExecute := providerKeeper.ClientsFromProposals(ctx) + numExecuted := 0 for _, tc := range testCases { - res := suite.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingCreateProposal(ctx, tc.SpawnTime, tc.ChainId) + res := providerKeeper.GetPendingCreateProposal(ctx, tc.SpawnTime, tc.ChainId) if !tc.ExpDeleted { - suite.Require().NotEmpty(res, "stop proposal was not deleted: %s %s", tc.ChainId, tc.SpawnTime.String()) + require.NotEmpty(t, res, "stop proposal was deleted: %s %s", tc.ChainId, tc.SpawnTime.String()) continue } - suite.Require().Empty(res, "stop proposal was not deleted %s %s", tc.ChainId, tc.SpawnTime.String()) + // In this case, proposal would now be executed + require.Empty(t, res, "stop proposal was not deleted %s %s", tc.ChainId, tc.SpawnTime.String()) + require.Equal(t, propsToExecute[numExecuted].ChainId, tc.ChainId) + numExecuted += 1 } } From ad58d52b00a10128ea9650990515c6ad8bcf0fc2 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Fri, 12 Aug 2022 14:25:56 -0700 Subject: [PATCH 05/24] progess save --- x/ccv/provider/keeper/proposal.go | 48 +++++++++++++++++--------- x/ccv/provider/keeper/proposal_test.go | 36 +++++++++++-------- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go index 4e515eb26f..d12a355445 100644 --- a/x/ccv/provider/keeper/proposal.go +++ b/x/ccv/provider/keeper/proposal.go @@ -251,7 +251,7 @@ func (k Keeper) PendingCreateProposalIterator(ctx sdk.Context) sdk.Iterator { // IteratePendingCreateProposal iterates over the pending proposals to create consumer chain clients in order // and creates the consumer client if the spawn time has passed, otherwise it will break out of loop and return. func (k Keeper) IteratePendingCreateProposal(ctx sdk.Context) { - propsToExecute := k.ClientsFromProposals(ctx) + propsToExecute := k.ClientsFromCreateProposals(ctx) for _, prop := range propsToExecute { err := k.CreateConsumerClient(ctx, prop.ChainId, prop.InitialHeight, prop.LockUnbondingOnTimeout) @@ -261,12 +261,12 @@ func (k Keeper) IteratePendingCreateProposal(ctx sdk.Context) { } } -// ClientsFromProposals iterates over the pending proposals in order and returns consumer clients to be created. +// ClientsFromCreateProposals iterates over the pending proposals in order and returns a list of consumer clients to be created. // A client is included in the returned list (and its proposal is deleted) if its proposed spawn time has passed, // otherwise the method will break out of loop and return. // -// Note: this method is separated from IteratePendingCreateProposal to be easily unit tested. -func (k Keeper) ClientsFromProposals(ctx sdk.Context) []types.CreateConsumerChainProposal { +// Note: this method is split out from IteratePendingCreateProposal to be easily unit tested. +func (k Keeper) ClientsFromCreateProposals(ctx sdk.Context) []types.CreateConsumerChainProposal { iterator := k.PendingCreateProposalIterator(ctx) defer iterator.Close() @@ -275,7 +275,7 @@ func (k Keeper) ClientsFromProposals(ctx sdk.Context) []types.CreateConsumerChai propsToExecute := []types.CreateConsumerChainProposal{} if !iterator.Valid() { - return propsToExecute // TODO: panic instead? + return propsToExecute } for ; iterator.Valid(); iterator.Next() { @@ -342,17 +342,35 @@ func (k Keeper) PendingStopProposalIterator(ctx sdk.Context) sdk.Iterator { // IteratePendingStopProposal iterates over the pending stop proposals in order and stop the chain if the stop time has passed, // otherwise it will break out of loop and return. func (k Keeper) IteratePendingStopProposal(ctx sdk.Context) { + propsToExecute := k.ClientsFromStopProposals(ctx) + + for _, prop := range propsToExecute { + err := k.StopConsumerChain(ctx, prop.ChainId, false, true) + if err != nil { + panic(fmt.Errorf("consumer chain failed to stop: %w", err)) + } + } +} + +// ClientsFromStopProposals iterates over the pending stop proposals in order and returns a list of consumer chains to stop. +// A client is included in the returned list (and its stop proposal is deleted) if its proposed stop time has passed, +// otherwise the method will break out of loop and return. +// +// Note: this method is split out from IteratePendingStopProposal to be easily unit tested. +func (k Keeper) ClientsFromStopProposals(ctx sdk.Context) []types.StopConsumerChainProposal { + iterator := k.PendingStopProposalIterator(ctx) defer iterator.Close() + // store the (to be) executed stop proposals in order + propsToExecute := []types.StopConsumerChainProposal{} + if !iterator.Valid() { - return + return propsToExecute } - // store the executed proposals in order - execProposals := []types.StopConsumerChainProposal{} - for ; iterator.Valid(); iterator.Next() { + key := iterator.Key() stopTime, chainID, err := types.ParsePendingStopProposalKey(key) if err != nil { @@ -360,19 +378,17 @@ func (k Keeper) IteratePendingStopProposal(ctx sdk.Context) { } if !ctx.BlockTime().Before(stopTime) { - err = k.StopConsumerChain(ctx, chainID, false, true) - if err != nil { - panic(fmt.Errorf("consumer chain failed to stop: %w", err)) - } - execProposals = append(execProposals, + propsToExecute = append(propsToExecute, types.StopConsumerChainProposal{ChainId: chainID, StopTime: stopTime}) } else { break } } - // delete the proposals executed - k.DeletePendingStopProposals(ctx, execProposals...) + // delete the proposals to be executed + k.DeletePendingStopProposals(ctx, propsToExecute...) + + return propsToExecute } // CloseChannel closes the channel for the given channel ID on the condition diff --git a/x/ccv/provider/keeper/proposal_test.go b/x/ccv/provider/keeper/proposal_test.go index c0e4fe0a78..8f0ee4c0fa 100644 --- a/x/ccv/provider/keeper/proposal_test.go +++ b/x/ccv/provider/keeper/proposal_test.go @@ -121,35 +121,41 @@ func (suite *KeeperTestSuite) TestCreateConsumerChainProposal() { } } -func (suite *KeeperTestSuite) TestIteratePendingStopProposal() { - - chainID := suite.consumerChain.ChainID +func TestIteratePendingStopProposals(t *testing.T) { testCases := []struct { types.StopConsumerChainProposal ExpDeleted bool }{ { - StopConsumerChainProposal: types.StopConsumerChainProposal{ChainId: chainID, StopTime: time.Now().UTC()}, + StopConsumerChainProposal: types.StopConsumerChainProposal{ChainId: "8", StopTime: time.Now().UTC()}, ExpDeleted: true, }, { - StopConsumerChainProposal: types.StopConsumerChainProposal{ChainId: chainID, StopTime: time.Now().UTC().Add(time.Hour)}, + StopConsumerChainProposal: types.StopConsumerChainProposal{ChainId: "9", StopTime: time.Now().UTC().Add(time.Hour)}, ExpDeleted: false, }, } + providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) for _, tc := range testCases { - suite.providerChain.App.(*appProvider.App).ProviderKeeper.SetPendingStopProposal( - suite.providerChain.GetContext(), tc.ChainId, tc.StopTime) + providerKeeper.SetPendingStopProposal(ctx, tc.ChainId, tc.StopTime) } - ctx := suite.providerChain.GetContext().WithBlockTime(testCases[0].StopTime) - suite.providerChain.App.(*appProvider.App).ProviderKeeper.IteratePendingStopProposal(ctx) + ctx = ctx.WithBlockTime(time.Now().UTC()) + propsToExecute := providerKeeper.ClientsFromStopProposals(ctx) + numExecuted := 0 for _, tc := range testCases { - found := suite.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingStopProposal(ctx, tc.ChainId, tc.StopTime) - suite.Require().NotEqual(tc.ExpDeleted, found, "stop proposal was not deleted %s %v", tc.ChainId, tc.StopTime) + res := providerKeeper.GetPendingStopProposal(ctx, tc.ChainId, tc.StopTime) + if !tc.ExpDeleted { + require.NotEmpty(t, res, "stop proposal was deleted: %s %s", tc.ChainId, tc.StopTime.String()) + continue + } + // In this case, stop proposal would now be executed + require.Empty(t, res, "stop proposal was not deleted %s %s", tc.ChainId, tc.StopTime.String()) + require.Equal(t, propsToExecute[numExecuted].ChainId, tc.ChainId) + numExecuted += 1 } } @@ -175,18 +181,18 @@ func TestIteratePendingCreateProposals(t *testing.T) { require.NoError(t, err) } - ctx = ctx.WithBlockTime(testCases[0].SpawnTime) + ctx = ctx.WithBlockTime(time.Now().UTC()) - propsToExecute := providerKeeper.ClientsFromProposals(ctx) + propsToExecute := providerKeeper.ClientsFromCreateProposals(ctx) numExecuted := 0 for _, tc := range testCases { res := providerKeeper.GetPendingCreateProposal(ctx, tc.SpawnTime, tc.ChainId) if !tc.ExpDeleted { - require.NotEmpty(t, res, "stop proposal was deleted: %s %s", tc.ChainId, tc.SpawnTime.String()) + require.NotEmpty(t, res, "create proposal was deleted: %s %s", tc.ChainId, tc.SpawnTime.String()) continue } // In this case, proposal would now be executed - require.Empty(t, res, "stop proposal was not deleted %s %s", tc.ChainId, tc.SpawnTime.String()) + require.Empty(t, res, "create proposal was not deleted %s %s", tc.ChainId, tc.SpawnTime.String()) require.Equal(t, propsToExecute[numExecuted].ChainId, tc.ChainId) numExecuted += 1 } From 537445940a0270f136ee919e707663e846daa021 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Fri, 12 Aug 2022 17:09:40 -0700 Subject: [PATCH 06/24] finished keeper --- x/ccv/provider/keeper/keeper_test.go | 160 +++++++++++++-------------- 1 file changed, 76 insertions(+), 84 deletions(-) diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 5b44733333..968ee511ce 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -38,16 +38,13 @@ import ( type KeeperTestSuite struct { suite.Suite - coordinator *ibctesting.Coordinator // testing chains providerChain *ibctesting.TestChain consumerChain *ibctesting.TestChain - - path *ibctesting.Path - - ctx sdk.Context + path *ibctesting.Path + ctx sdk.Context } func (suite *KeeperTestSuite) SetupTest() { @@ -130,35 +127,33 @@ func TestKeeperTestSuite(t *testing.T) { suite.Run(t, new(KeeperTestSuite)) } -func (suite *KeeperTestSuite) TestValsetUpdateBlockHeight() { - app := suite.providerChain.App.(*appProvider.App) - ctx := suite.ctx +func TestValsetUpdateBlockHeight(t *testing.T) { + providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) - blockHeight := app.ProviderKeeper.GetValsetUpdateBlockHeight(ctx, uint64(0)) - suite.Require().Zero(blockHeight) + blockHeight := providerKeeper.GetValsetUpdateBlockHeight(ctx, uint64(0)) + require.Zero(t, blockHeight) - app.ProviderKeeper.SetValsetUpdateBlockHeight(ctx, uint64(1), uint64(2)) - blockHeight = app.ProviderKeeper.GetValsetUpdateBlockHeight(ctx, uint64(1)) - suite.Require().Equal(blockHeight, uint64(2)) + providerKeeper.SetValsetUpdateBlockHeight(ctx, uint64(1), uint64(2)) + blockHeight = providerKeeper.GetValsetUpdateBlockHeight(ctx, uint64(1)) + require.Equal(t, blockHeight, uint64(2)) - app.ProviderKeeper.DeleteValsetUpdateBlockHeight(ctx, uint64(1)) - blockHeight = app.ProviderKeeper.GetValsetUpdateBlockHeight(ctx, uint64(1)) - suite.Require().Zero(blockHeight) + providerKeeper.DeleteValsetUpdateBlockHeight(ctx, uint64(1)) + blockHeight = providerKeeper.GetValsetUpdateBlockHeight(ctx, uint64(1)) + require.Zero(t, blockHeight) - app.ProviderKeeper.SetValsetUpdateBlockHeight(ctx, uint64(1), uint64(2)) - app.ProviderKeeper.SetValsetUpdateBlockHeight(ctx, uint64(3), uint64(4)) - blockHeight = app.ProviderKeeper.GetValsetUpdateBlockHeight(ctx, uint64(3)) - suite.Require().Equal(blockHeight, uint64(4)) + providerKeeper.SetValsetUpdateBlockHeight(ctx, uint64(1), uint64(2)) + providerKeeper.SetValsetUpdateBlockHeight(ctx, uint64(3), uint64(4)) + blockHeight = providerKeeper.GetValsetUpdateBlockHeight(ctx, uint64(3)) + require.Equal(t, blockHeight, uint64(4)) } -func (suite *KeeperTestSuite) TestSlashAcks() { - app := suite.providerChain.App.(*appProvider.App) - ctx := suite.ctx +func TestSlashAcks(t *testing.T) { + providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) var chainsAcks [][]string penaltiesfN := func() (penalties []string) { - app.ProviderKeeper.IterateSlashAcks(ctx, func(id string, acks []string) bool { + providerKeeper.IterateSlashAcks(ctx, func(id string, acks []string) bool { chainsAcks = append(chainsAcks, acks) return true }) @@ -167,59 +162,57 @@ func (suite *KeeperTestSuite) TestSlashAcks() { chainID := "consumer" - acks := app.ProviderKeeper.GetSlashAcks(ctx, chainID) - suite.Require().Nil(acks) + acks := providerKeeper.GetSlashAcks(ctx, chainID) + require.Nil(t, acks) p := []string{"alice", "bob", "charlie"} - app.ProviderKeeper.SetSlashAcks(ctx, chainID, p) + providerKeeper.SetSlashAcks(ctx, chainID, p) - acks = app.ProviderKeeper.GetSlashAcks(ctx, chainID) - suite.Require().NotNil(acks) + acks = providerKeeper.GetSlashAcks(ctx, chainID) + require.NotNil(t, acks) - suite.Require().Len(acks, 3) - emptied := app.ProviderKeeper.EmptySlashAcks(ctx, chainID) - suite.Require().Len(emptied, 3) + require.Len(t, acks, 3) + emptied := providerKeeper.EmptySlashAcks(ctx, chainID) + require.Len(t, emptied, 3) - acks = app.ProviderKeeper.GetSlashAcks(ctx, chainID) - suite.Require().Nil(acks) + acks = providerKeeper.GetSlashAcks(ctx, chainID) + require.Nil(t, acks) chains := []string{"c1", "c2", "c3"} for _, c := range chains { - app.ProviderKeeper.SetSlashAcks(ctx, c, p) + providerKeeper.SetSlashAcks(ctx, c, p) } penaltiesfN() - suite.Require().Len(chainsAcks, len(chains)) + require.Len(t, chainsAcks, len(chains)) } -func (suite *KeeperTestSuite) TestAppendSlashAck() { - app := suite.providerChain.App.(*appProvider.App) - ctx := suite.ctx +func TestAppendSlashAck(t *testing.T) { + providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) p := []string{"alice", "bob", "charlie"} chains := []string{"c1", "c2"} - app.ProviderKeeper.SetSlashAcks(ctx, chains[0], p) + providerKeeper.SetSlashAcks(ctx, chains[0], p) - app.ProviderKeeper.AppendSlashAck(ctx, chains[0], p[0]) - acks := app.ProviderKeeper.GetSlashAcks(ctx, chains[0]) - suite.Require().NotNil(acks) - suite.Require().Len(acks, len(p)+1) + providerKeeper.AppendSlashAck(ctx, chains[0], p[0]) + acks := providerKeeper.GetSlashAcks(ctx, chains[0]) + require.NotNil(t, acks) + require.Len(t, acks, len(p)+1) - app.ProviderKeeper.AppendSlashAck(ctx, chains[1], p[0]) - acks = app.ProviderKeeper.GetSlashAcks(ctx, chains[1]) - suite.Require().NotNil(acks) - suite.Require().Len(acks, 1) + providerKeeper.AppendSlashAck(ctx, chains[1], p[0]) + acks = providerKeeper.GetSlashAcks(ctx, chains[1]) + require.NotNil(t, acks) + require.Len(t, acks, 1) } -func (suite *KeeperTestSuite) TestPendingVSCs() { - app := suite.providerChain.App.(*appProvider.App) - ctx := suite.ctx +func TestPendingVSCs(t *testing.T) { + providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) chainID := "consumer" - _, found := app.ProviderKeeper.GetPendingVSCs(ctx, chainID) - suite.Require().False(found) + _, found := providerKeeper.GetPendingVSCs(ctx, chainID) + require.False(t, found) pks := ibcsimapp.CreateTestPubKeys(4) var ppks [4]tmprotocrypto.PublicKey @@ -243,12 +236,12 @@ func (suite *KeeperTestSuite) TestPendingVSCs() { }, } for _, packet := range packetList { - app.ProviderKeeper.AppendPendingVSC(ctx, chainID, packet) + providerKeeper.AppendPendingVSC(ctx, chainID, packet) } - packets, found := app.ProviderKeeper.GetPendingVSCs(ctx, chainID) - suite.Require().True(found) - suite.Require().Len(packets, 2) + packets, found := providerKeeper.GetPendingVSCs(ctx, chainID) + require.True(t, found) + require.Len(t, packets, 2) newPacket := ccv.ValidatorSetChangePacketData{ ValidatorUpdates: []abci.ValidatorUpdate{ @@ -256,19 +249,18 @@ func (suite *KeeperTestSuite) TestPendingVSCs() { }, ValsetUpdateId: 3, } - app.ProviderKeeper.AppendPendingVSC(ctx, chainID, newPacket) - emptied := app.ProviderKeeper.EmptyPendingVSC(ctx, chainID) - suite.Require().Len(emptied, 3) - suite.Require().True(emptied[len(emptied)-1].ValsetUpdateId == 3) - suite.Require().True(emptied[len(emptied)-1].GetValidatorUpdates()[0].PubKey.String() == ppks[3].String()) - - _, found = app.ProviderKeeper.GetPendingVSCs(ctx, chainID) - suite.Require().False(found) + providerKeeper.AppendPendingVSC(ctx, chainID, newPacket) + emptied := providerKeeper.EmptyPendingVSC(ctx, chainID) + require.Len(t, emptied, 3) + require.True(t, emptied[len(emptied)-1].ValsetUpdateId == 3) + require.True(t, emptied[len(emptied)-1].GetValidatorUpdates()[0].PubKey.String() == ppks[3].String()) + + _, found = providerKeeper.GetPendingVSCs(ctx, chainID) + require.False(t, found) } -func (suite *KeeperTestSuite) TestInitHeight() { - app := suite.providerChain.App.(*appProvider.App) - ctx := suite.ctx +func TestInitHeight(t *testing.T) { + providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) tc := []struct { chainID string @@ -279,17 +271,17 @@ func (suite *KeeperTestSuite) TestInitHeight() { {expected: 12, chainID: "chain2"}, } - app.ProviderKeeper.SetInitChainHeight(ctx, tc[1].chainID, tc[1].expected) - app.ProviderKeeper.SetInitChainHeight(ctx, tc[2].chainID, tc[2].expected) + providerKeeper.SetInitChainHeight(ctx, tc[1].chainID, tc[1].expected) + providerKeeper.SetInitChainHeight(ctx, tc[2].chainID, tc[2].expected) - for _, t := range tc { - height := app.ProviderKeeper.GetInitChainHeight(ctx, t.chainID) - suite.Require().EqualValues(t.expected, height) + for _, tc := range tc { + height := providerKeeper.GetInitChainHeight(ctx, tc.chainID) + require.Equal(t, tc.expected, height) } } func (suite *KeeperTestSuite) TestHandleSlashPacketDoubleSigning() { - ProviderKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper + providerKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper providerSlashingKeeper := suite.providerChain.App.(*appProvider.App).SlashingKeeper providerStakingKeeper := suite.providerChain.App.(*appProvider.App).StakingKeeper @@ -302,7 +294,7 @@ func (suite *KeeperTestSuite) TestHandleSlashPacketDoubleSigning() { suite.Require().Equal(stakingtypes.Bonded, validator.GetStatus()) // set init VSC id for chain0 - ProviderKeeper.SetInitChainHeight(suite.ctx, suite.consumerChain.ChainID, uint64(suite.ctx.BlockHeight())) + providerKeeper.SetInitChainHeight(suite.ctx, suite.consumerChain.ChainID, uint64(suite.ctx.BlockHeight())) // set validator signing-info providerSlashingKeeper.SetValidatorSigningInfo( @@ -311,7 +303,7 @@ func (suite *KeeperTestSuite) TestHandleSlashPacketDoubleSigning() { slashingtypes.ValidatorSigningInfo{Address: consAddr.String()}, ) - _, err := ProviderKeeper.HandleSlashPacket(suite.ctx, suite.consumerChain.ChainID, + _, err := providerKeeper.HandleSlashPacket(suite.ctx, suite.consumerChain.ChainID, ccv.NewSlashPacketData( abci.Validator{Address: tmVal.Address, Power: 0}, uint64(0), @@ -510,27 +502,27 @@ func (suite *KeeperTestSuite) TestHandleSlashPacketDistribution() { } } -func (suite *KeeperTestSuite) TestIterateOverUnbondingOpIndex() { - providerKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper - chainID := suite.consumerChain.ChainID +func TestIterateOverUnbondingOpIndex(t *testing.T) { + providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) + chainID := "6" // mock an unbonding index unbondingOpIndex := []uint64{0, 1, 2, 3, 4, 5, 6} // set ubd ops by varying vsc ids and index slices for i := 1; i < len(unbondingOpIndex); i++ { - providerKeeper.SetUnbondingOpIndex(suite.providerChain.GetContext(), chainID, uint64(i), unbondingOpIndex[:i]) + providerKeeper.SetUnbondingOpIndex(ctx, chainID, uint64(i), unbondingOpIndex[:i]) } // check iterator returns expected entries i := 1 - providerKeeper.IterateOverUnbondingOpIndex(suite.providerChain.GetContext(), chainID, func(vscID uint64, ubdIndex []uint64) bool { - suite.Require().Equal(uint64(i), vscID) - suite.Require().EqualValues(unbondingOpIndex[:i], ubdIndex) + providerKeeper.IterateOverUnbondingOpIndex(ctx, chainID, func(vscID uint64, ubdIndex []uint64) bool { + require.Equal(t, uint64(i), vscID) + require.EqualValues(t, unbondingOpIndex[:i], ubdIndex) i++ return true }) - suite.Require().Equal(len(unbondingOpIndex), i) + require.Equal(t, len(unbondingOpIndex), i) } func TestMaturedUnbondingOps(t *testing.T) { From 628c61cfab71b57823d48b483c473b325ace8cac Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Fri, 12 Aug 2022 18:25:39 -0700 Subject: [PATCH 07/24] couple unit tests for prop order --- x/ccv/provider/keeper/proposal.go | 26 ++--- x/ccv/provider/keeper/proposal_test.go | 129 +++++++++++++++++++++++-- 2 files changed, 135 insertions(+), 20 deletions(-) diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go index d12a355445..b200ab709e 100644 --- a/x/ccv/provider/keeper/proposal.go +++ b/x/ccv/provider/keeper/proposal.go @@ -249,9 +249,9 @@ func (k Keeper) PendingCreateProposalIterator(ctx sdk.Context) sdk.Iterator { } // IteratePendingCreateProposal iterates over the pending proposals to create consumer chain clients in order -// and creates the consumer client if the spawn time has passed, otherwise it will break out of loop and return. +// and creates the consumer client if the spawn time has passed. func (k Keeper) IteratePendingCreateProposal(ctx sdk.Context) { - propsToExecute := k.ClientsFromCreateProposals(ctx) + propsToExecute := k.CreateProposalsToExecute(ctx) for _, prop := range propsToExecute { err := k.CreateConsumerClient(ctx, prop.ChainId, prop.InitialHeight, prop.LockUnbondingOnTimeout) @@ -261,12 +261,12 @@ func (k Keeper) IteratePendingCreateProposal(ctx sdk.Context) { } } -// ClientsFromCreateProposals iterates over the pending proposals in order and returns a list of consumer clients to be created. -// A client is included in the returned list (and its proposal is deleted) if its proposed spawn time has passed, -// otherwise the method will break out of loop and return. +// CreateProposalsToExecute iterates over the pending proposals and returns an ordered list of proposals to be executed, +// ie. consumer clients to be created. A prop is included in the returned list (and is deleted from store) if its proposed +// spawn time has passed. // // Note: this method is split out from IteratePendingCreateProposal to be easily unit tested. -func (k Keeper) ClientsFromCreateProposals(ctx sdk.Context) []types.CreateConsumerChainProposal { +func (k Keeper) CreateProposalsToExecute(ctx sdk.Context) []types.CreateConsumerChainProposal { iterator := k.PendingCreateProposalIterator(ctx) defer iterator.Close() @@ -293,6 +293,7 @@ func (k Keeper) ClientsFromCreateProposals(ctx sdk.Context) []types.CreateConsum if !ctx.BlockTime().Before(spawnTime) { propsToExecute = append(propsToExecute, prop) } else { + // No more proposals to check, since they're stored/ordered by timestamp. break } } @@ -342,7 +343,7 @@ func (k Keeper) PendingStopProposalIterator(ctx sdk.Context) sdk.Iterator { // IteratePendingStopProposal iterates over the pending stop proposals in order and stop the chain if the stop time has passed, // otherwise it will break out of loop and return. func (k Keeper) IteratePendingStopProposal(ctx sdk.Context) { - propsToExecute := k.ClientsFromStopProposals(ctx) + propsToExecute := k.StopProposalsToExecute(ctx) for _, prop := range propsToExecute { err := k.StopConsumerChain(ctx, prop.ChainId, false, true) @@ -352,12 +353,12 @@ func (k Keeper) IteratePendingStopProposal(ctx sdk.Context) { } } -// ClientsFromStopProposals iterates over the pending stop proposals in order and returns a list of consumer chains to stop. -// A client is included in the returned list (and its stop proposal is deleted) if its proposed stop time has passed, -// otherwise the method will break out of loop and return. +// StopProposalsToExecute iterates over the pending stop proposals and returns an ordered list of stop proposals to be executed, +// ie. consumer chains to stop. A prop is included in the returned list (and is deleted from store) if its proposed +// stop time has passed. // -// Note: this method is split out from IteratePendingStopProposal to be easily unit tested. -func (k Keeper) ClientsFromStopProposals(ctx sdk.Context) []types.StopConsumerChainProposal { +// Note: this method is split out from IteratePendingCreateProposal to be easily unit tested. +func (k Keeper) StopProposalsToExecute(ctx sdk.Context) []types.StopConsumerChainProposal { iterator := k.PendingStopProposalIterator(ctx) defer iterator.Close() @@ -378,6 +379,7 @@ func (k Keeper) ClientsFromStopProposals(ctx sdk.Context) []types.StopConsumerCh } if !ctx.BlockTime().Before(stopTime) { + // No more proposals to check, since they're stored/ordered by timestamp. propsToExecute = append(propsToExecute, types.StopConsumerChainProposal{ChainId: chainID, StopTime: stopTime}) } else { diff --git a/x/ccv/provider/keeper/proposal_test.go b/x/ccv/provider/keeper/proposal_test.go index 8f0ee4c0fa..479265c03a 100644 --- a/x/ccv/provider/keeper/proposal_test.go +++ b/x/ccv/provider/keeper/proposal_test.go @@ -17,7 +17,6 @@ import ( crypto "github.com/tendermint/tendermint/proto/tendermint/crypto" ) -// TODO: This is an e2e test to be moved. func (suite *KeeperTestSuite) TestMakeConsumerGenesis() { suite.SetupTest() @@ -45,7 +44,6 @@ func (suite *KeeperTestSuite) TestMakeConsumerGenesis() { suite.Require().Equal(actualGenesis, expectedGenesis, "consumer chain genesis created incorrectly") } -// TODO: This is an e2e test to be moved. func (suite *KeeperTestSuite) TestCreateConsumerChainProposal() { var ( ctx sdk.Context @@ -121,7 +119,7 @@ func (suite *KeeperTestSuite) TestCreateConsumerChainProposal() { } } -func TestIteratePendingStopProposals(t *testing.T) { +func TestPendingStopProposalDeletion(t *testing.T) { testCases := []struct { types.StopConsumerChainProposal @@ -144,7 +142,7 @@ func TestIteratePendingStopProposals(t *testing.T) { ctx = ctx.WithBlockTime(time.Now().UTC()) - propsToExecute := providerKeeper.ClientsFromStopProposals(ctx) + propsToExecute := providerKeeper.StopProposalsToExecute(ctx) numExecuted := 0 for _, tc := range testCases { res := providerKeeper.GetPendingStopProposal(ctx, tc.ChainId, tc.StopTime) @@ -152,14 +150,71 @@ func TestIteratePendingStopProposals(t *testing.T) { require.NotEmpty(t, res, "stop proposal was deleted: %s %s", tc.ChainId, tc.StopTime.String()) continue } - // In this case, stop proposal would now be executed require.Empty(t, res, "stop proposal was not deleted %s %s", tc.ChainId, tc.StopTime.String()) require.Equal(t, propsToExecute[numExecuted].ChainId, tc.ChainId) numExecuted += 1 } } -func TestIteratePendingCreateProposals(t *testing.T) { +// Tests that pending stop proposals are accessed in order by timestamp via the iterator +func TestPendingStopProposalsOrder(t *testing.T) { + + now := time.Now().UTC() + + // props with unique chain ids and spawn times + sampleProp1 := types.StopConsumerChainProposal{ChainId: "1", StopTime: now} + sampleProp2 := types.StopConsumerChainProposal{ChainId: "2", StopTime: now.Add(1 * time.Hour)} + sampleProp3 := types.StopConsumerChainProposal{ChainId: "3", StopTime: now.Add(2 * time.Hour)} + sampleProp4 := types.StopConsumerChainProposal{ChainId: "4", StopTime: now.Add(3 * time.Hour)} + sampleProp5 := types.StopConsumerChainProposal{ChainId: "5", StopTime: now.Add(4 * time.Hour)} + + testCases := []struct { + propSubmitOrder []types.StopConsumerChainProposal + accessTime time.Time + expectedOrderedProps []types.StopConsumerChainProposal + }{ + { + propSubmitOrder: []types.StopConsumerChainProposal{ + sampleProp1, sampleProp2, sampleProp3, sampleProp4, sampleProp5, + }, + accessTime: now.Add(30 * time.Minute), + expectedOrderedProps: []types.StopConsumerChainProposal{ + sampleProp1, + }, + }, + { + propSubmitOrder: []types.StopConsumerChainProposal{ + sampleProp3, sampleProp2, sampleProp1, sampleProp5, sampleProp4, + }, + accessTime: now.Add(3 * time.Hour).Add(30 * time.Minute), + expectedOrderedProps: []types.StopConsumerChainProposal{ + sampleProp1, sampleProp2, sampleProp3, sampleProp4, + }, + }, + { + propSubmitOrder: []types.StopConsumerChainProposal{ + sampleProp5, sampleProp4, sampleProp3, sampleProp2, sampleProp1, + }, + accessTime: now.Add(5 * time.Hour), + expectedOrderedProps: []types.StopConsumerChainProposal{ + sampleProp1, sampleProp2, sampleProp3, sampleProp4, sampleProp5, + }, + }, + } + + for _, tc := range testCases { + providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) + ctx = ctx.WithBlockTime(tc.accessTime) + + for _, prop := range tc.propSubmitOrder { + providerKeeper.SetPendingStopProposal(ctx, prop.ChainId, prop.StopTime) + } + propsToExecute := providerKeeper.StopProposalsToExecute(ctx) + require.Equal(t, tc.expectedOrderedProps, propsToExecute) + } +} + +func TestPendingCreateProposalsDeletion(t *testing.T) { testCases := []struct { types.CreateConsumerChainProposal @@ -183,7 +238,7 @@ func TestIteratePendingCreateProposals(t *testing.T) { ctx = ctx.WithBlockTime(time.Now().UTC()) - propsToExecute := providerKeeper.ClientsFromCreateProposals(ctx) + propsToExecute := providerKeeper.CreateProposalsToExecute(ctx) numExecuted := 0 for _, tc := range testCases { res := providerKeeper.GetPendingCreateProposal(ctx, tc.SpawnTime, tc.ChainId) @@ -191,9 +246,67 @@ func TestIteratePendingCreateProposals(t *testing.T) { require.NotEmpty(t, res, "create proposal was deleted: %s %s", tc.ChainId, tc.SpawnTime.String()) continue } - // In this case, proposal would now be executed require.Empty(t, res, "create proposal was not deleted %s %s", tc.ChainId, tc.SpawnTime.String()) require.Equal(t, propsToExecute[numExecuted].ChainId, tc.ChainId) numExecuted += 1 } } + +// Tests that pending create proposals are accessed in order by timestamp via the iterator +func TestPendingCreateProposalsOrder(t *testing.T) { + + now := time.Now().UTC() + + // props with unique chain ids and spawn times + sampleProp1 := types.CreateConsumerChainProposal{ChainId: "1", SpawnTime: now} + sampleProp2 := types.CreateConsumerChainProposal{ChainId: "2", SpawnTime: now.Add(1 * time.Hour)} + sampleProp3 := types.CreateConsumerChainProposal{ChainId: "3", SpawnTime: now.Add(2 * time.Hour)} + sampleProp4 := types.CreateConsumerChainProposal{ChainId: "4", SpawnTime: now.Add(3 * time.Hour)} + sampleProp5 := types.CreateConsumerChainProposal{ChainId: "5", SpawnTime: now.Add(4 * time.Hour)} + + testCases := []struct { + propSubmitOrder []types.CreateConsumerChainProposal + accessTime time.Time + expectedOrderedProps []types.CreateConsumerChainProposal + }{ + { + propSubmitOrder: []types.CreateConsumerChainProposal{ + sampleProp1, sampleProp2, sampleProp3, sampleProp4, sampleProp5, + }, + accessTime: now.Add(30 * time.Minute), + expectedOrderedProps: []types.CreateConsumerChainProposal{ + sampleProp1, + }, + }, + { + propSubmitOrder: []types.CreateConsumerChainProposal{ + sampleProp3, sampleProp2, sampleProp1, sampleProp5, sampleProp4, + }, + accessTime: now.Add(3 * time.Hour).Add(30 * time.Minute), + expectedOrderedProps: []types.CreateConsumerChainProposal{ + sampleProp1, sampleProp2, sampleProp3, sampleProp4, + }, + }, + { + propSubmitOrder: []types.CreateConsumerChainProposal{ + sampleProp5, sampleProp4, sampleProp3, sampleProp2, sampleProp1, + }, + accessTime: now.Add(5 * time.Hour), + expectedOrderedProps: []types.CreateConsumerChainProposal{ + sampleProp1, sampleProp2, sampleProp3, sampleProp4, sampleProp5, + }, + }, + } + + for _, tc := range testCases { + providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) + ctx = ctx.WithBlockTime(tc.accessTime) + + for _, prop := range tc.propSubmitOrder { + err := providerKeeper.SetPendingCreateProposal(ctx, &prop) + require.NoError(t, err) + } + propsToExecute := providerKeeper.CreateProposalsToExecute(ctx) + require.Equal(t, tc.expectedOrderedProps, propsToExecute) + } +} From 56d61919c9c3d8cd548798f0e3205ee731aaac70 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Mon, 15 Aug 2022 14:27:52 -0700 Subject: [PATCH 08/24] pr suggestions --- go.mod | 1 + testutil/keeper/mock_defaults.go | 171 +++++++++++++++++++++++++++ testutil/keeper/unit_test_helpers.go | 124 ++----------------- x/ccv/provider/keeper/keeper_test.go | 73 +++++++++++- x/ccv/provider/keeper/params_test.go | 14 +-- x/ccv/provider/keeper/proposal.go | 10 +- 6 files changed, 262 insertions(+), 131 deletions(-) create mode 100644 testutil/keeper/mock_defaults.go diff --git a/go.mod b/go.mod index 65d3c51f9a..ea9d9d328e 100644 --- a/go.mod +++ b/go.mod @@ -109,6 +109,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.10.1 // indirect + github.com/stretchr/objx v0.2.0 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect diff --git a/testutil/keeper/mock_defaults.go b/testutil/keeper/mock_defaults.go new file mode 100644 index 0000000000..2f13ebb912 --- /dev/null +++ b/testutil/keeper/mock_defaults.go @@ -0,0 +1,171 @@ +package keeper + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + auth "github.com/cosmos/cosmos-sdk/x/auth/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + conntypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" + "github.com/stretchr/testify/mock" + abci "github.com/tendermint/tendermint/abci/types" +) + +// Defines the default mock implementations of various keepers referenced by the provider keeper. +// If any keeper method is called without an explicit statement that such a call is expected, +// the test will panic, see https://pkg.go.dev/github.com/stretchr/testify/mock#Mock.On +// +// Note: If you need to mock the behavior of specific keeper method(s) in a different +// way than the provided defaults, you can define a new mock implementation in another file. + +type MockChannelKeeper struct { + mock.Mock +} + +func (m MockChannelKeeper) GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) { + m.Called(ctx, srcPort, srcChan) + return channel, false +} +func (m MockChannelKeeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) { + m.Called(ctx, portID, channelID) + return 0, false +} +func (m MockChannelKeeper) SendPacket(ctx sdk.Context, channelCap *capabilitytypes.Capability, packet ibcexported.PacketI) error { + m.Called(ctx, channelCap, packet) + return nil +} +func (m MockChannelKeeper) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, acknowledgement ibcexported.Acknowledgement) error { + m.Called(ctx, chanCap, packet, acknowledgement) + return nil +} +func (m MockChannelKeeper) ChanCloseInit(ctx sdk.Context, portID, channelID string, chanCap *capabilitytypes.Capability) error { + m.Called(ctx, portID, channelID, chanCap) + return nil +} + +type MockPortKeeper struct { + mock.Mock +} + +func (m MockPortKeeper) BindPort(ctx sdk.Context, portID string) *capabilitytypes.Capability { + m.Called(ctx, portID) + return &capabilitytypes.Capability{} +} + +type MockConnectionKeeper struct { + mock.Mock +} + +func (m MockConnectionKeeper) GetConnection(ctx sdk.Context, connectionID string) (conntypes.ConnectionEnd, bool) { + m.Called(ctx, connectionID) + return conntypes.ConnectionEnd{}, false +} + +type MockClientKeeper struct { + mock.Mock +} + +func (m MockClientKeeper) CreateClient(ctx sdk.Context, clientState ibcexported.ClientState, consensusState ibcexported.ConsensusState) (string, error) { + m.Called(ctx, clientState, consensusState) + return "", nil +} +func (m MockClientKeeper) GetClientState(ctx sdk.Context, clientID string) (ibcexported.ClientState, bool) { + m.Called(ctx, clientID) + return nil, false +} +func (m MockClientKeeper) GetLatestClientConsensusState(ctx sdk.Context, clientID string) (ibcexported.ConsensusState, bool) { + m.Called(ctx, clientID) + return nil, false +} +func (m MockClientKeeper) GetSelfConsensusState(ctx sdk.Context, height ibcexported.Height) (ibcexported.ConsensusState, error) { + m.Called(ctx, height) + return nil, nil +} + +type MockStakingKeeper struct { + mock.Mock +} + +func (m MockStakingKeeper) GetValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate { + m.Called(ctx) + return nil +} +func (m MockStakingKeeper) UnbondingCanComplete(ctx sdk.Context, id uint64) error { + m.Called(ctx, id) + return nil +} +func (m MockStakingKeeper) UnbondingTime(ctx sdk.Context) time.Duration { + m.Called(ctx) + return 0 +} + +// Returns a bonded validator with the given address +func (m MockStakingKeeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator stakingtypes.Validator, found bool) { + m.Called(ctx, consAddr) + val := stakingtypes.Validator{ + Status: stakingtypes.Bonded, + } + return val, true +} +func (m MockStakingKeeper) Jail(ctx sdk.Context, addr sdk.ConsAddress) { + m.Called(ctx, addr) +} +func (m MockStakingKeeper) Slash(ctx sdk.Context, addr sdk.ConsAddress, + infractionHeight int64, power int64, slashFraction sdk.Dec, infraction stakingtypes.InfractionType) { + m.Called(ctx, addr, infractionHeight, power, slashFraction, infraction) +} +func (m MockStakingKeeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, found bool) { + return stakingtypes.Validator{}, false +} +func (m MockStakingKeeper) IterateLastValidatorPowers(ctx sdk.Context, cb func(addr sdk.ValAddress, power int64) (stop bool)) { +} +func (m MockStakingKeeper) PowerReduction(ctx sdk.Context) sdk.Int { + return sdk.ZeroInt() +} +func (m MockStakingKeeper) PutUnbondingOnHold(ctx sdk.Context, id uint64) error { + return nil +} + +type MockSlashingKeeper struct { + mock.Mock +} + +func (m MockSlashingKeeper) JailUntil(ctx sdk.Context, addr sdk.ConsAddress, t time.Time) { + m.Called(ctx, addr, t) +} +func (m MockSlashingKeeper) GetValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress) (info slashingtypes.ValidatorSigningInfo, found bool) { + m.Called(ctx, address) + return slashingtypes.ValidatorSigningInfo{}, false +} +func (m MockSlashingKeeper) DowntimeJailDuration(ctx sdk.Context) time.Duration { + m.Called(ctx) + return 0 +} +func (m MockSlashingKeeper) SlashFractionDowntime(ctx sdk.Context) sdk.Dec { + m.Called(ctx) + return sdk.Dec{} +} +func (m MockSlashingKeeper) SlashFractionDoubleSign(ctx sdk.Context) (res sdk.Dec) { + m.Called(ctx) + return sdk.NewDec(1) +} +func (m MockSlashingKeeper) Tombstone(ctx sdk.Context, addr sdk.ConsAddress) { + m.Called(ctx, addr) +} +func (m MockSlashingKeeper) IsTombstoned(ctx sdk.Context, addr sdk.ConsAddress) bool { + m.Called(ctx, addr) + return false +} + +type MockAccountKeeper struct { + mock.Mock +} + +func (m MockAccountKeeper) GetModuleAccount(ctx sdk.Context, name string) auth.ModuleAccountI { + m.Called(ctx, name) + return nil +} diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go index 11eb8ed615..8cd36c97eb 100644 --- a/testutil/keeper/unit_test_helpers.go +++ b/testutil/keeper/unit_test_helpers.go @@ -2,26 +2,17 @@ package keeper import ( "testing" - "time" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/store" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - auth "github.com/cosmos/cosmos-sdk/x/auth/types" capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" - slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - conntypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" - channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" "github.com/cosmos/interchain-security/x/ccv/types" "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmdb "github.com/tendermint/tm-db" @@ -37,13 +28,13 @@ func GetProviderKeeperAndCtx(t testing.TB) (providerkeeper.Keeper, sdk.Context) storeKey, paramsSubspace, capabilitykeeper.ScopedKeeper{}, - DummyChannelKeeper{}, - DummyPortKeeper{}, - DummyConnectionKeeper{}, - DummyClientKeeper{}, - DummyStakingKeeper{}, - DummySlashingKeeper{}, - DummyAccountKeeper{}, + MockChannelKeeper{}, + MockPortKeeper{}, + MockConnectionKeeper{}, + MockClientKeeper{}, + MockStakingKeeper{}, + MockSlashingKeeper{}, + MockAccountKeeper{}, "", ) return k, ctx @@ -107,104 +98,3 @@ func SetupInMemKeeper(t testing.TB) (*codec.ProtoCodec, *storetypes.KVStoreKey, ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) return cdc, storeKey, paramsSubspace, ctx } - -type DummyChannelKeeper struct{} - -func (DummyChannelKeeper) GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) { - return channel, found -} -func (DummyChannelKeeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) { - return 0, false -} -func (DummyChannelKeeper) SendPacket(ctx sdk.Context, channelCap *capabilitytypes.Capability, packet ibcexported.PacketI) error { - return nil -} -func (DummyChannelKeeper) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, acknowledgement ibcexported.Acknowledgement) error { - return nil -} -func (DummyChannelKeeper) ChanCloseInit(ctx sdk.Context, portID, channelID string, chanCap *capabilitytypes.Capability) error { - return nil -} - -type DummyPortKeeper struct{} - -func (DummyPortKeeper) BindPort(ctx sdk.Context, portID string) *capabilitytypes.Capability { - return &capabilitytypes.Capability{} -} - -type DummyConnectionKeeper struct{} - -func (DummyConnectionKeeper) GetConnection(ctx sdk.Context, connectionID string) (conntypes.ConnectionEnd, bool) { - return conntypes.ConnectionEnd{}, false -} - -type DummyClientKeeper struct{} - -func (d DummyClientKeeper) CreateClient(ctx sdk.Context, clientState ibcexported.ClientState, consensusState ibcexported.ConsensusState) (string, error) { - return "", nil -} -func (d DummyClientKeeper) GetClientState(ctx sdk.Context, clientID string) (ibcexported.ClientState, bool) { - return nil, false -} -func (d DummyClientKeeper) GetLatestClientConsensusState(ctx sdk.Context, clientID string) (ibcexported.ConsensusState, bool) { - return nil, false -} -func (d DummyClientKeeper) GetSelfConsensusState(ctx sdk.Context, height ibcexported.Height) (ibcexported.ConsensusState, error) { - return nil, nil -} - -type DummyStakingKeeper struct{} - -func (m DummyStakingKeeper) GetValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate { - return nil -} -func (m DummyStakingKeeper) UnbondingCanComplete(ctx sdk.Context, id uint64) error { - return nil -} -func (m DummyStakingKeeper) UnbondingTime(ctx sdk.Context) time.Duration { - return 0 -} -func (m DummyStakingKeeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator stakingtypes.Validator, found bool) { - return stakingtypes.Validator{}, false -} -func (m DummyStakingKeeper) Jail(sdk.Context, sdk.ConsAddress) { -} -func (m DummyStakingKeeper) Slash(sdk.Context, sdk.ConsAddress, int64, int64, sdk.Dec, stakingtypes.InfractionType) { -} -func (m DummyStakingKeeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, found bool) { - return stakingtypes.Validator{}, false -} -func (m DummyStakingKeeper) IterateLastValidatorPowers(ctx sdk.Context, cb func(addr sdk.ValAddress, power int64) (stop bool)) { -} -func (m DummyStakingKeeper) PowerReduction(ctx sdk.Context) sdk.Int { - return sdk.ZeroInt() -} -func (m DummyStakingKeeper) PutUnbondingOnHold(ctx sdk.Context, id uint64) error { - return nil -} - -type DummySlashingKeeper struct{} - -func (d DummySlashingKeeper) JailUntil(sdk.Context, sdk.ConsAddress, time.Time) {} -func (d DummySlashingKeeper) GetValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress) (info slashingtypes.ValidatorSigningInfo, found bool) { - return slashingtypes.ValidatorSigningInfo{}, false -} -func (d DummySlashingKeeper) DowntimeJailDuration(sdk.Context) time.Duration { - return 0 -} -func (d DummySlashingKeeper) SlashFractionDowntime(sdk.Context) sdk.Dec { - return sdk.Dec{} -} -func (d DummySlashingKeeper) SlashFractionDoubleSign(ctx sdk.Context) (res sdk.Dec) { - return res -} -func (d DummySlashingKeeper) Tombstone(sdk.Context, sdk.ConsAddress) {} -func (d DummySlashingKeeper) IsTombstoned(sdk.Context, sdk.ConsAddress) bool { - return false -} - -type DummyAccountKeeper struct{} - -func (d DummyAccountKeeper) GetModuleAccount(ctx sdk.Context, name string) auth.ModuleAccountI { - return nil -} diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 968ee511ce..b4bf05a790 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" @@ -280,6 +281,7 @@ func TestInitHeight(t *testing.T) { } } +// Tests the handling of a double-signing related slash packet, with e2e tests func (suite *KeeperTestSuite) TestHandleSlashPacketDoubleSigning() { providerKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper providerSlashingKeeper := suite.providerChain.App.(*appProvider.App).SlashingKeeper @@ -320,6 +322,69 @@ func (suite *KeeperTestSuite) TestHandleSlashPacketDoubleSigning() { suite.Require().True(signingInfo.Tombstoned) } +// Tests the handling of a double-signing related slash packet, with mocks and unit tests +// TODO(Shawn): Add in assertions to return values once https://github.com/stretchr/testify/issues/1251 is resolved +func TestHandleSlashPacketDoubleSigning(t *testing.T) { + chainId := "consumer" + infractionHeight := int64(5) + + cdc, storeKey, paramsSubspace, ctx := testkeeper.SetupInMemKeeper(t) + + slashPacket := ccv.NewSlashPacketData( + abci.Validator{Address: ed25519.GenPrivKey().PubKey().Address(), + Power: int64(0)}, + uint64(0), + stakingtypes.DoubleSign, + ) + + // Setup expected mock calls + mockStakingKeeper := testkeeper.MockStakingKeeper{} + mockStakingKeeper.On("Slash", + ctx, + sdk.ConsAddress(slashPacket.Validator.Address), + infractionHeight, + int64(0), // power + sdk.NewDec(1), // Slash fraction + stakingtypes.DoubleSign).Once() + + mockStakingKeeper.On("Jail", + ctx, + sdk.ConsAddress(slashPacket.Validator.Address)).Once() + + mockStakingKeeper.On("GetValidatorByConsAddr", + ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Once() + + mockSlashingKeeper := testkeeper.MockSlashingKeeper{} + mockSlashingKeeper.On("SlashFractionDoubleSign", ctx).Once() + mockSlashingKeeper.On("JailUntil", ctx, sdk.ConsAddress(slashPacket.Validator.Address), + evidencetypes.DoubleSignJailEndTime).Once() + mockSlashingKeeper.On("IsTombstoned", ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Once() + mockSlashingKeeper.On("Tombstone", ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Once() + + providerKeeper := testkeeper.GetProviderKeeperWithMocks(t, + cdc, + storeKey, + paramsSubspace, + ctx, + capabilitykeeper.ScopedKeeper{}, + testkeeper.MockChannelKeeper{}, + testkeeper.MockPortKeeper{}, + testkeeper.MockConnectionKeeper{}, + testkeeper.MockClientKeeper{}, + mockStakingKeeper, + mockSlashingKeeper, + testkeeper.MockAccountKeeper{}, + ) + + providerKeeper.SetInitChainHeight(ctx, chainId, uint64(infractionHeight)) + + success, err := providerKeeper.HandleSlashPacket(ctx, chainId, slashPacket) + require.NoError(t, err) + require.True(t, success) + mockSlashingKeeper.AssertExpectations(t) + mockStakingKeeper.AssertExpectations(t) +} + func (suite *KeeperTestSuite) TestHandleSlashPacketErrors() { providerStakingKeeper := suite.providerChain.App.(*appProvider.App).StakingKeeper ProviderKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper @@ -526,17 +591,17 @@ func TestIterateOverUnbondingOpIndex(t *testing.T) { } func TestMaturedUnbondingOps(t *testing.T) { - keeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) + providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) - ids, err := keeper.GetMaturedUnbondingOps(ctx) + ids, err := providerKeeper.GetMaturedUnbondingOps(ctx) require.NoError(t, err) require.Nil(t, ids) unbondingOpIds := []uint64{0, 1, 2, 3, 4, 5, 6} - err = keeper.AppendMaturedUnbondingOps(ctx, unbondingOpIds) + err = providerKeeper.AppendMaturedUnbondingOps(ctx, unbondingOpIds) require.NoError(t, err) - ids, err = keeper.EmptyMaturedUnbondingOps(ctx) + ids, err = providerKeeper.EmptyMaturedUnbondingOps(ctx) require.NoError(t, err) require.Equal(t, len(unbondingOpIds), len(ids)) for i := 0; i < len(unbondingOpIds); i++ { diff --git a/x/ccv/provider/keeper/params_test.go b/x/ccv/provider/keeper/params_test.go index 171315c0ab..adc3260932 100644 --- a/x/ccv/provider/keeper/params_test.go +++ b/x/ccv/provider/keeper/params_test.go @@ -34,13 +34,13 @@ func TestParams(t *testing.T) { paramsSubspace, ctx, capabilitykeeper.ScopedKeeper{}, - testkeeper.DummyChannelKeeper{}, - testkeeper.DummyPortKeeper{}, - testkeeper.DummyConnectionKeeper{}, - testkeeper.DummyClientKeeper{}, - testkeeper.DummyStakingKeeper{}, - testkeeper.DummySlashingKeeper{}, - testkeeper.DummyAccountKeeper{}, + testkeeper.MockChannelKeeper{}, + testkeeper.MockPortKeeper{}, + testkeeper.MockConnectionKeeper{}, + testkeeper.MockClientKeeper{}, + testkeeper.MockStakingKeeper{}, + testkeeper.MockSlashingKeeper{}, + testkeeper.MockAccountKeeper{}, ) params := providerKeeper.GetParams(ctx) diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go index b200ab709e..63e876486f 100644 --- a/x/ccv/provider/keeper/proposal.go +++ b/x/ccv/provider/keeper/proposal.go @@ -231,14 +231,17 @@ func (k Keeper) SetPendingCreateProposal(ctx sdk.Context, clientInfo *types.Crea } // GetPendingCreateProposal retrieves a pending proposal to create a consumer chain client (by spawn time and chain id) -func (k Keeper) GetPendingCreateProposal(ctx sdk.Context, timestamp time.Time, chainID string) types.CreateConsumerChainProposal { +func (k Keeper) GetPendingCreateProposal(ctx sdk.Context, spawnTime time.Time, chainID string) types.CreateConsumerChainProposal { store := ctx.KVStore(k.storeKey) - bz := store.Get(types.PendingCreateProposalKey(timestamp, chainID)) + bz := store.Get(types.PendingCreateProposalKey(spawnTime, chainID)) if len(bz) == 0 { return types.CreateConsumerChainProposal{} } var clientInfo types.CreateConsumerChainProposal k.cdc.MustUnmarshal(bz, &clientInfo) + // Populate info that's only stored in key, not store value + clientInfo.SpawnTime = spawnTime + clientInfo.ChainId = chainID return clientInfo } @@ -287,6 +290,7 @@ func (k Keeper) CreateProposalsToExecute(ctx sdk.Context) []types.CreateConsumer var prop types.CreateConsumerChainProposal k.cdc.MustUnmarshal(iterator.Value(), &prop) + // Populate info that's only stored in key, not store value prop.ChainId = chainID prop.SpawnTime = spawnTime @@ -379,10 +383,10 @@ func (k Keeper) StopProposalsToExecute(ctx sdk.Context) []types.StopConsumerChai } if !ctx.BlockTime().Before(stopTime) { - // No more proposals to check, since they're stored/ordered by timestamp. propsToExecute = append(propsToExecute, types.StopConsumerChainProposal{ChainId: chainID, StopTime: stopTime}) } else { + // No more proposals to check, since they're stored/ordered by timestamp. break } } From e08d03013df6091a5eb656f4e2d9c999eb956e9a Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Mon, 15 Aug 2022 15:59:40 -0700 Subject: [PATCH 09/24] testify -> gomock --- go.mod | 6 +- testutil/keeper/mock_defaults.go | 171 ------ testutil/keeper/mocks.go | 765 +++++++++++++++++++++++++++ testutil/keeper/unit_test_helpers.go | 14 +- x/ccv/provider/keeper/keeper_test.go | 52 +- x/ccv/provider/keeper/params_test.go | 14 +- 6 files changed, 811 insertions(+), 211 deletions(-) delete mode 100644 testutil/keeper/mock_defaults.go create mode 100644 testutil/keeper/mocks.go diff --git a/go.mod b/go.mod index ea9d9d328e..89b8f6bf81 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,10 @@ require ( gopkg.in/yaml.v2 v2.4.0 ) -require github.com/regen-network/cosmos-proto v0.3.1 +require ( + github.com/golang/mock v1.6.0 + github.com/regen-network/cosmos-proto v0.3.1 +) require ( filippo.io/edwards25519 v1.0.0-beta.2 // indirect @@ -109,7 +112,6 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.10.1 // indirect - github.com/stretchr/objx v0.2.0 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect diff --git a/testutil/keeper/mock_defaults.go b/testutil/keeper/mock_defaults.go deleted file mode 100644 index 2f13ebb912..0000000000 --- a/testutil/keeper/mock_defaults.go +++ /dev/null @@ -1,171 +0,0 @@ -package keeper - -import ( - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - auth "github.com/cosmos/cosmos-sdk/x/auth/types" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - conntypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" - channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" - "github.com/stretchr/testify/mock" - abci "github.com/tendermint/tendermint/abci/types" -) - -// Defines the default mock implementations of various keepers referenced by the provider keeper. -// If any keeper method is called without an explicit statement that such a call is expected, -// the test will panic, see https://pkg.go.dev/github.com/stretchr/testify/mock#Mock.On -// -// Note: If you need to mock the behavior of specific keeper method(s) in a different -// way than the provided defaults, you can define a new mock implementation in another file. - -type MockChannelKeeper struct { - mock.Mock -} - -func (m MockChannelKeeper) GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) { - m.Called(ctx, srcPort, srcChan) - return channel, false -} -func (m MockChannelKeeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) { - m.Called(ctx, portID, channelID) - return 0, false -} -func (m MockChannelKeeper) SendPacket(ctx sdk.Context, channelCap *capabilitytypes.Capability, packet ibcexported.PacketI) error { - m.Called(ctx, channelCap, packet) - return nil -} -func (m MockChannelKeeper) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, acknowledgement ibcexported.Acknowledgement) error { - m.Called(ctx, chanCap, packet, acknowledgement) - return nil -} -func (m MockChannelKeeper) ChanCloseInit(ctx sdk.Context, portID, channelID string, chanCap *capabilitytypes.Capability) error { - m.Called(ctx, portID, channelID, chanCap) - return nil -} - -type MockPortKeeper struct { - mock.Mock -} - -func (m MockPortKeeper) BindPort(ctx sdk.Context, portID string) *capabilitytypes.Capability { - m.Called(ctx, portID) - return &capabilitytypes.Capability{} -} - -type MockConnectionKeeper struct { - mock.Mock -} - -func (m MockConnectionKeeper) GetConnection(ctx sdk.Context, connectionID string) (conntypes.ConnectionEnd, bool) { - m.Called(ctx, connectionID) - return conntypes.ConnectionEnd{}, false -} - -type MockClientKeeper struct { - mock.Mock -} - -func (m MockClientKeeper) CreateClient(ctx sdk.Context, clientState ibcexported.ClientState, consensusState ibcexported.ConsensusState) (string, error) { - m.Called(ctx, clientState, consensusState) - return "", nil -} -func (m MockClientKeeper) GetClientState(ctx sdk.Context, clientID string) (ibcexported.ClientState, bool) { - m.Called(ctx, clientID) - return nil, false -} -func (m MockClientKeeper) GetLatestClientConsensusState(ctx sdk.Context, clientID string) (ibcexported.ConsensusState, bool) { - m.Called(ctx, clientID) - return nil, false -} -func (m MockClientKeeper) GetSelfConsensusState(ctx sdk.Context, height ibcexported.Height) (ibcexported.ConsensusState, error) { - m.Called(ctx, height) - return nil, nil -} - -type MockStakingKeeper struct { - mock.Mock -} - -func (m MockStakingKeeper) GetValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate { - m.Called(ctx) - return nil -} -func (m MockStakingKeeper) UnbondingCanComplete(ctx sdk.Context, id uint64) error { - m.Called(ctx, id) - return nil -} -func (m MockStakingKeeper) UnbondingTime(ctx sdk.Context) time.Duration { - m.Called(ctx) - return 0 -} - -// Returns a bonded validator with the given address -func (m MockStakingKeeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator stakingtypes.Validator, found bool) { - m.Called(ctx, consAddr) - val := stakingtypes.Validator{ - Status: stakingtypes.Bonded, - } - return val, true -} -func (m MockStakingKeeper) Jail(ctx sdk.Context, addr sdk.ConsAddress) { - m.Called(ctx, addr) -} -func (m MockStakingKeeper) Slash(ctx sdk.Context, addr sdk.ConsAddress, - infractionHeight int64, power int64, slashFraction sdk.Dec, infraction stakingtypes.InfractionType) { - m.Called(ctx, addr, infractionHeight, power, slashFraction, infraction) -} -func (m MockStakingKeeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, found bool) { - return stakingtypes.Validator{}, false -} -func (m MockStakingKeeper) IterateLastValidatorPowers(ctx sdk.Context, cb func(addr sdk.ValAddress, power int64) (stop bool)) { -} -func (m MockStakingKeeper) PowerReduction(ctx sdk.Context) sdk.Int { - return sdk.ZeroInt() -} -func (m MockStakingKeeper) PutUnbondingOnHold(ctx sdk.Context, id uint64) error { - return nil -} - -type MockSlashingKeeper struct { - mock.Mock -} - -func (m MockSlashingKeeper) JailUntil(ctx sdk.Context, addr sdk.ConsAddress, t time.Time) { - m.Called(ctx, addr, t) -} -func (m MockSlashingKeeper) GetValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress) (info slashingtypes.ValidatorSigningInfo, found bool) { - m.Called(ctx, address) - return slashingtypes.ValidatorSigningInfo{}, false -} -func (m MockSlashingKeeper) DowntimeJailDuration(ctx sdk.Context) time.Duration { - m.Called(ctx) - return 0 -} -func (m MockSlashingKeeper) SlashFractionDowntime(ctx sdk.Context) sdk.Dec { - m.Called(ctx) - return sdk.Dec{} -} -func (m MockSlashingKeeper) SlashFractionDoubleSign(ctx sdk.Context) (res sdk.Dec) { - m.Called(ctx) - return sdk.NewDec(1) -} -func (m MockSlashingKeeper) Tombstone(ctx sdk.Context, addr sdk.ConsAddress) { - m.Called(ctx, addr) -} -func (m MockSlashingKeeper) IsTombstoned(ctx sdk.Context, addr sdk.ConsAddress) bool { - m.Called(ctx, addr) - return false -} - -type MockAccountKeeper struct { - mock.Mock -} - -func (m MockAccountKeeper) GetModuleAccount(ctx sdk.Context, name string) auth.ModuleAccountI { - m.Called(ctx, name) - return nil -} diff --git a/testutil/keeper/mocks.go b/testutil/keeper/mocks.go new file mode 100644 index 0000000000..fd6e877191 --- /dev/null +++ b/testutil/keeper/mocks.go @@ -0,0 +1,765 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: x/ccv/types/expected_keepers.go + +// Package mock_types is a generated GoMock package. +package keeper + +import ( + context "context" + reflect "reflect" + time "time" + + types "github.com/cosmos/cosmos-sdk/types" + types0 "github.com/cosmos/cosmos-sdk/x/auth/types" + types1 "github.com/cosmos/cosmos-sdk/x/capability/types" + types2 "github.com/cosmos/cosmos-sdk/x/slashing/types" + types3 "github.com/cosmos/cosmos-sdk/x/staking/types" + types4 "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" + types5 "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" + types6 "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + exported "github.com/cosmos/ibc-go/v3/modules/core/exported" + gomock "github.com/golang/mock/gomock" + types7 "github.com/tendermint/tendermint/abci/types" +) + +// MockStakingKeeper is a mock of StakingKeeper interface. +type MockStakingKeeper struct { + ctrl *gomock.Controller + recorder *MockStakingKeeperMockRecorder +} + +// MockStakingKeeperMockRecorder is the mock recorder for MockStakingKeeper. +type MockStakingKeeperMockRecorder struct { + mock *MockStakingKeeper +} + +// NewMockStakingKeeper creates a new mock instance. +func NewMockStakingKeeper(ctrl *gomock.Controller) *MockStakingKeeper { + mock := &MockStakingKeeper{ctrl: ctrl} + mock.recorder = &MockStakingKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder { + return m.recorder +} + +// GetValidator mocks base method. +func (m *MockStakingKeeper) GetValidator(ctx types.Context, addr types.ValAddress) (types3.Validator, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetValidator", ctx, addr) + ret0, _ := ret[0].(types3.Validator) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetValidator indicates an expected call of GetValidator. +func (mr *MockStakingKeeperMockRecorder) GetValidator(ctx, addr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidator", reflect.TypeOf((*MockStakingKeeper)(nil).GetValidator), ctx, addr) +} + +// GetValidatorByConsAddr mocks base method. +func (m *MockStakingKeeper) GetValidatorByConsAddr(ctx types.Context, consAddr types.ConsAddress) (types3.Validator, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetValidatorByConsAddr", ctx, consAddr) + ret0, _ := ret[0].(types3.Validator) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetValidatorByConsAddr indicates an expected call of GetValidatorByConsAddr. +func (mr *MockStakingKeeperMockRecorder) GetValidatorByConsAddr(ctx, consAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorByConsAddr", reflect.TypeOf((*MockStakingKeeper)(nil).GetValidatorByConsAddr), ctx, consAddr) +} + +// GetValidatorUpdates mocks base method. +func (m *MockStakingKeeper) GetValidatorUpdates(ctx types.Context) []types7.ValidatorUpdate { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetValidatorUpdates", ctx) + ret0, _ := ret[0].([]types7.ValidatorUpdate) + return ret0 +} + +// GetValidatorUpdates indicates an expected call of GetValidatorUpdates. +func (mr *MockStakingKeeperMockRecorder) GetValidatorUpdates(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorUpdates", reflect.TypeOf((*MockStakingKeeper)(nil).GetValidatorUpdates), ctx) +} + +// IterateLastValidatorPowers mocks base method. +func (m *MockStakingKeeper) IterateLastValidatorPowers(ctx types.Context, cb func(types.ValAddress, int64) bool) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "IterateLastValidatorPowers", ctx, cb) +} + +// IterateLastValidatorPowers indicates an expected call of IterateLastValidatorPowers. +func (mr *MockStakingKeeperMockRecorder) IterateLastValidatorPowers(ctx, cb interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateLastValidatorPowers", reflect.TypeOf((*MockStakingKeeper)(nil).IterateLastValidatorPowers), ctx, cb) +} + +// Jail mocks base method. +func (m *MockStakingKeeper) Jail(arg0 types.Context, arg1 types.ConsAddress) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Jail", arg0, arg1) +} + +// Jail indicates an expected call of Jail. +func (mr *MockStakingKeeperMockRecorder) Jail(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Jail", reflect.TypeOf((*MockStakingKeeper)(nil).Jail), arg0, arg1) +} + +// PowerReduction mocks base method. +func (m *MockStakingKeeper) PowerReduction(ctx types.Context) types.Int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PowerReduction", ctx) + ret0, _ := ret[0].(types.Int) + return ret0 +} + +// PowerReduction indicates an expected call of PowerReduction. +func (mr *MockStakingKeeperMockRecorder) PowerReduction(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PowerReduction", reflect.TypeOf((*MockStakingKeeper)(nil).PowerReduction), ctx) +} + +// PutUnbondingOnHold mocks base method. +func (m *MockStakingKeeper) PutUnbondingOnHold(ctx types.Context, id uint64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PutUnbondingOnHold", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// PutUnbondingOnHold indicates an expected call of PutUnbondingOnHold. +func (mr *MockStakingKeeperMockRecorder) PutUnbondingOnHold(ctx, id interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutUnbondingOnHold", reflect.TypeOf((*MockStakingKeeper)(nil).PutUnbondingOnHold), ctx, id) +} + +// Slash mocks base method. +func (m *MockStakingKeeper) Slash(arg0 types.Context, arg1 types.ConsAddress, arg2, arg3 int64, arg4 types.Dec, arg5 types3.InfractionType) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Slash", arg0, arg1, arg2, arg3, arg4, arg5) +} + +// Slash indicates an expected call of Slash. +func (mr *MockStakingKeeperMockRecorder) Slash(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Slash", reflect.TypeOf((*MockStakingKeeper)(nil).Slash), arg0, arg1, arg2, arg3, arg4, arg5) +} + +// UnbondingCanComplete mocks base method. +func (m *MockStakingKeeper) UnbondingCanComplete(ctx types.Context, id uint64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UnbondingCanComplete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// UnbondingCanComplete indicates an expected call of UnbondingCanComplete. +func (mr *MockStakingKeeperMockRecorder) UnbondingCanComplete(ctx, id interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnbondingCanComplete", reflect.TypeOf((*MockStakingKeeper)(nil).UnbondingCanComplete), ctx, id) +} + +// UnbondingTime mocks base method. +func (m *MockStakingKeeper) UnbondingTime(ctx types.Context) time.Duration { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UnbondingTime", ctx) + ret0, _ := ret[0].(time.Duration) + return ret0 +} + +// UnbondingTime indicates an expected call of UnbondingTime. +func (mr *MockStakingKeeperMockRecorder) UnbondingTime(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnbondingTime", reflect.TypeOf((*MockStakingKeeper)(nil).UnbondingTime), ctx) +} + +// MockSlashingKeeper is a mock of SlashingKeeper interface. +type MockSlashingKeeper struct { + ctrl *gomock.Controller + recorder *MockSlashingKeeperMockRecorder +} + +// MockSlashingKeeperMockRecorder is the mock recorder for MockSlashingKeeper. +type MockSlashingKeeperMockRecorder struct { + mock *MockSlashingKeeper +} + +// NewMockSlashingKeeper creates a new mock instance. +func NewMockSlashingKeeper(ctrl *gomock.Controller) *MockSlashingKeeper { + mock := &MockSlashingKeeper{ctrl: ctrl} + mock.recorder = &MockSlashingKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSlashingKeeper) EXPECT() *MockSlashingKeeperMockRecorder { + return m.recorder +} + +// DowntimeJailDuration mocks base method. +func (m *MockSlashingKeeper) DowntimeJailDuration(arg0 types.Context) time.Duration { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DowntimeJailDuration", arg0) + ret0, _ := ret[0].(time.Duration) + return ret0 +} + +// DowntimeJailDuration indicates an expected call of DowntimeJailDuration. +func (mr *MockSlashingKeeperMockRecorder) DowntimeJailDuration(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DowntimeJailDuration", reflect.TypeOf((*MockSlashingKeeper)(nil).DowntimeJailDuration), arg0) +} + +// GetValidatorSigningInfo mocks base method. +func (m *MockSlashingKeeper) GetValidatorSigningInfo(ctx types.Context, address types.ConsAddress) (types2.ValidatorSigningInfo, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetValidatorSigningInfo", ctx, address) + ret0, _ := ret[0].(types2.ValidatorSigningInfo) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetValidatorSigningInfo indicates an expected call of GetValidatorSigningInfo. +func (mr *MockSlashingKeeperMockRecorder) GetValidatorSigningInfo(ctx, address interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorSigningInfo", reflect.TypeOf((*MockSlashingKeeper)(nil).GetValidatorSigningInfo), ctx, address) +} + +// IsTombstoned mocks base method. +func (m *MockSlashingKeeper) IsTombstoned(arg0 types.Context, arg1 types.ConsAddress) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsTombstoned", arg0, arg1) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsTombstoned indicates an expected call of IsTombstoned. +func (mr *MockSlashingKeeperMockRecorder) IsTombstoned(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsTombstoned", reflect.TypeOf((*MockSlashingKeeper)(nil).IsTombstoned), arg0, arg1) +} + +// JailUntil mocks base method. +func (m *MockSlashingKeeper) JailUntil(arg0 types.Context, arg1 types.ConsAddress, arg2 time.Time) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "JailUntil", arg0, arg1, arg2) +} + +// JailUntil indicates an expected call of JailUntil. +func (mr *MockSlashingKeeperMockRecorder) JailUntil(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "JailUntil", reflect.TypeOf((*MockSlashingKeeper)(nil).JailUntil), arg0, arg1, arg2) +} + +// SlashFractionDoubleSign mocks base method. +func (m *MockSlashingKeeper) SlashFractionDoubleSign(ctx types.Context) types.Dec { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SlashFractionDoubleSign", ctx) + ret0, _ := ret[0].(types.Dec) + return ret0 +} + +// SlashFractionDoubleSign indicates an expected call of SlashFractionDoubleSign. +func (mr *MockSlashingKeeperMockRecorder) SlashFractionDoubleSign(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SlashFractionDoubleSign", reflect.TypeOf((*MockSlashingKeeper)(nil).SlashFractionDoubleSign), ctx) +} + +// SlashFractionDowntime mocks base method. +func (m *MockSlashingKeeper) SlashFractionDowntime(arg0 types.Context) types.Dec { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SlashFractionDowntime", arg0) + ret0, _ := ret[0].(types.Dec) + return ret0 +} + +// SlashFractionDowntime indicates an expected call of SlashFractionDowntime. +func (mr *MockSlashingKeeperMockRecorder) SlashFractionDowntime(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SlashFractionDowntime", reflect.TypeOf((*MockSlashingKeeper)(nil).SlashFractionDowntime), arg0) +} + +// Tombstone mocks base method. +func (m *MockSlashingKeeper) Tombstone(arg0 types.Context, arg1 types.ConsAddress) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Tombstone", arg0, arg1) +} + +// Tombstone indicates an expected call of Tombstone. +func (mr *MockSlashingKeeperMockRecorder) Tombstone(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Tombstone", reflect.TypeOf((*MockSlashingKeeper)(nil).Tombstone), arg0, arg1) +} + +// MockChannelKeeper is a mock of ChannelKeeper interface. +type MockChannelKeeper struct { + ctrl *gomock.Controller + recorder *MockChannelKeeperMockRecorder +} + +// MockChannelKeeperMockRecorder is the mock recorder for MockChannelKeeper. +type MockChannelKeeperMockRecorder struct { + mock *MockChannelKeeper +} + +// NewMockChannelKeeper creates a new mock instance. +func NewMockChannelKeeper(ctrl *gomock.Controller) *MockChannelKeeper { + mock := &MockChannelKeeper{ctrl: ctrl} + mock.recorder = &MockChannelKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockChannelKeeper) EXPECT() *MockChannelKeeperMockRecorder { + return m.recorder +} + +// ChanCloseInit mocks base method. +func (m *MockChannelKeeper) ChanCloseInit(ctx types.Context, portID, channelID string, chanCap *types1.Capability) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChanCloseInit", ctx, portID, channelID, chanCap) + ret0, _ := ret[0].(error) + return ret0 +} + +// ChanCloseInit indicates an expected call of ChanCloseInit. +func (mr *MockChannelKeeperMockRecorder) ChanCloseInit(ctx, portID, channelID, chanCap interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChanCloseInit", reflect.TypeOf((*MockChannelKeeper)(nil).ChanCloseInit), ctx, portID, channelID, chanCap) +} + +// GetChannel mocks base method. +func (m *MockChannelKeeper) GetChannel(ctx types.Context, srcPort, srcChan string) (types6.Channel, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetChannel", ctx, srcPort, srcChan) + ret0, _ := ret[0].(types6.Channel) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetChannel indicates an expected call of GetChannel. +func (mr *MockChannelKeeperMockRecorder) GetChannel(ctx, srcPort, srcChan interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChannel", reflect.TypeOf((*MockChannelKeeper)(nil).GetChannel), ctx, srcPort, srcChan) +} + +// GetNextSequenceSend mocks base method. +func (m *MockChannelKeeper) GetNextSequenceSend(ctx types.Context, portID, channelID string) (uint64, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNextSequenceSend", ctx, portID, channelID) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetNextSequenceSend indicates an expected call of GetNextSequenceSend. +func (mr *MockChannelKeeperMockRecorder) GetNextSequenceSend(ctx, portID, channelID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNextSequenceSend", reflect.TypeOf((*MockChannelKeeper)(nil).GetNextSequenceSend), ctx, portID, channelID) +} + +// SendPacket mocks base method. +func (m *MockChannelKeeper) SendPacket(ctx types.Context, channelCap *types1.Capability, packet exported.PacketI) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendPacket", ctx, channelCap, packet) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendPacket indicates an expected call of SendPacket. +func (mr *MockChannelKeeperMockRecorder) SendPacket(ctx, channelCap, packet interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendPacket", reflect.TypeOf((*MockChannelKeeper)(nil).SendPacket), ctx, channelCap, packet) +} + +// WriteAcknowledgement mocks base method. +func (m *MockChannelKeeper) WriteAcknowledgement(ctx types.Context, chanCap *types1.Capability, packet exported.PacketI, acknowledgement exported.Acknowledgement) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WriteAcknowledgement", ctx, chanCap, packet, acknowledgement) + ret0, _ := ret[0].(error) + return ret0 +} + +// WriteAcknowledgement indicates an expected call of WriteAcknowledgement. +func (mr *MockChannelKeeperMockRecorder) WriteAcknowledgement(ctx, chanCap, packet, acknowledgement interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteAcknowledgement", reflect.TypeOf((*MockChannelKeeper)(nil).WriteAcknowledgement), ctx, chanCap, packet, acknowledgement) +} + +// MockPortKeeper is a mock of PortKeeper interface. +type MockPortKeeper struct { + ctrl *gomock.Controller + recorder *MockPortKeeperMockRecorder +} + +// MockPortKeeperMockRecorder is the mock recorder for MockPortKeeper. +type MockPortKeeperMockRecorder struct { + mock *MockPortKeeper +} + +// NewMockPortKeeper creates a new mock instance. +func NewMockPortKeeper(ctrl *gomock.Controller) *MockPortKeeper { + mock := &MockPortKeeper{ctrl: ctrl} + mock.recorder = &MockPortKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockPortKeeper) EXPECT() *MockPortKeeperMockRecorder { + return m.recorder +} + +// BindPort mocks base method. +func (m *MockPortKeeper) BindPort(ctx types.Context, portID string) *types1.Capability { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BindPort", ctx, portID) + ret0, _ := ret[0].(*types1.Capability) + return ret0 +} + +// BindPort indicates an expected call of BindPort. +func (mr *MockPortKeeperMockRecorder) BindPort(ctx, portID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindPort", reflect.TypeOf((*MockPortKeeper)(nil).BindPort), ctx, portID) +} + +// MockConnectionKeeper is a mock of ConnectionKeeper interface. +type MockConnectionKeeper struct { + ctrl *gomock.Controller + recorder *MockConnectionKeeperMockRecorder +} + +// MockConnectionKeeperMockRecorder is the mock recorder for MockConnectionKeeper. +type MockConnectionKeeperMockRecorder struct { + mock *MockConnectionKeeper +} + +// NewMockConnectionKeeper creates a new mock instance. +func NewMockConnectionKeeper(ctrl *gomock.Controller) *MockConnectionKeeper { + mock := &MockConnectionKeeper{ctrl: ctrl} + mock.recorder = &MockConnectionKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockConnectionKeeper) EXPECT() *MockConnectionKeeperMockRecorder { + return m.recorder +} + +// GetConnection mocks base method. +func (m *MockConnectionKeeper) GetConnection(ctx types.Context, connectionID string) (types5.ConnectionEnd, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetConnection", ctx, connectionID) + ret0, _ := ret[0].(types5.ConnectionEnd) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetConnection indicates an expected call of GetConnection. +func (mr *MockConnectionKeeperMockRecorder) GetConnection(ctx, connectionID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConnection", reflect.TypeOf((*MockConnectionKeeper)(nil).GetConnection), ctx, connectionID) +} + +// MockClientKeeper is a mock of ClientKeeper interface. +type MockClientKeeper struct { + ctrl *gomock.Controller + recorder *MockClientKeeperMockRecorder +} + +// MockClientKeeperMockRecorder is the mock recorder for MockClientKeeper. +type MockClientKeeperMockRecorder struct { + mock *MockClientKeeper +} + +// NewMockClientKeeper creates a new mock instance. +func NewMockClientKeeper(ctrl *gomock.Controller) *MockClientKeeper { + mock := &MockClientKeeper{ctrl: ctrl} + mock.recorder = &MockClientKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockClientKeeper) EXPECT() *MockClientKeeperMockRecorder { + return m.recorder +} + +// CreateClient mocks base method. +func (m *MockClientKeeper) CreateClient(ctx types.Context, clientState exported.ClientState, consensusState exported.ConsensusState) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateClient", ctx, clientState, consensusState) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateClient indicates an expected call of CreateClient. +func (mr *MockClientKeeperMockRecorder) CreateClient(ctx, clientState, consensusState interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateClient", reflect.TypeOf((*MockClientKeeper)(nil).CreateClient), ctx, clientState, consensusState) +} + +// GetClientState mocks base method. +func (m *MockClientKeeper) GetClientState(ctx types.Context, clientID string) (exported.ClientState, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetClientState", ctx, clientID) + ret0, _ := ret[0].(exported.ClientState) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetClientState indicates an expected call of GetClientState. +func (mr *MockClientKeeperMockRecorder) GetClientState(ctx, clientID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClientState", reflect.TypeOf((*MockClientKeeper)(nil).GetClientState), ctx, clientID) +} + +// GetLatestClientConsensusState mocks base method. +func (m *MockClientKeeper) GetLatestClientConsensusState(ctx types.Context, clientID string) (exported.ConsensusState, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLatestClientConsensusState", ctx, clientID) + ret0, _ := ret[0].(exported.ConsensusState) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetLatestClientConsensusState indicates an expected call of GetLatestClientConsensusState. +func (mr *MockClientKeeperMockRecorder) GetLatestClientConsensusState(ctx, clientID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLatestClientConsensusState", reflect.TypeOf((*MockClientKeeper)(nil).GetLatestClientConsensusState), ctx, clientID) +} + +// GetSelfConsensusState mocks base method. +func (m *MockClientKeeper) GetSelfConsensusState(ctx types.Context, height exported.Height) (exported.ConsensusState, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSelfConsensusState", ctx, height) + ret0, _ := ret[0].(exported.ConsensusState) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSelfConsensusState indicates an expected call of GetSelfConsensusState. +func (mr *MockClientKeeperMockRecorder) GetSelfConsensusState(ctx, height interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSelfConsensusState", reflect.TypeOf((*MockClientKeeper)(nil).GetSelfConsensusState), ctx, height) +} + +// MockConsumerHooks is a mock of ConsumerHooks interface. +type MockConsumerHooks struct { + ctrl *gomock.Controller + recorder *MockConsumerHooksMockRecorder +} + +// MockConsumerHooksMockRecorder is the mock recorder for MockConsumerHooks. +type MockConsumerHooksMockRecorder struct { + mock *MockConsumerHooks +} + +// NewMockConsumerHooks creates a new mock instance. +func NewMockConsumerHooks(ctrl *gomock.Controller) *MockConsumerHooks { + mock := &MockConsumerHooks{ctrl: ctrl} + mock.recorder = &MockConsumerHooksMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockConsumerHooks) EXPECT() *MockConsumerHooksMockRecorder { + return m.recorder +} + +// AfterValidatorBonded mocks base method. +func (m *MockConsumerHooks) AfterValidatorBonded(ctx types.Context, consAddr types.ConsAddress, arg2 types.ValAddress) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AfterValidatorBonded", ctx, consAddr, arg2) +} + +// AfterValidatorBonded indicates an expected call of AfterValidatorBonded. +func (mr *MockConsumerHooksMockRecorder) AfterValidatorBonded(ctx, consAddr, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AfterValidatorBonded", reflect.TypeOf((*MockConsumerHooks)(nil).AfterValidatorBonded), ctx, consAddr, arg2) +} + +// MockBankKeeper is a mock of BankKeeper interface. +type MockBankKeeper struct { + ctrl *gomock.Controller + recorder *MockBankKeeperMockRecorder +} + +// MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper. +type MockBankKeeperMockRecorder struct { + mock *MockBankKeeper +} + +// NewMockBankKeeper creates a new mock instance. +func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper { + mock := &MockBankKeeper{ctrl: ctrl} + mock.recorder = &MockBankKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder { + return m.recorder +} + +// GetAllBalances mocks base method. +func (m *MockBankKeeper) GetAllBalances(ctx types.Context, addr types.AccAddress) types.Coins { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAllBalances", ctx, addr) + ret0, _ := ret[0].(types.Coins) + return ret0 +} + +// GetAllBalances indicates an expected call of GetAllBalances. +func (mr *MockBankKeeperMockRecorder) GetAllBalances(ctx, addr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBalances", reflect.TypeOf((*MockBankKeeper)(nil).GetAllBalances), ctx, addr) +} + +// GetBalance mocks base method. +func (m *MockBankKeeper) GetBalance(ctx types.Context, addr types.AccAddress, denom string) types.Coin { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBalance", ctx, addr, denom) + ret0, _ := ret[0].(types.Coin) + return ret0 +} + +// GetBalance indicates an expected call of GetBalance. +func (mr *MockBankKeeperMockRecorder) GetBalance(ctx, addr, denom interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBalance", reflect.TypeOf((*MockBankKeeper)(nil).GetBalance), ctx, addr, denom) +} + +// SendCoinsFromModuleToModule mocks base method. +func (m *MockBankKeeper) SendCoinsFromModuleToModule(ctx types.Context, senderModule, recipientModule string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromModuleToModule", ctx, senderModule, recipientModule, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromModuleToModule indicates an expected call of SendCoinsFromModuleToModule. +func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToModule(ctx, senderModule, recipientModule, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToModule), ctx, senderModule, recipientModule, amt) +} + +// MockAccountKeeper is a mock of AccountKeeper interface. +type MockAccountKeeper struct { + ctrl *gomock.Controller + recorder *MockAccountKeeperMockRecorder +} + +// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper. +type MockAccountKeeperMockRecorder struct { + mock *MockAccountKeeper +} + +// NewMockAccountKeeper creates a new mock instance. +func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper { + mock := &MockAccountKeeper{ctrl: ctrl} + mock.recorder = &MockAccountKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder { + return m.recorder +} + +// GetModuleAccount mocks base method. +func (m *MockAccountKeeper) GetModuleAccount(ctx types.Context, name string) types0.ModuleAccountI { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetModuleAccount", ctx, name) + ret0, _ := ret[0].(types0.ModuleAccountI) + return ret0 +} + +// GetModuleAccount indicates an expected call of GetModuleAccount. +func (mr *MockAccountKeeperMockRecorder) GetModuleAccount(ctx, name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAccount), ctx, name) +} + +// MockIBCTransferKeeper is a mock of IBCTransferKeeper interface. +type MockIBCTransferKeeper struct { + ctrl *gomock.Controller + recorder *MockIBCTransferKeeperMockRecorder +} + +// MockIBCTransferKeeperMockRecorder is the mock recorder for MockIBCTransferKeeper. +type MockIBCTransferKeeperMockRecorder struct { + mock *MockIBCTransferKeeper +} + +// NewMockIBCTransferKeeper creates a new mock instance. +func NewMockIBCTransferKeeper(ctrl *gomock.Controller) *MockIBCTransferKeeper { + mock := &MockIBCTransferKeeper{ctrl: ctrl} + mock.recorder = &MockIBCTransferKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockIBCTransferKeeper) EXPECT() *MockIBCTransferKeeperMockRecorder { + return m.recorder +} + +// SendTransfer mocks base method. +func (m *MockIBCTransferKeeper) SendTransfer(ctx types.Context, sourcePort, sourceChannel string, token types.Coin, sender types.AccAddress, receiver string, timeoutHeight types4.Height, timeoutTimestamp uint64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendTransfer", ctx, sourcePort, sourceChannel, token, sender, receiver, timeoutHeight, timeoutTimestamp) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendTransfer indicates an expected call of SendTransfer. +func (mr *MockIBCTransferKeeperMockRecorder) SendTransfer(ctx, sourcePort, sourceChannel, token, sender, receiver, timeoutHeight, timeoutTimestamp interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTransfer", reflect.TypeOf((*MockIBCTransferKeeper)(nil).SendTransfer), ctx, sourcePort, sourceChannel, token, sender, receiver, timeoutHeight, timeoutTimestamp) +} + +// MockIBCCoreKeeper is a mock of IBCCoreKeeper interface. +type MockIBCCoreKeeper struct { + ctrl *gomock.Controller + recorder *MockIBCCoreKeeperMockRecorder +} + +// MockIBCCoreKeeperMockRecorder is the mock recorder for MockIBCCoreKeeper. +type MockIBCCoreKeeperMockRecorder struct { + mock *MockIBCCoreKeeper +} + +// NewMockIBCCoreKeeper creates a new mock instance. +func NewMockIBCCoreKeeper(ctrl *gomock.Controller) *MockIBCCoreKeeper { + mock := &MockIBCCoreKeeper{ctrl: ctrl} + mock.recorder = &MockIBCCoreKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockIBCCoreKeeper) EXPECT() *MockIBCCoreKeeperMockRecorder { + return m.recorder +} + +// ChannelOpenInit mocks base method. +func (m *MockIBCCoreKeeper) ChannelOpenInit(goCtx context.Context, msg *types6.MsgChannelOpenInit) (*types6.MsgChannelOpenInitResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChannelOpenInit", goCtx, msg) + ret0, _ := ret[0].(*types6.MsgChannelOpenInitResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ChannelOpenInit indicates an expected call of ChannelOpenInit. +func (mr *MockIBCCoreKeeperMockRecorder) ChannelOpenInit(goCtx, msg interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChannelOpenInit", reflect.TypeOf((*MockIBCCoreKeeper)(nil).ChannelOpenInit), goCtx, msg) +} diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go index 8cd36c97eb..71b5bc9382 100644 --- a/testutil/keeper/unit_test_helpers.go +++ b/testutil/keeper/unit_test_helpers.go @@ -28,13 +28,13 @@ func GetProviderKeeperAndCtx(t testing.TB) (providerkeeper.Keeper, sdk.Context) storeKey, paramsSubspace, capabilitykeeper.ScopedKeeper{}, - MockChannelKeeper{}, - MockPortKeeper{}, - MockConnectionKeeper{}, - MockClientKeeper{}, - MockStakingKeeper{}, - MockSlashingKeeper{}, - MockAccountKeeper{}, + &MockChannelKeeper{}, + &MockPortKeeper{}, + &MockConnectionKeeper{}, + &MockClientKeeper{}, + &MockStakingKeeper{}, + &MockSlashingKeeper{}, + &MockAccountKeeper{}, "", ) return k, ctx diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index b4bf05a790..50ac9d7129 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -8,6 +8,7 @@ import ( capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + "github.com/golang/mock/gomock" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" @@ -323,8 +324,10 @@ func (suite *KeeperTestSuite) TestHandleSlashPacketDoubleSigning() { } // Tests the handling of a double-signing related slash packet, with mocks and unit tests -// TODO(Shawn): Add in assertions to return values once https://github.com/stretchr/testify/issues/1251 is resolved func TestHandleSlashPacketDoubleSigning(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + chainId := "consumer" infractionHeight := int64(5) @@ -338,28 +341,31 @@ func TestHandleSlashPacketDoubleSigning(t *testing.T) { ) // Setup expected mock calls - mockStakingKeeper := testkeeper.MockStakingKeeper{} - mockStakingKeeper.On("Slash", + mockStakingKeeper := testkeeper.NewMockStakingKeeper(ctrl) + mockStakingKeeper.EXPECT().Slash( ctx, sdk.ConsAddress(slashPacket.Validator.Address), infractionHeight, int64(0), // power sdk.NewDec(1), // Slash fraction - stakingtypes.DoubleSign).Once() + stakingtypes.DoubleSign).Return().Times(1) - mockStakingKeeper.On("Jail", - ctx, - sdk.ConsAddress(slashPacket.Validator.Address)).Once() + mockStakingKeeper.EXPECT().Jail( + gomock.Eq(ctx), + gomock.Eq(sdk.ConsAddress(slashPacket.Validator.Address)), + ).Return() - mockStakingKeeper.On("GetValidatorByConsAddr", - ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Once() + mockStakingKeeper.EXPECT().GetValidatorByConsAddr( + ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Return( + stakingtypes.Validator{Status: stakingtypes.Bonded}, true, + ).Times(1) - mockSlashingKeeper := testkeeper.MockSlashingKeeper{} - mockSlashingKeeper.On("SlashFractionDoubleSign", ctx).Once() - mockSlashingKeeper.On("JailUntil", ctx, sdk.ConsAddress(slashPacket.Validator.Address), - evidencetypes.DoubleSignJailEndTime).Once() - mockSlashingKeeper.On("IsTombstoned", ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Once() - mockSlashingKeeper.On("Tombstone", ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Once() + mockSlashingKeeper := testkeeper.NewMockSlashingKeeper(ctrl) + mockSlashingKeeper.EXPECT().SlashFractionDoubleSign(ctx).Return(sdk.NewDec(1)).Times(1) + mockSlashingKeeper.EXPECT().JailUntil(ctx, sdk.ConsAddress(slashPacket.Validator.Address), + evidencetypes.DoubleSignJailEndTime).Times(1) + mockSlashingKeeper.EXPECT().IsTombstoned(ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Return(false).Times(1) + mockSlashingKeeper.EXPECT().Tombstone(ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Times(1) providerKeeper := testkeeper.GetProviderKeeperWithMocks(t, cdc, @@ -367,22 +373,20 @@ func TestHandleSlashPacketDoubleSigning(t *testing.T) { paramsSubspace, ctx, capabilitykeeper.ScopedKeeper{}, - testkeeper.MockChannelKeeper{}, - testkeeper.MockPortKeeper{}, - testkeeper.MockConnectionKeeper{}, - testkeeper.MockClientKeeper{}, + testkeeper.NewMockChannelKeeper(ctrl), + testkeeper.NewMockPortKeeper(ctrl), + testkeeper.NewMockConnectionKeeper(ctrl), + testkeeper.NewMockClientKeeper(ctrl), mockStakingKeeper, mockSlashingKeeper, - testkeeper.MockAccountKeeper{}, + testkeeper.NewMockAccountKeeper(ctrl), ) providerKeeper.SetInitChainHeight(ctx, chainId, uint64(infractionHeight)) - success, err := providerKeeper.HandleSlashPacket(ctx, chainId, slashPacket) + _, err := providerKeeper.HandleSlashPacket(ctx, chainId, slashPacket) require.NoError(t, err) - require.True(t, success) - mockSlashingKeeper.AssertExpectations(t) - mockStakingKeeper.AssertExpectations(t) + // require.True(t, success) } func (suite *KeeperTestSuite) TestHandleSlashPacketErrors() { diff --git a/x/ccv/provider/keeper/params_test.go b/x/ccv/provider/keeper/params_test.go index adc3260932..cd5b84bf97 100644 --- a/x/ccv/provider/keeper/params_test.go +++ b/x/ccv/provider/keeper/params_test.go @@ -34,13 +34,13 @@ func TestParams(t *testing.T) { paramsSubspace, ctx, capabilitykeeper.ScopedKeeper{}, - testkeeper.MockChannelKeeper{}, - testkeeper.MockPortKeeper{}, - testkeeper.MockConnectionKeeper{}, - testkeeper.MockClientKeeper{}, - testkeeper.MockStakingKeeper{}, - testkeeper.MockSlashingKeeper{}, - testkeeper.MockAccountKeeper{}, + &testkeeper.MockChannelKeeper{}, + &testkeeper.MockPortKeeper{}, + &testkeeper.MockConnectionKeeper{}, + &testkeeper.MockClientKeeper{}, + &testkeeper.MockStakingKeeper{}, + &testkeeper.MockSlashingKeeper{}, + &testkeeper.MockAccountKeeper{}, ) params := providerKeeper.GetParams(ctx) From d7786f108b57d5828a9ed0719653679a3d9aaf22 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Mon, 15 Aug 2022 16:23:23 -0700 Subject: [PATCH 10/24] small change --- x/ccv/provider/keeper/keeper_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 50ac9d7129..45aac7d579 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -384,9 +384,9 @@ func TestHandleSlashPacketDoubleSigning(t *testing.T) { providerKeeper.SetInitChainHeight(ctx, chainId, uint64(infractionHeight)) - _, err := providerKeeper.HandleSlashPacket(ctx, chainId, slashPacket) + success, err := providerKeeper.HandleSlashPacket(ctx, chainId, slashPacket) require.NoError(t, err) - // require.True(t, success) + require.True(t, success) } func (suite *KeeperTestSuite) TestHandleSlashPacketErrors() { From ecbbe04f4a4aad7eeedf5c3c2b7678e6428942b9 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Tue, 16 Aug 2022 08:53:30 -0700 Subject: [PATCH 11/24] operation order - small change --- x/ccv/provider/keeper/proposal.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go index 63e876486f..e5de585cc7 100644 --- a/x/ccv/provider/keeper/proposal.go +++ b/x/ccv/provider/keeper/proposal.go @@ -271,12 +271,12 @@ func (k Keeper) IteratePendingCreateProposal(ctx sdk.Context) { // Note: this method is split out from IteratePendingCreateProposal to be easily unit tested. func (k Keeper) CreateProposalsToExecute(ctx sdk.Context) []types.CreateConsumerChainProposal { - iterator := k.PendingCreateProposalIterator(ctx) - defer iterator.Close() - // store the (to be) executed proposals in order propsToExecute := []types.CreateConsumerChainProposal{} + iterator := k.PendingCreateProposalIterator(ctx) + defer iterator.Close() + if !iterator.Valid() { return propsToExecute } @@ -364,12 +364,12 @@ func (k Keeper) IteratePendingStopProposal(ctx sdk.Context) { // Note: this method is split out from IteratePendingCreateProposal to be easily unit tested. func (k Keeper) StopProposalsToExecute(ctx sdk.Context) []types.StopConsumerChainProposal { - iterator := k.PendingStopProposalIterator(ctx) - defer iterator.Close() - // store the (to be) executed stop proposals in order propsToExecute := []types.StopConsumerChainProposal{} + iterator := k.PendingStopProposalIterator(ctx) + defer iterator.Close() + if !iterator.Valid() { return propsToExecute } From ec4806698e3de9053b5d6fcc34826423b50a255f Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Wed, 17 Aug 2022 14:02:34 -0700 Subject: [PATCH 12/24] wip --- testutil/keeper/mocks.go | 68 +++++++++- testutil/keeper/unit_test_helpers.go | 71 +++++++++- x/ccv/consumer/keeper/keeper.go | 5 +- x/ccv/consumer/keeper/keeper_test.go | 192 ++++++++++++++++----------- x/ccv/consumer/keeper/params_test.go | 54 ++++---- x/ccv/consumer/keeper/relay_test.go | 106 +++++++++++---- x/ccv/provider/keeper/keeper.go | 5 +- x/ccv/provider/keeper/keeper_test.go | 56 ++++---- x/ccv/provider/keeper/params_test.go | 1 - x/ccv/types/expected_keepers.go | 9 +- x/ccv/utils/utils.go | 5 +- 11 files changed, 397 insertions(+), 175 deletions(-) diff --git a/testutil/keeper/mocks.go b/testutil/keeper/mocks.go index fd6e877191..3ed5c283e2 100644 --- a/testutil/keeper/mocks.go +++ b/testutil/keeper/mocks.go @@ -1,7 +1,6 @@ // Code generated by MockGen. DO NOT EDIT. // Source: x/ccv/types/expected_keepers.go -// Package mock_types is a generated GoMock package. package keeper import ( @@ -763,3 +762,70 @@ func (mr *MockIBCCoreKeeperMockRecorder) ChannelOpenInit(goCtx, msg interface{}) mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChannelOpenInit", reflect.TypeOf((*MockIBCCoreKeeper)(nil).ChannelOpenInit), goCtx, msg) } + + +// MockScopedKeeper is a mock of ScopedKeeper interface. +type MockScopedKeeper struct { + ctrl *gomock.Controller + recorder *MockScopedKeeperMockRecorder +} + +// MockScopedKeeperMockRecorder is the mock recorder for MockScopedKeeper. +type MockScopedKeeperMockRecorder struct { + mock *MockScopedKeeper +} + +// NewMockScopedKeeper creates a new mock instance. +func NewMockScopedKeeper(ctrl *gomock.Controller) *MockScopedKeeper { + mock := &MockScopedKeeper{ctrl: ctrl} + mock.recorder = &MockScopedKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockScopedKeeper) EXPECT() *MockScopedKeeperMockRecorder { + return m.recorder +} + +// AuthenticateCapability mocks base method. +func (m *MockScopedKeeper) AuthenticateCapability(ctx types.Context, cap *types1.Capability, name string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AuthenticateCapability", ctx, cap, name) + ret0, _ := ret[0].(bool) + return ret0 +} + +// AuthenticateCapability indicates an expected call of AuthenticateCapability. +func (mr *MockScopedKeeperMockRecorder) AuthenticateCapability(ctx, cap, name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthenticateCapability", reflect.TypeOf((*MockScopedKeeper)(nil).AuthenticateCapability), ctx, cap, name) +} + +// ClaimCapability mocks base method. +func (m *MockScopedKeeper) ClaimCapability(ctx types.Context, cap *types1.Capability, name string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ClaimCapability", ctx, cap, name) + ret0, _ := ret[0].(error) + return ret0 +} + +// ClaimCapability indicates an expected call of ClaimCapability. +func (mr *MockScopedKeeperMockRecorder) ClaimCapability(ctx, cap, name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClaimCapability", reflect.TypeOf((*MockScopedKeeper)(nil).ClaimCapability), ctx, cap, name) +} + +// GetCapability mocks base method. +func (m *MockScopedKeeper) GetCapability(ctx types.Context, name string) (*types1.Capability, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCapability", ctx, name) + ret0, _ := ret[0].(*types1.Capability) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetCapability indicates an expected call of GetCapability. +func (mr *MockScopedKeeperMockRecorder) GetCapability(ctx, name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCapability", reflect.TypeOf((*MockScopedKeeper)(nil).GetCapability), ctx, name) +} diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go index 71b5bc9382..de682f04ba 100644 --- a/testutil/keeper/unit_test_helpers.go +++ b/testutil/keeper/unit_test_helpers.go @@ -10,6 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" "github.com/cosmos/interchain-security/x/ccv/types" "github.com/stretchr/testify/require" @@ -18,7 +19,7 @@ import ( tmdb "github.com/tendermint/tm-db" ) -// Constructs a keeper and context object for unit tests, backed by an in-memory db. +// Constructs a provider keeper and context object for unit tests, backed by an in-memory db. func GetProviderKeeperAndCtx(t testing.TB) (providerkeeper.Keeper, sdk.Context) { cdc, storeKey, paramsSubspace, ctx := SetupInMemKeeper(t) @@ -27,7 +28,7 @@ func GetProviderKeeperAndCtx(t testing.TB) (providerkeeper.Keeper, sdk.Context) cdc, storeKey, paramsSubspace, - capabilitykeeper.ScopedKeeper{}, + &MockScopedKeeper{}, &MockChannelKeeper{}, &MockPortKeeper{}, &MockConnectionKeeper{}, @@ -40,7 +41,31 @@ func GetProviderKeeperAndCtx(t testing.TB) (providerkeeper.Keeper, sdk.Context) return k, ctx } -// Constructs a keeper for unit tests, backed by an in-memory db, +// Constructs a consumer keeper and context object for unit tests, backed by an in-memory db. +func GetConsumerKeeperAndCtx(t testing.TB) (consumerkeeper.Keeper, sdk.Context) { + + cdc, storeKey, paramsSubspace, ctx := SetupInMemKeeper(t) + + k := consumerkeeper.NewKeeper( + cdc, + storeKey, + paramsSubspace, + &MockScopedKeeper{}, + &MockChannelKeeper{}, + &MockPortKeeper{}, + &MockConnectionKeeper{}, + &MockClientKeeper{}, + &MockSlashingKeeper{}, + &MockBankKeeper{}, + &MockAccountKeeper{}, + &MockIBCTransferKeeper{}, + &MockIBCCoreKeeper{}, + "", + ) + return k, ctx +} + +// Constructs a provider keeper for unit tests, backed by an in-memory db, // with ability to pass mocked or otherwise manipulated parameters. // Note: Use the dummy types defined in this file for keepers you don't wish to mock, // and SetupInMemKeeper() for other parameters you don't wish to manipulate. @@ -48,7 +73,6 @@ func GetProviderKeeperWithMocks(t testing.TB, cdc *codec.ProtoCodec, storeKey *storetypes.KVStoreKey, paramsSubspace paramstypes.Subspace, - ctx sdk.Context, capabilityKeeper capabilitykeeper.ScopedKeeper, channelKeeper types.ChannelKeeper, portKeeper types.PortKeeper, @@ -76,6 +100,45 @@ func GetProviderKeeperWithMocks(t testing.TB, return k } +// Constructs a consumer keeper for unit tests, backed by an in-memory db, +// with ability to pass mocked or otherwise manipulated parameters. +// Note: Use the dummy types defined in this file for keepers you don't wish to mock, +// and SetupInMemKeeper() for other parameters you don't wish to manipulate. +func GetConsumerKeeperWithMocks(t testing.TB, + cdc *codec.ProtoCodec, + storeKey *storetypes.KVStoreKey, + paramsSubspace paramstypes.Subspace, + capabilityKeeper types.ScopedKeeper, + channelKeeper types.ChannelKeeper, + portKeeper types.PortKeeper, + connectionKeeper types.ConnectionKeeper, + clientKeeper types.ClientKeeper, + slashingKeeper types.SlashingKeeper, + bankKeeper types.BankKeeper, + accountKeeper types.AccountKeeper, + ibcTransferKeeper types.IBCTransferKeeper, + ibcCoreKeeper types.IBCCoreKeeper, +) consumerkeeper.Keeper { + + k := consumerkeeper.NewKeeper( + cdc, + storeKey, + paramsSubspace, + capabilityKeeper, + channelKeeper, + portKeeper, + connectionKeeper, + clientKeeper, + slashingKeeper, + bankKeeper, + accountKeeper, + ibcTransferKeeper, + ibcCoreKeeper, + "", + ) + return k +} + func SetupInMemKeeper(t testing.TB) (*codec.ProtoCodec, *storetypes.KVStoreKey, paramstypes.Subspace, sdk.Context) { storeKey := sdk.NewKVStoreKey(types.StoreKey) memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) diff --git a/x/ccv/consumer/keeper/keeper.go b/x/ccv/consumer/keeper/keeper.go index 2885f34382..1cdadcc2c0 100644 --- a/x/ccv/consumer/keeper/keeper.go +++ b/x/ccv/consumer/keeper/keeper.go @@ -9,7 +9,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" @@ -29,7 +28,7 @@ type Keeper struct { storeKey sdk.StoreKey cdc codec.BinaryCodec paramStore paramtypes.Subspace - scopedKeeper capabilitykeeper.ScopedKeeper + scopedKeeper ccv.ScopedKeeper channelKeeper ccv.ChannelKeeper portKeeper ccv.PortKeeper connectionKeeper ccv.ConnectionKeeper @@ -48,7 +47,7 @@ type Keeper struct { // collector (and not the provider chain) func NewKeeper( cdc codec.BinaryCodec, key sdk.StoreKey, paramSpace paramtypes.Subspace, - scopedKeeper capabilitykeeper.ScopedKeeper, + scopedKeeper ccv.ScopedKeeper, channelKeeper ccv.ChannelKeeper, portKeeper ccv.PortKeeper, connectionKeeper ccv.ConnectionKeeper, clientKeeper ccv.ClientKeeper, slashingKeeper ccv.SlashingKeeper, bankKeeper ccv.BankKeeper, accountKeeper ccv.AccountKeeper, diff --git a/x/ccv/consumer/keeper/keeper_test.go b/x/ccv/consumer/keeper/keeper_test.go index d96656f762..54d8dcae97 100644 --- a/x/ccv/consumer/keeper/keeper_test.go +++ b/x/ccv/consumer/keeper/keeper_test.go @@ -6,9 +6,11 @@ import ( "testing" "time" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" sdk "github.com/cosmos/cosmos-sdk/types" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -20,7 +22,9 @@ import ( ibctesting "github.com/cosmos/ibc-go/v3/testing" appConsumer "github.com/cosmos/interchain-security/app/consumer" appProvider "github.com/cosmos/interchain-security/app/provider" + testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/testutil/simapp" + consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" "github.com/cosmos/interchain-security/x/ccv/consumer/types" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" @@ -30,6 +34,8 @@ import ( "github.com/stretchr/testify/suite" abci "github.com/tendermint/tendermint/abci/types" tmtypes "github.com/tendermint/tendermint/types" + + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" ) type KeeperTestSuite struct { @@ -132,20 +138,19 @@ func (suite *KeeperTestSuite) SetupCCVChannel() { suite.coordinator.CreateChannels(suite.path) } -func (suite *KeeperTestSuite) TestUnbondingTime() { - // The unbonding time on the consumer was already set during InitGenesis() - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.DeleteUnbondingTime(suite.ctx) - _, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(suite.ctx) - suite.Require().False(ok) +func TestUnbondingTime(t *testing.T) { + consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) + _, ok := consumerKeeper.GetUnbondingTime(ctx) + require.False(t, ok) unbondingPeriod := time.Hour * 24 * 7 * 3 - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.SetUnbondingTime(suite.ctx, unbondingPeriod) - storedUnbondingPeriod, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(suite.ctx) - suite.Require().True(ok) - suite.Require().True(storedUnbondingPeriod == unbondingPeriod) - + consumerKeeper.SetUnbondingTime(ctx, unbondingPeriod) + storedUnbondingPeriod, ok := consumerKeeper.GetUnbondingTime(ctx) + require.True(t, ok) + require.Equal(t, storedUnbondingPeriod, unbondingPeriod) } -func (suite *KeeperTestSuite) TestProviderClient() { +// Tests that the provider client managed by the consumer keeper matches the client keeper's client state +func (suite *KeeperTestSuite) TestProviderClientMatches() { providerClient, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClient(suite.ctx) suite.Require().True(ok) @@ -153,20 +158,31 @@ func (suite *KeeperTestSuite) TestProviderClient() { suite.Require().Equal(suite.providerClient, clientState, "stored client state does not match genesis provider client") } -func (suite *KeeperTestSuite) TestProviderChannel() { - _, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderChannel(suite.ctx) - suite.Require().False(ok) - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.SetProviderChannel(suite.ctx, "channelID") - channelID, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderChannel(suite.ctx) - suite.Require().True(ok) - suite.Require().Equal("channelID", channelID) +func TestProviderClient(t *testing.T) { + consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) + _, ok := consumerKeeper.GetProviderClient(ctx) + require.False(t, ok) + consumerKeeper.SetProviderClient(ctx, "someClientID") + clientID, ok := consumerKeeper.GetProviderClient(ctx) + require.True(t, ok) + require.Equal(t, "someClientID", clientID) +} + +func TestProviderChannel(t *testing.T) { + consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) + _, ok := consumerKeeper.GetProviderChannel(ctx) + require.False(t, ok) + consumerKeeper.SetProviderChannel(ctx, "channelID") + channelID, ok := consumerKeeper.GetProviderChannel(ctx) + require.True(t, ok) + require.Equal(t, "channelID", channelID) } -func (suite *KeeperTestSuite) TestPendingChanges() { +func TestPendingChanges(t *testing.T) { pk1, err := cryptocodec.ToTmProtoPublicKey(ed25519.GenPrivKey().PubKey()) - suite.Require().NoError(err) + require.NoError(t, err) pk2, err := cryptocodec.ToTmProtoPublicKey(ed25519.GenPrivKey().PubKey()) - suite.Require().NoError(err) + require.NoError(t, err) pd := ccv.NewValidatorSetChangePacketData( []abci.ValidatorUpdate{ @@ -183,38 +199,40 @@ func (suite *KeeperTestSuite) TestPendingChanges() { nil, ) - err = suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.SetPendingChanges(suite.ctx, pd) - suite.Require().NoError(err) - gotPd, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPendingChanges(suite.ctx) - suite.Require().True(ok) - suite.Require().Equal(&pd, gotPd, "packet data in store does not equal packet data set") - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.DeletePendingChanges(suite.ctx) - gotPd, ok = suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPendingChanges(suite.ctx) - suite.Require().False(ok) - suite.Require().Nil(gotPd, "got non-nil pending changes after Delete") + consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) + err = consumerKeeper.SetPendingChanges(ctx, pd) + require.NoError(t, err) + gotPd, ok := consumerKeeper.GetPendingChanges(ctx) + require.True(t, ok) + require.Equal(t, &pd, gotPd, "packet data in store does not equal packet data set") + consumerKeeper.DeletePendingChanges(ctx) + gotPd, ok = consumerKeeper.GetPendingChanges(ctx) + require.False(t, ok) + require.Nil(t, gotPd, "got non-nil pending changes after Delete") } -func (suite *KeeperTestSuite) TestPacketMaturityTime() { - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.SetPacketMaturityTime(suite.ctx, 1, 10) - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.SetPacketMaturityTime(suite.ctx, 2, 25) - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.SetPacketMaturityTime(suite.ctx, 5, 15) - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.SetPacketMaturityTime(suite.ctx, 6, 40) +func TestPacketMaturityTime(t *testing.T) { + consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) + consumerKeeper.SetPacketMaturityTime(ctx, 1, 10) + consumerKeeper.SetPacketMaturityTime(ctx, 2, 25) + consumerKeeper.SetPacketMaturityTime(ctx, 5, 15) + consumerKeeper.SetPacketMaturityTime(ctx, 6, 40) - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.DeletePacketMaturityTime(suite.ctx, 6) + consumerKeeper.DeletePacketMaturityTime(ctx, 6) - suite.Require().Equal(uint64(10), suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.ctx, 1)) - suite.Require().Equal(uint64(25), suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.ctx, 2)) - suite.Require().Equal(uint64(15), suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.ctx, 5)) - suite.Require().Equal(uint64(0), suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.ctx, 3)) - suite.Require().Equal(uint64(0), suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.ctx, 6)) + require.Equal(t, uint64(10), consumerKeeper.GetPacketMaturityTime(ctx, 1)) + require.Equal(t, uint64(25), consumerKeeper.GetPacketMaturityTime(ctx, 2)) + require.Equal(t, uint64(15), consumerKeeper.GetPacketMaturityTime(ctx, 5)) + require.Equal(t, uint64(0), consumerKeeper.GetPacketMaturityTime(ctx, 3)) + require.Equal(t, uint64(0), consumerKeeper.GetPacketMaturityTime(ctx, 6)) orderedTimes := [][]uint64{{1, 10}, {2, 25}, {5, 15}} i := 0 - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.IteratePacketMaturityTime(suite.ctx, func(seq, time uint64) bool { + consumerKeeper.IteratePacketMaturityTime(ctx, func(seq, time uint64) bool { // require that we iterate through unbonding time in order of sequence - suite.Require().Equal(orderedTimes[i][0], seq) - suite.Require().Equal(orderedTimes[i][1], time) + require.Equal(t, orderedTimes[i][0], seq) + require.Equal(t, orderedTimes[i][1], time) i++ return false }) @@ -566,53 +584,69 @@ func (suite *KeeperTestSuite) TestSendSlashPacket() { suite.Require().Len(requests, 0) } -func (suite *KeeperTestSuite) TestCrossChainValidator() { - app := suite.consumerChain.App.(*appConsumer.App) - ctx := suite.consumerChain.GetContext() +func TestCrossChainValidator(t *testing.T) { + + // Construct a keeper with a custom codec + // TODO: We need to ensure all custom interfaces are registered in prod, see https://github.com/cosmos/interchain-security/issues/273 + _, storeKey, paramsSubspace, ctx := testkeeper.SetupInMemKeeper(t) + ir := codectypes.NewInterfaceRegistry() + + // Public key implementation must be registered + cryptocodec.RegisterInterfaces(ir) + cdc := codec.NewProtoCodec(ir) + + consumerKeeper := consumerkeeper.NewKeeper( + cdc, + storeKey, + paramsSubspace, + capabilitykeeper.ScopedKeeper{}, + &testkeeper.MockChannelKeeper{}, + &testkeeper.MockPortKeeper{}, + &testkeeper.MockConnectionKeeper{}, + &testkeeper.MockClientKeeper{}, + &testkeeper.MockSlashingKeeper{}, + &testkeeper.MockBankKeeper{}, + &testkeeper.MockAccountKeeper{}, + &testkeeper.MockIBCTransferKeeper{}, + &testkeeper.MockIBCCoreKeeper{}, + "", + ) // should return false - _, foud := app.ConsumerKeeper.GetCCValidator(ctx, ed25519.GenPrivKey().PubKey().Address()) - suite.Require().False(foud) + _, found := consumerKeeper.GetCCValidator(ctx, ed25519.GenPrivKey().PubKey().Address()) + require.False(t, found) - // get a validator from consumer chain - val := suite.providerChain.Vals.Validators[0] + // Obtain derived private key + privKey := ed25519.GenPrivKey() - // convert validator publick key - pubkey, err := cryptocodec.FromTmPubKeyInterface(val.PubKey) - suite.Require().NoError(err) - - // set cross chain validator - ccVal, err := types.NewCCValidator(val.Address, 1000, pubkey) - suite.Require().NoError(err) + // Set cross chain validator + ccVal, err := types.NewCCValidator(privKey.PubKey().Address(), 1000, privKey.PubKey()) + require.NoError(t, err) + consumerKeeper.SetCCValidator(ctx, ccVal) - app.ConsumerKeeper.SetCCValidator(ctx, ccVal) - - // should return true - gotCCVal, found := app.ConsumerKeeper.GetCCValidator(ctx, ccVal.Address) - suite.Require().True(found) + gotCCVal, found := consumerKeeper.GetCCValidator(ctx, ccVal.Address) + require.True(t, found) // verify the returned validator values - suite.Require().EqualValues(ccVal, gotCCVal) + require.EqualValues(t, ccVal, gotCCVal) // expect to return the same consensus pubkey - pk, err := gotCCVal.ConsPubKey() - suite.Require().NoError(err) + pk, err := ccVal.ConsPubKey() + require.NoError(t, err) gotPK, err := gotCCVal.ConsPubKey() - suite.Require().NoError(err) - - suite.Require().True(pk.Equals(gotPK)) + require.NoError(t, err) + require.Equal(t, pk, gotPK) // delete validator - app.ConsumerKeeper.DeleteCCValidator(ctx, ccVal.Address) + consumerKeeper.DeleteCCValidator(ctx, ccVal.Address) // should return false - _, foud = app.ConsumerKeeper.GetCCValidator(ctx, ccVal.Address) - suite.Require().False(foud) + _, found = consumerKeeper.GetCCValidator(ctx, ccVal.Address) + require.False(t, found) } -func (suite *KeeperTestSuite) TestPendingSlashRequests() { - consumerKeeper := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper - ctx := suite.consumerChain.GetContext() +func TestPendingSlashRequests(t *testing.T) { + consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) // prepare test setup by storing 10 pending slash requests request := []types.SlashRequest{} @@ -637,10 +671,10 @@ func (suite *KeeperTestSuite) TestPendingSlashRequests() { }, } - for _, t := range testCases { - t.operation() + for _, tc := range testCases { + tc.operation() requests := consumerKeeper.GetPendingSlashRequests(ctx) - suite.Require().Len(requests, t.expLen) + require.Len(t, requests, tc.expLen) } } diff --git a/x/ccv/consumer/keeper/params_test.go b/x/ccv/consumer/keeper/params_test.go index b2df776257..6e19907e67 100644 --- a/x/ccv/consumer/keeper/params_test.go +++ b/x/ccv/consumer/keeper/params_test.go @@ -1,37 +1,37 @@ package keeper_test import ( - app "github.com/cosmos/interchain-security/app/consumer" + "testing" + + testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/x/ccv/consumer/types" + "github.com/stretchr/testify/require" ) -func (suite *KeeperTestSuite) TestParams() { - // suite setup initializes genesis - expParams := types.NewParams(true, 1000, "", "") // these are the default params +func TestParams(t *testing.T) { + consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) + consumerKeeper.SetParams(ctx, types.DefaultParams()) + + expParams := types.NewParams(false, 1000, "", "") // these are the default params, IBC suite independently sets enabled=true - params := suite.consumerChain.App.(*app.App).ConsumerKeeper.GetParams(suite.consumerChain.GetContext()) - suite.Require().Equal(expParams, params) + params := consumerKeeper.GetParams(ctx) + require.Equal(t, expParams, params) newParams := types.NewParams(false, 1000, "abc", "def") - suite.consumerChain.App.(*app.App).ConsumerKeeper.SetParams(suite.consumerChain.GetContext(), newParams) - params = suite.consumerChain.App.(*app.App).ConsumerKeeper.GetParams(suite.consumerChain.GetContext()) - suite.Require().Equal(newParams, params) - - suite.consumerChain.App.(*app.App).ConsumerKeeper. - SetBlocksPerDistributionTransmission(suite.consumerChain.GetContext(), 10) - gotBPDT := suite.consumerChain.App.(*app.App).ConsumerKeeper. - GetBlocksPerDistributionTransmission(suite.consumerChain.GetContext()) - suite.Require().Equal(gotBPDT, int64(10)) - - suite.consumerChain.App.(*app.App).ConsumerKeeper. - SetDistributionTransmissionChannel(suite.consumerChain.GetContext(), "foobarbaz") - gotChan := suite.consumerChain.App.(*app.App).ConsumerKeeper. - GetDistributionTransmissionChannel(suite.consumerChain.GetContext()) - suite.Require().Equal(gotChan, "foobarbaz") - - suite.consumerChain.App.(*app.App).ConsumerKeeper. - SetProviderFeePoolAddrStr(suite.consumerChain.GetContext(), "foobar") - gotAddr := suite.consumerChain.App.(*app.App).ConsumerKeeper. - GetProviderFeePoolAddrStr(suite.consumerChain.GetContext()) - suite.Require().Equal(gotAddr, "foobar") + consumerKeeper.SetParams(ctx, newParams) + params = consumerKeeper.GetParams(ctx) + require.Equal(t, newParams, params) + + consumerKeeper.SetBlocksPerDistributionTransmission(ctx, 10) + gotBPDT := consumerKeeper.GetBlocksPerDistributionTransmission(ctx) + require.Equal(t, gotBPDT, int64(10)) + + consumerKeeper.SetDistributionTransmissionChannel(ctx, "foobarbaz") + gotChan := consumerKeeper.GetDistributionTransmissionChannel(ctx) + require.Equal(t, gotChan, "foobarbaz") + + consumerKeeper.SetProviderFeePoolAddrStr(ctx, "foobar") + gotAddr := consumerKeeper. + GetProviderFeePoolAddrStr(ctx) + require.Equal(t, gotAddr, "foobar") } diff --git a/x/ccv/consumer/keeper/relay_test.go b/x/ccv/consumer/keeper/relay_test.go index 89af84c257..7ce4888fcf 100644 --- a/x/ccv/consumer/keeper/relay_test.go +++ b/x/ccv/consumer/keeper/relay_test.go @@ -2,32 +2,38 @@ package keeper_test import ( "sort" + "testing" "time" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v3/modules/core/24-host" appConsumer "github.com/cosmos/interchain-security/app/consumer" + testkeeper "github.com/cosmos/interchain-security/testutil/keeper" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" "github.com/cosmos/interchain-security/x/ccv/types" "github.com/cosmos/interchain-security/x/ccv/utils" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/bytes" ) -func (suite *KeeperTestSuite) TestOnRecvVSCPacket() { - // setup CCV channel - suite.SetupCCVChannel() +func TestOnRecvVSCPacket(t *testing.T) { + channelID1 := "channel1" + channelID2 := "channel2" pk1, err := cryptocodec.ToTmProtoPublicKey(ed25519.GenPrivKey().PubKey()) - suite.Require().NoError(err) + require.NoError(t, err) pk2, err := cryptocodec.ToTmProtoPublicKey(ed25519.GenPrivKey().PubKey()) - suite.Require().NoError(err) + require.NoError(t, err) pk3, err := cryptocodec.ToTmProtoPublicKey(ed25519.GenPrivKey().PubKey()) - suite.Require().NoError(err) + require.NoError(t, err) changes1 := []abci.ValidatorUpdate{ { @@ -68,11 +74,11 @@ func (suite *KeeperTestSuite) TestOnRecvVSCPacket() { packet channeltypes.Packet newChanges types.ValidatorSetChangePacketData expectedPendingChanges types.ValidatorSetChangePacketData - expErrorAck bool + noAck bool }{ { "success on first packet", - channeltypes.NewPacket(pd.GetBytes(), 1, providertypes.PortID, suite.path.EndpointB.ChannelID, consumertypes.PortID, suite.path.EndpointA.ChannelID, + channeltypes.NewPacket(pd.GetBytes(), 1, providertypes.PortID, channelID1, consumertypes.PortID, channelID2, clienttypes.NewHeight(1, 0), 0), types.ValidatorSetChangePacketData{ValidatorUpdates: changes1}, types.ValidatorSetChangePacketData{ValidatorUpdates: changes1}, @@ -80,7 +86,7 @@ func (suite *KeeperTestSuite) TestOnRecvVSCPacket() { }, { "success on subsequent packet", - channeltypes.NewPacket(pd.GetBytes(), 2, providertypes.PortID, suite.path.EndpointB.ChannelID, consumertypes.PortID, suite.path.EndpointA.ChannelID, + channeltypes.NewPacket(pd.GetBytes(), 2, providertypes.PortID, channelID1, consumertypes.PortID, channelID2, clienttypes.NewHeight(1, 0), 0), types.ValidatorSetChangePacketData{ValidatorUpdates: changes1}, types.ValidatorSetChangePacketData{ValidatorUpdates: changes1}, @@ -88,11 +94,12 @@ func (suite *KeeperTestSuite) TestOnRecvVSCPacket() { }, { "success on packet with more changes", - channeltypes.NewPacket(pd2.GetBytes(), 3, providertypes.PortID, suite.path.EndpointB.ChannelID, consumertypes.PortID, suite.path.EndpointA.ChannelID, + channeltypes.NewPacket(pd2.GetBytes(), 3, providertypes.PortID, channelID1, consumertypes.PortID, channelID2, clienttypes.NewHeight(1, 0), 0), types.ValidatorSetChangePacketData{ValidatorUpdates: changes2}, types.ValidatorSetChangePacketData{ValidatorUpdates: []abci.ValidatorUpdate{ { + // this one is not included PubKey: pk1, Power: 30, }, @@ -109,7 +116,7 @@ func (suite *KeeperTestSuite) TestOnRecvVSCPacket() { }, { "invalid packet: different destination channel than provider channel", - channeltypes.NewPacket(pd.GetBytes(), 1, providertypes.PortID, suite.path.EndpointB.ChannelID, consumertypes.PortID, "InvalidChannel", + channeltypes.NewPacket(pd.GetBytes(), 1, providertypes.PortID, channelID1, consumertypes.PortID, "InvalidChannel", clienttypes.NewHeight(1, 0), 0), types.ValidatorSetChangePacketData{ValidatorUpdates: []abci.ValidatorUpdate{}}, types.ValidatorSetChangePacketData{ValidatorUpdates: []abci.ValidatorUpdate{}}, @@ -117,22 +124,65 @@ func (suite *KeeperTestSuite) TestOnRecvVSCPacket() { }, } + // Instantiate custom keeper with mocks + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cdc, storeKey, paramsSubspace, ctx := testkeeper.SetupInMemKeeper(t) + + mockScopedKeeper := testkeeper.NewMockScopedKeeper(ctrl) + mockChannelKeeper := testkeeper.NewMockChannelKeeper(ctrl) + + // Setup expected mock calls for final test case + + dummyCap := &capabilitytypes.Capability{} + gomock.InOrder( + + mockScopedKeeper.EXPECT().GetCapability( + ctx, host.ChannelCapabilityPath(consumertypes.PortID, "InvalidChannel"), + ).Return(dummyCap, true).Times(1), + + mockChannelKeeper.EXPECT().ChanCloseInit( + ctx, consumertypes.PortID, "InvalidChannel", dummyCap, + ).Return(nil).Times(1), + ) + + consumerKeeper := testkeeper.GetConsumerKeeperWithMocks(t, + cdc, + storeKey, + paramsSubspace, + mockScopedKeeper, + mockChannelKeeper, + testkeeper.NewMockPortKeeper(ctrl), + testkeeper.NewMockConnectionKeeper(ctrl), + testkeeper.NewMockClientKeeper(ctrl), + testkeeper.NewMockSlashingKeeper(ctrl), + testkeeper.NewMockBankKeeper(ctrl), + testkeeper.NewMockAccountKeeper(ctrl), + testkeeper.NewMockIBCTransferKeeper(ctrl), + testkeeper.NewMockIBCCoreKeeper(ctrl), + ) + + consumerKeeper.SetProviderChannel(ctx, channelID2) + consumerKeeper.SetUnbondingTime(ctx, 100*time.Hour) + for _, tc := range testCases { - ack := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.OnRecvVSCPacket(suite.ctx, tc.packet, tc.newChanges) - suite.Require().NotNil(ack, "invalid test case: %s did not return ack", tc.name) + ack := consumerKeeper.OnRecvVSCPacket(ctx, tc.packet, tc.newChanges) - if tc.expErrorAck { - suite.Require().False(ack.Success(), "invalid test case: %s did not return an Error Acknowledgment", tc.name) + if tc.noAck { + // if closing channel was successful, no acknowledgement returned, see OnRecvPacketOnUnknownChannel + // TODO: Confirm this functionality + require.Nil(t, ack, "invalid test case: %s ack returned ", tc.name) } else { - suite.Require().True(ack.Success(), "invalid test case: %s did not return a Success Acknowledgment", tc.name) - providerChannel, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderChannel(suite.ctx) - suite.Require().True(ok) - suite.Require().Equal(tc.packet.DestinationChannel, providerChannel, + require.NotNil(t, ack, "invalid test case: %s did not return ack", tc.name) + require.True(t, ack.Success(), "invalid test case: %s did not return a Success Acknowledgment", tc.name) + providerChannel, ok := consumerKeeper.GetProviderChannel(ctx) + require.True(t, ok) + require.Equal(t, tc.packet.DestinationChannel, providerChannel, "provider channel is not destination channel on successful receive for valid test case: %s", tc.name) // Check that pending changes are accumulated and stored correctly - actualPendingChanges, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPendingChanges(suite.ctx) - suite.Require().True(ok) + actualPendingChanges, ok := consumerKeeper.GetPendingChanges(ctx) + require.True(t, ok) // Sort to avoid dumb inequalities sort.SliceStable(actualPendingChanges.ValidatorUpdates, func(i, j int) bool { return actualPendingChanges.ValidatorUpdates[i].PubKey.Compare(actualPendingChanges.ValidatorUpdates[j].PubKey) == -1 @@ -140,17 +190,18 @@ func (suite *KeeperTestSuite) TestOnRecvVSCPacket() { sort.SliceStable(tc.expectedPendingChanges.ValidatorUpdates, func(i, j int) bool { return tc.expectedPendingChanges.ValidatorUpdates[i].PubKey.Compare(tc.expectedPendingChanges.ValidatorUpdates[j].PubKey) == -1 }) - suite.Require().Equal(tc.expectedPendingChanges, *actualPendingChanges, "pending changes not equal to expected changes after successful packet receive. case: %s", tc.name) + require.Equal(t, tc.expectedPendingChanges, *actualPendingChanges, "pending changes not equal to expected changes after successful packet receive. case: %s", tc.name) - unbondingPeriod, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(suite.ctx) - suite.Require().True(found) - expectedTime := uint64(suite.ctx.BlockTime().Add(unbondingPeriod).UnixNano()) - maturityTime := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.ctx, tc.newChanges.ValsetUpdateId) - suite.Require().Equal(expectedTime, maturityTime, "packet maturity time has unexpected value for case: %s", tc.name) + unbondingPeriod, found := consumerKeeper.GetUnbondingTime(ctx) + require.True(t, found) + expectedTime := uint64(ctx.BlockTime().Add(unbondingPeriod).UnixNano()) + maturityTime := consumerKeeper.GetPacketMaturityTime(ctx, tc.newChanges.ValsetUpdateId) + require.Equal(t, expectedTime, maturityTime, "packet maturity time has unexpected value for case: %s", tc.name) } } } +// TODO: maybe a unit test func (suite *KeeperTestSuite) TestUnbondMaturePackets() { // setup CCV channel suite.SetupCCVChannel() @@ -263,6 +314,7 @@ func incrementTimeBy(s *KeeperTestSuite, jumpPeriod time.Duration) { } } +// TODO: This is a unit test func (suite *KeeperTestSuite) TestOnAcknowledgement() { packetData := types.NewSlashPacketData( abci.Validator{Address: bytes.HexBytes{}, Power: int64(1)}, uint64(1), stakingtypes.Downtime, diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index 6485ccb12d..25c0a4d85e 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -9,7 +9,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" @@ -33,7 +32,7 @@ type Keeper struct { storeKey sdk.StoreKey cdc codec.BinaryCodec paramSpace paramtypes.Subspace - scopedKeeper capabilitykeeper.ScopedKeeper + scopedKeeper ccv.ScopedKeeper channelKeeper ccv.ChannelKeeper portKeeper ccv.PortKeeper connectionKeeper ccv.ConnectionKeeper @@ -46,7 +45,7 @@ type Keeper struct { // NewKeeper creates a new provider Keeper instance func NewKeeper( - cdc codec.BinaryCodec, key sdk.StoreKey, paramSpace paramtypes.Subspace, scopedKeeper capabilitykeeper.ScopedKeeper, + cdc codec.BinaryCodec, key sdk.StoreKey, paramSpace paramtypes.Subspace, scopedKeeper ccv.ScopedKeeper, channelKeeper ccv.ChannelKeeper, portKeeper ccv.PortKeeper, connectionKeeper ccv.ConnectionKeeper, clientKeeper ccv.ClientKeeper, stakingKeeper ccv.StakingKeeper, slashingKeeper ccv.SlashingKeeper, diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 45aac7d579..c229554f77 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -340,38 +340,44 @@ func TestHandleSlashPacketDoubleSigning(t *testing.T) { stakingtypes.DoubleSign, ) - // Setup expected mock calls mockStakingKeeper := testkeeper.NewMockStakingKeeper(ctrl) - mockStakingKeeper.EXPECT().Slash( - ctx, - sdk.ConsAddress(slashPacket.Validator.Address), - infractionHeight, - int64(0), // power - sdk.NewDec(1), // Slash fraction - stakingtypes.DoubleSign).Return().Times(1) - - mockStakingKeeper.EXPECT().Jail( - gomock.Eq(ctx), - gomock.Eq(sdk.ConsAddress(slashPacket.Validator.Address)), - ).Return() - - mockStakingKeeper.EXPECT().GetValidatorByConsAddr( - ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Return( - stakingtypes.Validator{Status: stakingtypes.Bonded}, true, - ).Times(1) - mockSlashingKeeper := testkeeper.NewMockSlashingKeeper(ctrl) - mockSlashingKeeper.EXPECT().SlashFractionDoubleSign(ctx).Return(sdk.NewDec(1)).Times(1) - mockSlashingKeeper.EXPECT().JailUntil(ctx, sdk.ConsAddress(slashPacket.Validator.Address), - evidencetypes.DoubleSignJailEndTime).Times(1) - mockSlashingKeeper.EXPECT().IsTombstoned(ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Return(false).Times(1) - mockSlashingKeeper.EXPECT().Tombstone(ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Times(1) + + // Setup expected mock calls + gomock.InOrder( + + mockStakingKeeper.EXPECT().GetValidatorByConsAddr( + ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Return( + stakingtypes.Validator{Status: stakingtypes.Bonded}, true, + ).Times(1), + + mockSlashingKeeper.EXPECT().IsTombstoned(ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Return(false).Times(1), + + mockSlashingKeeper.EXPECT().SlashFractionDoubleSign(ctx).Return(sdk.NewDec(1)).Times(1), + + mockSlashingKeeper.EXPECT().Tombstone(ctx, sdk.ConsAddress(slashPacket.Validator.Address)).Times(1), + + mockStakingKeeper.EXPECT().Slash( + ctx, + sdk.ConsAddress(slashPacket.Validator.Address), + infractionHeight, + int64(0), // power + sdk.NewDec(1), // Slash fraction + stakingtypes.DoubleSign).Return().Times(1), + + mockStakingKeeper.EXPECT().Jail( + gomock.Eq(ctx), + gomock.Eq(sdk.ConsAddress(slashPacket.Validator.Address)), + ).Return(), + + mockSlashingKeeper.EXPECT().JailUntil(ctx, sdk.ConsAddress(slashPacket.Validator.Address), + evidencetypes.DoubleSignJailEndTime).Times(1), + ) providerKeeper := testkeeper.GetProviderKeeperWithMocks(t, cdc, storeKey, paramsSubspace, - ctx, capabilitykeeper.ScopedKeeper{}, testkeeper.NewMockChannelKeeper(ctrl), testkeeper.NewMockPortKeeper(ctrl), diff --git a/x/ccv/provider/keeper/params_test.go b/x/ccv/provider/keeper/params_test.go index cd5b84bf97..3350c1fa7a 100644 --- a/x/ccv/provider/keeper/params_test.go +++ b/x/ccv/provider/keeper/params_test.go @@ -32,7 +32,6 @@ func TestParams(t *testing.T) { cdc, storeKey, paramsSubspace, - ctx, capabilitykeeper.ScopedKeeper{}, &testkeeper.MockChannelKeeper{}, &testkeeper.MockPortKeeper{}, diff --git a/x/ccv/types/expected_keepers.go b/x/ccv/types/expected_keepers.go index 15e4adab22..e792fd2c7d 100644 --- a/x/ccv/types/expected_keepers.go +++ b/x/ccv/types/expected_keepers.go @@ -6,10 +6,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" auth "github.com/cosmos/cosmos-sdk/x/auth/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" conntypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" @@ -115,3 +114,9 @@ type IBCCoreKeeper interface { msg *channeltypes.MsgChannelOpenInit, ) (*channeltypes.MsgChannelOpenInitResponse, error) } + +type ScopedKeeper interface { + GetCapability(ctx sdk.Context, name string) (*capabilitytypes.Capability, bool) + AuthenticateCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) bool + ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) error +} diff --git a/x/ccv/utils/utils.go b/x/ccv/utils/utils.go index ac248d9357..60b02437c6 100644 --- a/x/ccv/utils/utils.go +++ b/x/ccv/utils/utils.go @@ -7,7 +7,6 @@ import ( cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" "github.com/cosmos/ibc-go/modules/core/exported" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" @@ -52,7 +51,7 @@ func GetChangePubKeyAddress(change abci.ValidatorUpdate) (addr []byte) { // over the source channelID and portID func SendIBCPacket( ctx sdk.Context, - scopedKeeper capabilitykeeper.ScopedKeeper, + scopedKeeper ccv.ScopedKeeper, channelKeeper ccv.ChannelKeeper, channelID string, portID string, @@ -88,7 +87,7 @@ func SendIBCPacket( // not on an established CCV channel func OnRecvPacketOnUnknownChannel( ctx sdk.Context, - scopedKeeper capabilitykeeper.ScopedKeeper, + scopedKeeper ccv.ScopedKeeper, channelKeeper ccv.ChannelKeeper, packet channeltypes.Packet, ) exported.Acknowledgement { From 173521775624fbb96ee5395667a27fdc059fe4d0 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Wed, 17 Aug 2022 19:59:33 -0700 Subject: [PATCH 13/24] relay test --- x/ccv/consumer/keeper/keeper.go | 2 +- x/ccv/consumer/keeper/relay.go | 3 +- x/ccv/consumer/keeper/relay_test.go | 92 +++++++++++++++++++++++++---- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/x/ccv/consumer/keeper/keeper.go b/x/ccv/consumer/keeper/keeper.go index 1cdadcc2c0..3614769880 100644 --- a/x/ccv/consumer/keeper/keeper.go +++ b/x/ccv/consumer/keeper/keeper.go @@ -93,7 +93,7 @@ func (k *Keeper) SetHooks(sh ccv.ConsumerHooks) *Keeper { } // ChanCloseInit defines a wrapper function for the channel Keeper's function -// in order to expose it to the ICS20 transfer handler. +// Following ICS 004: https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics#closing-handshake func (k Keeper) ChanCloseInit(ctx sdk.Context, portID, channelID string) error { capName := host.ChannelCapabilityPath(portID, channelID) chanCap, ok := k.scopedKeeper.GetCapability(ctx, capName) diff --git a/x/ccv/consumer/keeper/relay.go b/x/ccv/consumer/keeper/relay.go index e1d0e6e5a4..6bf691bffd 100644 --- a/x/ccv/consumer/keeper/relay.go +++ b/x/ccv/consumer/keeper/relay.go @@ -208,11 +208,12 @@ func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Pac "channel", packet.SourceChannel, "error", err, ) + // Initiate ChanCloseInit using packet source (non-counterparty) port and channel err := k.ChanCloseInit(ctx, packet.SourcePort, packet.SourceChannel) if err != nil { return fmt.Errorf("ChanCloseInit(%s) failed: %s", packet.SourceChannel, err.Error()) } - // check if there is an established CCV channel + // check if there is an established CCV channel to provider channelID, found := k.GetProviderChannel(ctx) if !found { return sdkerrors.Wrapf(types.ErrNoProposerChannelId, "recv ErrorAcknowledgement on non-established channel %s", packet.SourceChannel) diff --git a/x/ccv/consumer/keeper/relay_test.go b/x/ccv/consumer/keeper/relay_test.go index 7ce4888fcf..e366502fc6 100644 --- a/x/ccv/consumer/keeper/relay_test.go +++ b/x/ccv/consumer/keeper/relay_test.go @@ -201,7 +201,6 @@ func TestOnRecvVSCPacket(t *testing.T) { } } -// TODO: maybe a unit test func (suite *KeeperTestSuite) TestUnbondMaturePackets() { // setup CCV channel suite.SetupCCVChannel() @@ -314,23 +313,92 @@ func incrementTimeBy(s *KeeperTestSuite, jumpPeriod time.Duration) { } } -// TODO: This is a unit test -func (suite *KeeperTestSuite) TestOnAcknowledgement() { +func TestOnAcknowledgement(t *testing.T) { + + // Channel ID to some dest chain that's not the established provider + channelIDToDestChain := "channelIDToDestChain" + + // Channel ID to established provider + channelIDToProvider := "channelIDToProvider" + + // Channel ID on destination (counter party) chain + channelIDOnDest := "ChannelIDOnDest" + + // Instantiate custom keeper with mocks + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cdc, storeKey, paramsSubspace, ctx := testkeeper.SetupInMemKeeper(t) + + mockScopedKeeper := testkeeper.NewMockScopedKeeper(ctrl) + mockChannelKeeper := testkeeper.NewMockChannelKeeper(ctrl) + + consumerKeeper := testkeeper.GetConsumerKeeperWithMocks(t, + cdc, + storeKey, + paramsSubspace, + mockScopedKeeper, + mockChannelKeeper, + testkeeper.NewMockPortKeeper(ctrl), + testkeeper.NewMockConnectionKeeper(ctrl), + testkeeper.NewMockClientKeeper(ctrl), + testkeeper.NewMockSlashingKeeper(ctrl), + testkeeper.NewMockBankKeeper(ctrl), + testkeeper.NewMockAccountKeeper(ctrl), + testkeeper.NewMockIBCTransferKeeper(ctrl), + testkeeper.NewMockIBCCoreKeeper(ctrl), + ) + + // Set an established provider channel for later in test + consumerKeeper.SetProviderChannel(ctx, channelIDToProvider) + packetData := types.NewSlashPacketData( abci.Validator{Address: bytes.HexBytes{}, Power: int64(1)}, uint64(1), stakingtypes.Downtime, ) - packet := channeltypes.NewPacket(packetData.GetBytes(), 1, providertypes.PortID, suite.path.EndpointB.ChannelID, - consumertypes.PortID, suite.path.EndpointA.ChannelID, clienttypes.Height{}, uint64(time.Now().Add(60*time.Second).UnixNano())) + // According to ICS 004: (https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics#processing-acknowledgements), + // acknowledgedPacket is in reference to a packet originally sent from this (consumer) module. + // TODO: Do we want to test weird edge cases like processing an ack where source port ID != consumer port ID? + packet := channeltypes.NewPacket( + packetData.GetBytes(), + 1, + consumertypes.PortID, // Source port + channelIDToDestChain, // Source channel + providertypes.PortID, // Dest (counter party) port + channelIDOnDest, // Dest (counter party) channel + clienttypes.Height{}, + uint64(time.Now().Add(60*time.Second).UnixNano()), + ) + ack := channeltypes.NewResultAcknowledgement([]byte{1}) - // expect no error - err := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.OnAcknowledgementPacket(suite.ctx, packet, ack) - suite.Nil(err) + // expect no error returned from OnAcknowledgementPacket, no input error with ack + err := consumerKeeper.OnAcknowledgementPacket(ctx, packet, ack) + require.Nil(t, err) - // expect an error - ack = channeltypes.NewErrorAcknowledgement("error") + // Still expect no error returned from OnAcknowledgementPacket, + // but the input error ack will be handled with appropriate ChanCloseInit calls + dummyCap := &capabilitytypes.Capability{} + gomock.InOrder( - err = suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.OnAcknowledgementPacket(suite.ctx, packet, ack) - suite.NotNil(err) + mockScopedKeeper.EXPECT().GetCapability( + ctx, host.ChannelCapabilityPath(consumertypes.PortID, channelIDToDestChain), + ).Return(dummyCap, true).Times(1), + // Due to input error ack, ChanCloseInit is called on channel to destination chain + mockChannelKeeper.EXPECT().ChanCloseInit( + ctx, consumertypes.PortID, channelIDToDestChain, dummyCap, + ).Return(nil).Times(1), + + mockScopedKeeper.EXPECT().GetCapability( + ctx, host.ChannelCapabilityPath(consumertypes.PortID, channelIDToProvider), + ).Return(dummyCap, true).Times(1), + // Due to input error ack and existence of established channel to provider, + // ChanCloseInit is called on channel to provider + mockChannelKeeper.EXPECT().ChanCloseInit( + ctx, consumertypes.PortID, channelIDToProvider, dummyCap, + ).Return(nil).Times(1), + ) + + ack = channeltypes.NewErrorAcknowledgement("error") + err = consumerKeeper.OnAcknowledgementPacket(ctx, packet, ack) + require.Nil(t, err) } From 64053215c210220db7d2d52a86ce9eb5e885c686 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Wed, 17 Aug 2022 20:01:17 -0700 Subject: [PATCH 14/24] lol --- x/ccv/consumer/keeper/relay_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ccv/consumer/keeper/relay_test.go b/x/ccv/consumer/keeper/relay_test.go index e366502fc6..7da7511589 100644 --- a/x/ccv/consumer/keeper/relay_test.go +++ b/x/ccv/consumer/keeper/relay_test.go @@ -356,7 +356,7 @@ func TestOnAcknowledgement(t *testing.T) { ) // According to ICS 004: (https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics#processing-acknowledgements), - // acknowledgedPacket is in reference to a packet originally sent from this (consumer) module. + // acknowledgePacket is in reference to a packet originally sent from this (consumer) module. // TODO: Do we want to test weird edge cases like processing an ack where source port ID != consumer port ID? packet := channeltypes.NewPacket( packetData.GetBytes(), From 6e242d1f780a537422f9d12aba1503fa25b3937c Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Wed, 17 Aug 2022 20:20:51 -0700 Subject: [PATCH 15/24] comments --- x/ccv/consumer/keeper/relay.go | 4 +++- x/ccv/consumer/keeper/relay_test.go | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/x/ccv/consumer/keeper/relay.go b/x/ccv/consumer/keeper/relay.go index 6bf691bffd..cf2c0b75c3 100644 --- a/x/ccv/consumer/keeper/relay.go +++ b/x/ccv/consumer/keeper/relay.go @@ -195,7 +195,9 @@ func (k Keeper) SendPendingSlashRequests(ctx sdk.Context) { k.ClearPendingSlashRequests(ctx) } -// OnAcknowledgementPacket handles acknowledgments for sent VSCMatured and Slash packets +// OnAcknowledgementPacket executes application logic for acknowledgments of sent VSCMatured and Slash packets +// in conjunction with the ibc keeper's execution of "acknowledgePacket", +// according to https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics#processing-acknowledgements func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, ack channeltypes.Acknowledgement) error { if err := ack.GetError(); err != "" { // Reasons for ErrorAcknowledgment diff --git a/x/ccv/consumer/keeper/relay_test.go b/x/ccv/consumer/keeper/relay_test.go index 7da7511589..a752332b06 100644 --- a/x/ccv/consumer/keeper/relay_test.go +++ b/x/ccv/consumer/keeper/relay_test.go @@ -313,7 +313,10 @@ func incrementTimeBy(s *KeeperTestSuite, jumpPeriod time.Duration) { } } -func TestOnAcknowledgement(t *testing.T) { +// TestOnAcknowledgementPacket tests application logic for acknowledgments of sent VSCMatured and Slash packets +// in conjunction with the ibc keeper's execution of "acknowledgePacket", +// according to https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics#processing-acknowledgements +func TestOnAcknowledgementPacket(t *testing.T) { // Channel ID to some dest chain that's not the established provider channelIDToDestChain := "channelIDToDestChain" @@ -355,9 +358,8 @@ func TestOnAcknowledgement(t *testing.T) { abci.Validator{Address: bytes.HexBytes{}, Power: int64(1)}, uint64(1), stakingtypes.Downtime, ) - // According to ICS 004: (https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics#processing-acknowledgements), - // acknowledgePacket is in reference to a packet originally sent from this (consumer) module. - // TODO: Do we want to test weird edge cases like processing an ack where source port ID != consumer port ID? + // AcknowledgePacket is in reference to a packet originally sent from this (consumer) module. + // TODO: Do we want to test weird edge cases like processing an ack where source portID != consumer portID? packet := channeltypes.NewPacket( packetData.GetBytes(), 1, From f39346b915518080a9b34325ef78aa7df0019fe0 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Wed, 17 Aug 2022 20:46:34 -0700 Subject: [PATCH 16/24] cleans --- x/ccv/consumer/keeper/keeper_test.go | 3 +-- x/ccv/consumer/keeper/relay.go | 2 +- x/ccv/consumer/keeper/relay_test.go | 17 +++++++++-------- x/ccv/provider/keeper/proposal.go | 25 +++++++------------------ x/ccv/provider/keeper/proposal_test.go | 16 ++++++++++------ 5 files changed, 28 insertions(+), 35 deletions(-) diff --git a/x/ccv/consumer/keeper/keeper_test.go b/x/ccv/consumer/keeper/keeper_test.go index 54d8dcae97..91d3b9891c 100644 --- a/x/ccv/consumer/keeper/keeper_test.go +++ b/x/ccv/consumer/keeper/keeper_test.go @@ -10,7 +10,6 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" sdk "github.com/cosmos/cosmos-sdk/types" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -599,7 +598,7 @@ func TestCrossChainValidator(t *testing.T) { cdc, storeKey, paramsSubspace, - capabilitykeeper.ScopedKeeper{}, + &testkeeper.MockScopedKeeper{}, &testkeeper.MockChannelKeeper{}, &testkeeper.MockPortKeeper{}, &testkeeper.MockConnectionKeeper{}, diff --git a/x/ccv/consumer/keeper/relay.go b/x/ccv/consumer/keeper/relay.go index cf2c0b75c3..4a6adffe2b 100644 --- a/x/ccv/consumer/keeper/relay.go +++ b/x/ccv/consumer/keeper/relay.go @@ -196,7 +196,7 @@ func (k Keeper) SendPendingSlashRequests(ctx sdk.Context) { } // OnAcknowledgementPacket executes application logic for acknowledgments of sent VSCMatured and Slash packets -// in conjunction with the ibc keeper's execution of "acknowledgePacket", +// in conjunction with the ibc module's execution of "acknowledgePacket", // according to https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics#processing-acknowledgements func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, ack channeltypes.Acknowledgement) error { if err := ack.GetError(); err != "" { diff --git a/x/ccv/consumer/keeper/relay_test.go b/x/ccv/consumer/keeper/relay_test.go index a752332b06..9dfe29b2e6 100644 --- a/x/ccv/consumer/keeper/relay_test.go +++ b/x/ccv/consumer/keeper/relay_test.go @@ -25,8 +25,8 @@ import ( ) func TestOnRecvVSCPacket(t *testing.T) { - channelID1 := "channel1" - channelID2 := "channel2" + consumerCCVChannelID := "consumerCCVChannelID" + providerCCVChannelID := "providerCCVChannelID" pk1, err := cryptocodec.ToTmProtoPublicKey(ed25519.GenPrivKey().PubKey()) require.NoError(t, err) @@ -78,7 +78,7 @@ func TestOnRecvVSCPacket(t *testing.T) { }{ { "success on first packet", - channeltypes.NewPacket(pd.GetBytes(), 1, providertypes.PortID, channelID1, consumertypes.PortID, channelID2, + channeltypes.NewPacket(pd.GetBytes(), 1, providertypes.PortID, providerCCVChannelID, consumertypes.PortID, consumerCCVChannelID, clienttypes.NewHeight(1, 0), 0), types.ValidatorSetChangePacketData{ValidatorUpdates: changes1}, types.ValidatorSetChangePacketData{ValidatorUpdates: changes1}, @@ -86,7 +86,7 @@ func TestOnRecvVSCPacket(t *testing.T) { }, { "success on subsequent packet", - channeltypes.NewPacket(pd.GetBytes(), 2, providertypes.PortID, channelID1, consumertypes.PortID, channelID2, + channeltypes.NewPacket(pd.GetBytes(), 2, providertypes.PortID, providerCCVChannelID, consumertypes.PortID, consumerCCVChannelID, clienttypes.NewHeight(1, 0), 0), types.ValidatorSetChangePacketData{ValidatorUpdates: changes1}, types.ValidatorSetChangePacketData{ValidatorUpdates: changes1}, @@ -94,7 +94,7 @@ func TestOnRecvVSCPacket(t *testing.T) { }, { "success on packet with more changes", - channeltypes.NewPacket(pd2.GetBytes(), 3, providertypes.PortID, channelID1, consumertypes.PortID, channelID2, + channeltypes.NewPacket(pd2.GetBytes(), 3, providertypes.PortID, providerCCVChannelID, consumertypes.PortID, consumerCCVChannelID, clienttypes.NewHeight(1, 0), 0), types.ValidatorSetChangePacketData{ValidatorUpdates: changes2}, types.ValidatorSetChangePacketData{ValidatorUpdates: []abci.ValidatorUpdate{ @@ -116,7 +116,7 @@ func TestOnRecvVSCPacket(t *testing.T) { }, { "invalid packet: different destination channel than provider channel", - channeltypes.NewPacket(pd.GetBytes(), 1, providertypes.PortID, channelID1, consumertypes.PortID, "InvalidChannel", + channeltypes.NewPacket(pd.GetBytes(), 1, providertypes.PortID, providerCCVChannelID, consumertypes.PortID, "InvalidChannel", clienttypes.NewHeight(1, 0), 0), types.ValidatorSetChangePacketData{ValidatorUpdates: []abci.ValidatorUpdate{}}, types.ValidatorSetChangePacketData{ValidatorUpdates: []abci.ValidatorUpdate{}}, @@ -162,7 +162,8 @@ func TestOnRecvVSCPacket(t *testing.T) { testkeeper.NewMockIBCCoreKeeper(ctrl), ) - consumerKeeper.SetProviderChannel(ctx, channelID2) + // Set channel to provider, still in context of consumer chain + consumerKeeper.SetProviderChannel(ctx, consumerCCVChannelID) consumerKeeper.SetUnbondingTime(ctx, 100*time.Hour) for _, tc := range testCases { @@ -314,7 +315,7 @@ func incrementTimeBy(s *KeeperTestSuite, jumpPeriod time.Duration) { } // TestOnAcknowledgementPacket tests application logic for acknowledgments of sent VSCMatured and Slash packets -// in conjunction with the ibc keeper's execution of "acknowledgePacket", +// in conjunction with the ibc module's execution of "acknowledgePacket", // according to https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics#processing-acknowledgements func TestOnAcknowledgementPacket(t *testing.T) { diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go index e5de585cc7..642722bbf3 100644 --- a/x/ccv/provider/keeper/proposal.go +++ b/x/ccv/provider/keeper/proposal.go @@ -239,9 +239,6 @@ func (k Keeper) GetPendingCreateProposal(ctx sdk.Context, spawnTime time.Time, c } var clientInfo types.CreateConsumerChainProposal k.cdc.MustUnmarshal(bz, &clientInfo) - // Populate info that's only stored in key, not store value - clientInfo.SpawnTime = spawnTime - clientInfo.ChainId = chainID return clientInfo } @@ -262,11 +259,12 @@ func (k Keeper) IteratePendingCreateProposal(ctx sdk.Context) { panic(fmt.Errorf("consumer client could not be created: %w", err)) } } + // delete the executed proposals + k.DeletePendingCreateProposal(ctx, propsToExecute...) } // CreateProposalsToExecute iterates over the pending proposals and returns an ordered list of proposals to be executed, -// ie. consumer clients to be created. A prop is included in the returned list (and is deleted from store) if its proposed -// spawn time has passed. +// ie. consumer clients to be created. A prop is included in the returned list if its proposed spawn time has passed. // // Note: this method is split out from IteratePendingCreateProposal to be easily unit tested. func (k Keeper) CreateProposalsToExecute(ctx sdk.Context) []types.CreateConsumerChainProposal { @@ -283,16 +281,13 @@ func (k Keeper) CreateProposalsToExecute(ctx sdk.Context) []types.CreateConsumer for ; iterator.Valid(); iterator.Next() { key := iterator.Key() - spawnTime, chainID, err := types.ParsePendingCreateProposalKey(key) + spawnTime, _, err := types.ParsePendingCreateProposalKey(key) if err != nil { panic(fmt.Errorf("failed to parse pending client key: %w", err)) } var prop types.CreateConsumerChainProposal k.cdc.MustUnmarshal(iterator.Value(), &prop) - // Populate info that's only stored in key, not store value - prop.ChainId = chainID - prop.SpawnTime = spawnTime if !ctx.BlockTime().Before(spawnTime) { propsToExecute = append(propsToExecute, prop) @@ -301,9 +296,6 @@ func (k Keeper) CreateProposalsToExecute(ctx sdk.Context) []types.CreateConsumer break } } - - // delete the proposals to be executed - k.DeletePendingCreateProposal(ctx, propsToExecute...) return propsToExecute } @@ -355,11 +347,12 @@ func (k Keeper) IteratePendingStopProposal(ctx sdk.Context) { panic(fmt.Errorf("consumer chain failed to stop: %w", err)) } } + // delete the executed proposals + k.DeletePendingStopProposals(ctx, propsToExecute...) } // StopProposalsToExecute iterates over the pending stop proposals and returns an ordered list of stop proposals to be executed, -// ie. consumer chains to stop. A prop is included in the returned list (and is deleted from store) if its proposed -// stop time has passed. +// ie. consumer chains to stop. A prop is included in the returned list if its proposed stop time has passed. // // Note: this method is split out from IteratePendingCreateProposal to be easily unit tested. func (k Keeper) StopProposalsToExecute(ctx sdk.Context) []types.StopConsumerChainProposal { @@ -390,10 +383,6 @@ func (k Keeper) StopProposalsToExecute(ctx sdk.Context) []types.StopConsumerChai break } } - - // delete the proposals to be executed - k.DeletePendingStopProposals(ctx, propsToExecute...) - return propsToExecute } diff --git a/x/ccv/provider/keeper/proposal_test.go b/x/ccv/provider/keeper/proposal_test.go index 479265c03a..c66ceda54e 100644 --- a/x/ccv/provider/keeper/proposal_test.go +++ b/x/ccv/provider/keeper/proposal_test.go @@ -143,7 +143,9 @@ func TestPendingStopProposalDeletion(t *testing.T) { ctx = ctx.WithBlockTime(time.Now().UTC()) propsToExecute := providerKeeper.StopProposalsToExecute(ctx) - numExecuted := 0 + // Delete stop proposals, same as what would be done by IteratePendingStopProposal + providerKeeper.DeletePendingStopProposals(ctx, propsToExecute...) + numDeleted := 0 for _, tc := range testCases { res := providerKeeper.GetPendingStopProposal(ctx, tc.ChainId, tc.StopTime) if !tc.ExpDeleted { @@ -151,8 +153,8 @@ func TestPendingStopProposalDeletion(t *testing.T) { continue } require.Empty(t, res, "stop proposal was not deleted %s %s", tc.ChainId, tc.StopTime.String()) - require.Equal(t, propsToExecute[numExecuted].ChainId, tc.ChainId) - numExecuted += 1 + require.Equal(t, propsToExecute[numDeleted].ChainId, tc.ChainId) + numDeleted += 1 } } @@ -239,7 +241,9 @@ func TestPendingCreateProposalsDeletion(t *testing.T) { ctx = ctx.WithBlockTime(time.Now().UTC()) propsToExecute := providerKeeper.CreateProposalsToExecute(ctx) - numExecuted := 0 + // Delete create proposals, same as what would be done by IteratePendingCreateProposal + providerKeeper.DeletePendingCreateProposal(ctx, propsToExecute...) + numDeleted := 0 for _, tc := range testCases { res := providerKeeper.GetPendingCreateProposal(ctx, tc.SpawnTime, tc.ChainId) if !tc.ExpDeleted { @@ -247,8 +251,8 @@ func TestPendingCreateProposalsDeletion(t *testing.T) { continue } require.Empty(t, res, "create proposal was not deleted %s %s", tc.ChainId, tc.SpawnTime.String()) - require.Equal(t, propsToExecute[numExecuted].ChainId, tc.ChainId) - numExecuted += 1 + require.Equal(t, propsToExecute[numDeleted].ChainId, tc.ChainId) + numDeleted += 1 } } From d8f03a586b57f099769a26f6bb27ec5e2886dbcc Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Wed, 17 Aug 2022 20:52:19 -0700 Subject: [PATCH 17/24] smalls --- testutil/keeper/unit_test_helpers.go | 4 ---- x/ccv/consumer/keeper/relay_test.go | 1 - 2 files changed, 5 deletions(-) diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go index de682f04ba..06aaee3dea 100644 --- a/testutil/keeper/unit_test_helpers.go +++ b/testutil/keeper/unit_test_helpers.go @@ -67,8 +67,6 @@ func GetConsumerKeeperAndCtx(t testing.TB) (consumerkeeper.Keeper, sdk.Context) // Constructs a provider keeper for unit tests, backed by an in-memory db, // with ability to pass mocked or otherwise manipulated parameters. -// Note: Use the dummy types defined in this file for keepers you don't wish to mock, -// and SetupInMemKeeper() for other parameters you don't wish to manipulate. func GetProviderKeeperWithMocks(t testing.TB, cdc *codec.ProtoCodec, storeKey *storetypes.KVStoreKey, @@ -102,8 +100,6 @@ func GetProviderKeeperWithMocks(t testing.TB, // Constructs a consumer keeper for unit tests, backed by an in-memory db, // with ability to pass mocked or otherwise manipulated parameters. -// Note: Use the dummy types defined in this file for keepers you don't wish to mock, -// and SetupInMemKeeper() for other parameters you don't wish to manipulate. func GetConsumerKeeperWithMocks(t testing.TB, cdc *codec.ProtoCodec, storeKey *storetypes.KVStoreKey, diff --git a/x/ccv/consumer/keeper/relay_test.go b/x/ccv/consumer/keeper/relay_test.go index 9dfe29b2e6..94b096ea9b 100644 --- a/x/ccv/consumer/keeper/relay_test.go +++ b/x/ccv/consumer/keeper/relay_test.go @@ -99,7 +99,6 @@ func TestOnRecvVSCPacket(t *testing.T) { types.ValidatorSetChangePacketData{ValidatorUpdates: changes2}, types.ValidatorSetChangePacketData{ValidatorUpdates: []abci.ValidatorUpdate{ { - // this one is not included PubKey: pk1, Power: 30, }, From df6edcdc4f18ca8b4726f49cbcbf7bbf1c36f75a Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Thu, 18 Aug 2022 10:58:05 -0700 Subject: [PATCH 18/24] progress save --- testutil/keeper/unit_test_helpers.go | 51 +++++++++++++++-- x/ccv/consumer/keeper/keeper_test.go | 14 +---- x/ccv/consumer/keeper/relay_test.go | 4 +- x/ccv/consumer/keeper/validators_test.go | 73 ++++++++++++++++-------- 4 files changed, 98 insertions(+), 44 deletions(-) diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go index 06aaee3dea..a4dd366139 100644 --- a/testutil/keeper/unit_test_helpers.go +++ b/testutil/keeper/unit_test_helpers.go @@ -14,9 +14,14 @@ import ( providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" "github.com/cosmos/interchain-security/x/ccv/types" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmdb "github.com/tendermint/tm-db" + + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" ) // Constructs a provider keeper and context object for unit tests, backed by an in-memory db. @@ -67,7 +72,7 @@ func GetConsumerKeeperAndCtx(t testing.TB) (consumerkeeper.Keeper, sdk.Context) // Constructs a provider keeper for unit tests, backed by an in-memory db, // with ability to pass mocked or otherwise manipulated parameters. -func GetProviderKeeperWithMocks(t testing.TB, +func GetProviderKeeperWithMocks( cdc *codec.ProtoCodec, storeKey *storetypes.KVStoreKey, paramsSubspace paramstypes.Subspace, @@ -81,7 +86,7 @@ func GetProviderKeeperWithMocks(t testing.TB, accountKeeper types.AccountKeeper, ) providerkeeper.Keeper { - k := providerkeeper.NewKeeper( + return providerkeeper.NewKeeper( cdc, storeKey, paramsSubspace, @@ -95,12 +100,11 @@ func GetProviderKeeperWithMocks(t testing.TB, accountKeeper, "", ) - return k } // Constructs a consumer keeper for unit tests, backed by an in-memory db, // with ability to pass mocked or otherwise manipulated parameters. -func GetConsumerKeeperWithMocks(t testing.TB, +func GetCustomConsumerKeeperWithMocks( cdc *codec.ProtoCodec, storeKey *storetypes.KVStoreKey, paramsSubspace paramstypes.Subspace, @@ -116,7 +120,7 @@ func GetConsumerKeeperWithMocks(t testing.TB, ibcCoreKeeper types.IBCCoreKeeper, ) consumerkeeper.Keeper { - k := consumerkeeper.NewKeeper( + return consumerkeeper.NewKeeper( cdc, storeKey, paramsSubspace, @@ -132,7 +136,32 @@ func GetConsumerKeeperWithMocks(t testing.TB, ibcCoreKeeper, "", ) - return k +} + +// Constructs a consumer keeper for unit tests, backed by an in-memory db, +// with ability to pass manipulated parameters, but no mocked keepers. +func GetCustomConsumerKeeper( + cdc *codec.ProtoCodec, + storeKey *storetypes.KVStoreKey, + paramsSubspace paramstypes.Subspace, +) consumerkeeper.Keeper { + + return consumerkeeper.NewKeeper( + cdc, + storeKey, + paramsSubspace, + &MockScopedKeeper{}, + &MockChannelKeeper{}, + &MockPortKeeper{}, + &MockConnectionKeeper{}, + &MockClientKeeper{}, + &MockSlashingKeeper{}, + &MockBankKeeper{}, + &MockAccountKeeper{}, + &MockIBCTransferKeeper{}, + &MockIBCCoreKeeper{}, + "", + ) } func SetupInMemKeeper(t testing.TB) (*codec.ProtoCodec, *storetypes.KVStoreKey, paramstypes.Subspace, sdk.Context) { @@ -157,3 +186,13 @@ func SetupInMemKeeper(t testing.TB) (*codec.ProtoCodec, *storetypes.KVStoreKey, ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) return cdc, storeKey, paramsSubspace, ctx } + +type PrivateKey struct { + PrivKey cryptotypes.PrivKey +} + +// Generates a public key for unit tests (abiding by tricky interface implementations from tm/sdk) +func GenPubKey() (crypto.PubKey, error) { + privKey := PrivateKey{ed25519.GenPrivKey()} + return cryptocodec.ToTmPubKeyInterface(privKey.PrivKey.PubKey()) +} diff --git a/x/ccv/consumer/keeper/keeper_test.go b/x/ccv/consumer/keeper/keeper_test.go index 91d3b9891c..331e2cc7e9 100644 --- a/x/ccv/consumer/keeper/keeper_test.go +++ b/x/ccv/consumer/keeper/keeper_test.go @@ -23,7 +23,6 @@ import ( appProvider "github.com/cosmos/interchain-security/app/provider" testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/testutil/simapp" - consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" "github.com/cosmos/interchain-security/x/ccv/consumer/types" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" @@ -594,21 +593,10 @@ func TestCrossChainValidator(t *testing.T) { cryptocodec.RegisterInterfaces(ir) cdc := codec.NewProtoCodec(ir) - consumerKeeper := consumerkeeper.NewKeeper( + consumerKeeper := testkeeper.GetCustomConsumerKeeper( cdc, storeKey, paramsSubspace, - &testkeeper.MockScopedKeeper{}, - &testkeeper.MockChannelKeeper{}, - &testkeeper.MockPortKeeper{}, - &testkeeper.MockConnectionKeeper{}, - &testkeeper.MockClientKeeper{}, - &testkeeper.MockSlashingKeeper{}, - &testkeeper.MockBankKeeper{}, - &testkeeper.MockAccountKeeper{}, - &testkeeper.MockIBCTransferKeeper{}, - &testkeeper.MockIBCCoreKeeper{}, - "", ) // should return false diff --git a/x/ccv/consumer/keeper/relay_test.go b/x/ccv/consumer/keeper/relay_test.go index 94b096ea9b..caab1969d1 100644 --- a/x/ccv/consumer/keeper/relay_test.go +++ b/x/ccv/consumer/keeper/relay_test.go @@ -145,7 +145,7 @@ func TestOnRecvVSCPacket(t *testing.T) { ).Return(nil).Times(1), ) - consumerKeeper := testkeeper.GetConsumerKeeperWithMocks(t, + consumerKeeper := testkeeper.GetCustomConsumerKeeperWithMocks( cdc, storeKey, paramsSubspace, @@ -335,7 +335,7 @@ func TestOnAcknowledgementPacket(t *testing.T) { mockScopedKeeper := testkeeper.NewMockScopedKeeper(ctrl) mockChannelKeeper := testkeeper.NewMockChannelKeeper(ctrl) - consumerKeeper := testkeeper.GetConsumerKeeperWithMocks(t, + consumerKeeper := testkeeper.GetCustomConsumerKeeperWithMocks( cdc, storeKey, paramsSubspace, diff --git a/x/ccv/consumer/keeper/validators_test.go b/x/ccv/consumer/keeper/validators_test.go index 77bc07215a..8a7eb41a06 100644 --- a/x/ccv/consumer/keeper/validators_test.go +++ b/x/ccv/consumer/keeper/validators_test.go @@ -1,21 +1,39 @@ package keeper_test import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" appConsumer "github.com/cosmos/interchain-security/app/consumer" + testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/x/ccv/consumer/types" + "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" tmrand "github.com/tendermint/tendermint/libs/rand" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtypes "github.com/tendermint/tendermint/types" ) -func (k KeeperTestSuite) TestApplyCCValidatorChanges() { - consumerKeeper := k.consumerChain.App.(*appConsumer.App).ConsumerKeeper - ctx := k.ctx +func TestApplyCCValidatorChanges(t *testing.T) { + // Construct a keeper with a custom codec + // TODO: We need to ensure all custom interfaces are registered in prod, see https://github.com/cosmos/interchain-security/issues/273 + _, storeKey, paramsSubspace, ctx := testkeeper.SetupInMemKeeper(t) + ir := codectypes.NewInterfaceRegistry() + + // Public key implementation must be registered + cryptocodec.RegisterInterfaces(ir) + cdc := codec.NewProtoCodec(ir) + + consumerKeeper := testkeeper.GetCustomConsumerKeeper( + cdc, + storeKey, + paramsSubspace, + ) // utility functions getCCVals := func() (vals []types.CrossChainValidator) { @@ -25,11 +43,11 @@ func (k KeeperTestSuite) TestApplyCCValidatorChanges() { setCCVals := func(vals []*tmtypes.Validator) { for _, v := range vals { - pubkey, err := cryptocodec.FromTmPubKeyInterface(v.PubKey) - k.Require().NoError(err) + publicKey, err := cryptocodec.FromTmPubKeyInterface(v.PubKey) + require.NoError(t, err) - ccv, err := types.NewCCValidator(v.Address, v.VotingPower, pubkey) - k.Require().NoError(err) + ccv, err := types.NewCCValidator(v.Address, v.VotingPower, publicKey) + require.NoError(t, err) consumerKeeper.SetCCValidator(ctx, ccv) } } @@ -48,28 +66,35 @@ func (k KeeperTestSuite) TestApplyCCValidatorChanges() { return } - // prepare the testing setup by clearing - // the current cross-chain validators in states + // prepare the testing setup by clearing the current cross-chain validators in states clearCCVals() - // reuse the testsuite consumer chain validators - // to construct changes - tcVals := k.consumerChain.Vals.Validators + // setup a slice of validators with non zero voting power + numValidators := 4 + tcValidators := []*tmtypes.Validator{} + for i := 0; i < numValidators; i++ { + pubKey, err := testkeeper.GenPubKey() + require.NoError(t, err) + + votingPower := int64(i + 1) + validator := tmtypes.NewValidator(pubKey, votingPower) + tcValidators = append(tcValidators, validator) + } + changes := []abci.ValidatorUpdate{} changesPower := int64(0) - for _, v := range tcVals { + for _, v := range tcValidators { changes = append(changes, tmtypes.TM2PB.ValidatorUpdate(v)) changesPower += v.VotingPower } - // finish setup by importing 3 out 4 testing validators - // into cross-chain validator states - setCCVals(tcVals[:len(tcVals)-1]) + // finish setup by importing 3 out 4 testing validators into cross-chain validator states + setCCVals(tcValidators[:len(tcValidators)-1]) // verify setup ccVals := getCCVals() - k.Require().Len(ccVals, len(tcVals)-1) + require.Len(t, ccVals, len(tcValidators)-1) // test behaviors testCases := []struct { @@ -93,24 +118,25 @@ func (k KeeperTestSuite) TestApplyCCValidatorChanges() { changes: []abci.ValidatorUpdate{ {PubKey: changes[0].PubKey, Power: changes[0].Power + 1}, {PubKey: changes[1].PubKey, Power: changes[1].Power + 2}, - {PubKey: changes[2].PubKey, Power: changes[1].Power + 3}, - {PubKey: changes[3].PubKey, Power: changes[1].Power + 4}, + {PubKey: changes[2].PubKey, Power: changes[2].Power + 3}, + {PubKey: changes[3].PubKey, Power: changes[3].Power + 4}, }, expTotalPower: changesPower + 10, expValsNum: len(ccVals) + 1, }, } - for _, t := range testCases { + for _, tc := range testCases { - consumerKeeper.ApplyCCValidatorChanges(ctx, t.changes) + consumerKeeper.ApplyCCValidatorChanges(ctx, tc.changes) gotVals := getCCVals() - k.Require().Len(gotVals, t.expValsNum) - k.Require().Equal(t.expTotalPower, sumCCValsPow(gotVals)) + require.Len(t, gotVals, tc.expValsNum) + require.Equal(t, tc.expTotalPower, sumCCValsPow(gotVals)) } } +// TODO: unit test func (k KeeperTestSuite) TestHistoricalInfo() { consumerKeeper := k.consumerChain.App.(*appConsumer.App).ConsumerKeeper cCtx := k.consumerChain.GetContext @@ -147,6 +173,7 @@ func (k KeeperTestSuite) TestHistoricalInfo() { k.Require().True(IsValSetSorted(recv.Valset, sdk.DefaultPowerReduction), "HistoricalInfo validators is not sorted") } +// TODO e2e test, or it could be a unit? func (k KeeperTestSuite) TestTrackHistoricalInfo() { consumerKeeper := k.consumerChain.App.(*appConsumer.App).ConsumerKeeper cCtx := k.consumerChain.GetContext From c408745838750a6605c8ea91fcf26803ea1aad68 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Thu, 18 Aug 2022 12:44:53 -0700 Subject: [PATCH 19/24] final tests --- x/ccv/consumer/keeper/keeper_test.go | 2 +- x/ccv/consumer/keeper/validators_test.go | 110 ++++++++++++++--------- x/ccv/consumer/types/genesis_test.go | 11 ++- x/ccv/provider/keeper/keeper_test.go | 2 +- x/ccv/provider/keeper/params_test.go | 2 +- 5 files changed, 75 insertions(+), 52 deletions(-) diff --git a/x/ccv/consumer/keeper/keeper_test.go b/x/ccv/consumer/keeper/keeper_test.go index 331e2cc7e9..cfe638f564 100644 --- a/x/ccv/consumer/keeper/keeper_test.go +++ b/x/ccv/consumer/keeper/keeper_test.go @@ -585,7 +585,7 @@ func (suite *KeeperTestSuite) TestSendSlashPacket() { func TestCrossChainValidator(t *testing.T) { // Construct a keeper with a custom codec - // TODO: We need to ensure all custom interfaces are registered in prod, see https://github.com/cosmos/interchain-security/issues/273 + // TODO: Ensure all custom interfaces are registered in prod, see https://github.com/cosmos/interchain-security/issues/273 _, storeKey, paramsSubspace, ctx := testkeeper.SetupInMemKeeper(t) ir := codectypes.NewInterfaceRegistry() diff --git a/x/ccv/consumer/keeper/validators_test.go b/x/ccv/consumer/keeper/validators_test.go index 8a7eb41a06..ecd5382c22 100644 --- a/x/ccv/consumer/keeper/validators_test.go +++ b/x/ccv/consumer/keeper/validators_test.go @@ -11,6 +11,7 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" appConsumer "github.com/cosmos/interchain-security/app/consumer" testkeeper "github.com/cosmos/interchain-security/testutil/keeper" + "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" "github.com/cosmos/interchain-security/x/ccv/consumer/types" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" @@ -21,7 +22,6 @@ import ( func TestApplyCCValidatorChanges(t *testing.T) { // Construct a keeper with a custom codec - // TODO: We need to ensure all custom interfaces are registered in prod, see https://github.com/cosmos/interchain-security/issues/273 _, storeKey, paramsSubspace, ctx := testkeeper.SetupInMemKeeper(t) ir := codectypes.NewInterfaceRegistry() @@ -41,17 +41,6 @@ func TestApplyCCValidatorChanges(t *testing.T) { return } - setCCVals := func(vals []*tmtypes.Validator) { - for _, v := range vals { - publicKey, err := cryptocodec.FromTmPubKeyInterface(v.PubKey) - require.NoError(t, err) - - ccv, err := types.NewCCValidator(v.Address, v.VotingPower, publicKey) - require.NoError(t, err) - consumerKeeper.SetCCValidator(ctx, ccv) - } - } - clearCCVals := func() { ccVals := consumerKeeper.GetAllCCValidator(ctx) for _, v := range ccVals { @@ -69,17 +58,7 @@ func TestApplyCCValidatorChanges(t *testing.T) { // prepare the testing setup by clearing the current cross-chain validators in states clearCCVals() - // setup a slice of validators with non zero voting power - numValidators := 4 - tcValidators := []*tmtypes.Validator{} - for i := 0; i < numValidators; i++ { - pubKey, err := testkeeper.GenPubKey() - require.NoError(t, err) - - votingPower := int64(i + 1) - validator := tmtypes.NewValidator(pubKey, votingPower) - tcValidators = append(tcValidators, validator) - } + tcValidators := GenerateValidators(t) changes := []abci.ValidatorUpdate{} changesPower := int64(0) @@ -89,8 +68,8 @@ func TestApplyCCValidatorChanges(t *testing.T) { changesPower += v.VotingPower } - // finish setup by importing 3 out 4 testing validators into cross-chain validator states - setCCVals(tcValidators[:len(tcValidators)-1]) + // finish setup by storing 3 out 4 testing validators as cross-chain validator records + SetCCValidators(t, consumerKeeper, ctx, tcValidators[:len(tcValidators)-1]) // verify setup ccVals := getCCVals() @@ -136,44 +115,61 @@ func TestApplyCCValidatorChanges(t *testing.T) { } } -// TODO: unit test -func (k KeeperTestSuite) TestHistoricalInfo() { - consumerKeeper := k.consumerChain.App.(*appConsumer.App).ConsumerKeeper - cCtx := k.consumerChain.GetContext +// Tests the getter and setter behavior for historical info +func TestHistoricalInfo(t *testing.T) { + + // Construct a keeper with a custom codec + _, storeKey, paramsSubspace, ctx := testkeeper.SetupInMemKeeper(t) + ir := codectypes.NewInterfaceRegistry() + + // Public key implementation must be registered + cryptocodec.RegisterInterfaces(ir) + cdc := codec.NewProtoCodec(ir) + + consumerKeeper := testkeeper.GetCustomConsumerKeeper( + cdc, + storeKey, + paramsSubspace, + ) - // get consumer validators - cVals := consumerKeeper.GetAllCCValidator(cCtx()) + ctx = ctx.WithBlockHeight(15) - // iterates over validators and convert them to staking type + // Generate test validators, save them to store, and retrieve stored records + validators := GenerateValidators(t) + SetCCValidators(t, consumerKeeper, ctx, validators) + ccValidators := consumerKeeper.GetAllCCValidator(ctx) + require.Len(t, ccValidators, len(validators)) + + // iterate over validators and convert them to staking type sVals := []stakingtypes.Validator{} - for _, v := range cVals { + for _, v := range ccValidators { pk, err := v.ConsPubKey() - k.Require().NoError(err) + require.NoError(t, err) val, err := stakingtypes.NewValidator(nil, pk, stakingtypes.Description{}) - k.Require().NoError(err) + require.NoError(t, err) // set voting power to random value val.Tokens = sdk.TokensFromConsensusPower(tmrand.NewRand().Int64(), sdk.DefaultPowerReduction) sVals = append(sVals, val) } - currHeight := cCtx().BlockHeight() + currentHeight := ctx.BlockHeight() // create and store historical info - hi := stakingtypes.NewHistoricalInfo(cCtx().BlockHeader(), sVals, sdk.DefaultPowerReduction) - consumerKeeper.SetHistoricalInfo(cCtx(), currHeight, &hi) + hi := stakingtypes.NewHistoricalInfo(ctx.BlockHeader(), sVals, sdk.DefaultPowerReduction) + consumerKeeper.SetHistoricalInfo(ctx, currentHeight, &hi) // expect to get historical info - recv, found := consumerKeeper.GetHistoricalInfo(cCtx(), currHeight) - k.Require().True(found, "HistoricalInfo not found after set") - k.Require().Equal(hi, recv, "HistoricalInfo not equal") + recv, found := consumerKeeper.GetHistoricalInfo(ctx, currentHeight) + require.True(t, found, "HistoricalInfo not found after set") + require.Equal(t, hi, recv, "HistoricalInfo not equal") // verify that historical info valset has validators sorted in order - k.Require().True(IsValSetSorted(recv.Valset, sdk.DefaultPowerReduction), "HistoricalInfo validators is not sorted") + require.True(t, IsValSetSorted(recv.Valset, sdk.DefaultPowerReduction), "HistoricalInfo validators is not sorted") } -// TODO e2e test, or it could be a unit? +// Tests the tracking of historical info in the context of new blocks being committed func (k KeeperTestSuite) TestTrackHistoricalInfo() { consumerKeeper := k.consumerChain.App.(*appConsumer.App).ConsumerKeeper cCtx := k.consumerChain.GetContext @@ -261,3 +257,31 @@ func IsValSetSorted(data []stakingtypes.Validator, powerReduction sdk.Int) bool } return true } + +// Generates 4 test validators with non zero voting power +func GenerateValidators(t testing.TB) []*tmtypes.Validator { + numValidators := 4 + validators := []*tmtypes.Validator{} + for i := 0; i < numValidators; i++ { + pubKey, err := testkeeper.GenPubKey() + require.NoError(t, err) + + votingPower := int64(i + 1) + validator := tmtypes.NewValidator(pubKey, votingPower) + validators = append(validators, validator) + } + return validators +} + +// Sets each input tmtypes.Validator as a types.CrossChainValidator in the consumer keeper store +func SetCCValidators(t testing.TB, consumerKeeper keeper.Keeper, + ctx sdk.Context, validators []*tmtypes.Validator) { + for _, v := range validators { + publicKey, err := cryptocodec.FromTmPubKeyInterface(v.PubKey) + require.NoError(t, err) + + ccv, err := types.NewCCValidator(v.Address, v.VotingPower, publicKey) + require.NoError(t, err) + consumerKeeper.SetCCValidator(ctx, ccv) + } +} diff --git a/x/ccv/consumer/types/genesis_test.go b/x/ccv/consumer/types/genesis_test.go index 4c82133a90..4a6c34980e 100644 --- a/x/ccv/consumer/types/genesis_test.go +++ b/x/ccv/consumer/types/genesis_test.go @@ -7,12 +7,13 @@ import ( clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" commitmenttypes "github.com/cosmos/ibc-go/v3/modules/core/23-commitment/types" ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" - "github.com/cosmos/ibc-go/v3/testing/mock" "github.com/cosmos/interchain-security/x/ccv/consumer/types" tmtypes "github.com/tendermint/tendermint/types" + testutil "github.com/cosmos/interchain-security/testutil/keeper" + "github.com/stretchr/testify/require" ) @@ -29,9 +30,8 @@ var ( ) func TestValidateInitialGenesisState(t *testing.T) { - // generate validator private/public key - privVal := mock.NewPV() - pubKey, err := privVal.GetPubKey() + // generate validator public key + pubKey, err := testutil.GenPubKey() require.NoError(t, err) // create validator set with single validator @@ -147,8 +147,7 @@ func TestValidateInitialGenesisState(t *testing.T) { func TestValidateRestartGenesisState(t *testing.T) { // generate validator private/public key - privVal := mock.NewPV() - pubKey, err := privVal.GetPubKey() + pubKey, err := testutil.GenPubKey() require.NoError(t, err) // create validator set with single validator diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index c229554f77..5a542ba2c9 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -374,7 +374,7 @@ func TestHandleSlashPacketDoubleSigning(t *testing.T) { evidencetypes.DoubleSignJailEndTime).Times(1), ) - providerKeeper := testkeeper.GetProviderKeeperWithMocks(t, + providerKeeper := testkeeper.GetProviderKeeperWithMocks( cdc, storeKey, paramsSubspace, diff --git a/x/ccv/provider/keeper/params_test.go b/x/ccv/provider/keeper/params_test.go index 3350c1fa7a..b67c856398 100644 --- a/x/ccv/provider/keeper/params_test.go +++ b/x/ccv/provider/keeper/params_test.go @@ -28,7 +28,7 @@ func TestParams(t *testing.T) { paramsSubspace.Set(ctx, types.KeyTemplateClient, expectedClientState) - providerKeeper := testkeeper.GetProviderKeeperWithMocks(t, + providerKeeper := testkeeper.GetProviderKeeperWithMocks( cdc, storeKey, paramsSubspace, From 34a106a6472ebc9127706b63982b94fa73b86480 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Thu, 18 Aug 2022 13:12:36 -0700 Subject: [PATCH 20/24] cleans --- x/ccv/consumer/keeper/relay_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/x/ccv/consumer/keeper/relay_test.go b/x/ccv/consumer/keeper/relay_test.go index caab1969d1..2187a40db4 100644 --- a/x/ccv/consumer/keeper/relay_test.go +++ b/x/ccv/consumer/keeper/relay_test.go @@ -170,7 +170,6 @@ func TestOnRecvVSCPacket(t *testing.T) { if tc.noAck { // if closing channel was successful, no acknowledgement returned, see OnRecvPacketOnUnknownChannel - // TODO: Confirm this functionality require.Nil(t, ack, "invalid test case: %s ack returned ", tc.name) } else { require.NotNil(t, ack, "invalid test case: %s did not return ack", tc.name) @@ -359,7 +358,6 @@ func TestOnAcknowledgementPacket(t *testing.T) { ) // AcknowledgePacket is in reference to a packet originally sent from this (consumer) module. - // TODO: Do we want to test weird edge cases like processing an ack where source portID != consumer portID? packet := channeltypes.NewPacket( packetData.GetBytes(), 1, From d9290b6505cc1c96470043cbbe580fd050d81255 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Mon, 22 Aug 2022 08:44:24 -0700 Subject: [PATCH 21/24] GetProviderClient -> GetProviderClientID --- x/ccv/consumer/keeper/genesis.go | 8 ++++---- x/ccv/consumer/keeper/genesis_test.go | 2 +- x/ccv/consumer/keeper/keeper.go | 14 +++++++------- x/ccv/consumer/keeper/keeper_test.go | 6 +++--- x/ccv/consumer/module_test.go | 2 +- x/ccv/consumer/types/keys.go | 4 ++-- x/ccv/consumer/types/keys_test.go | 2 +- x/ccv/provider/keeper/keeper_test.go | 2 +- x/ccv/provider/provider_test.go | 2 +- 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/x/ccv/consumer/keeper/genesis.go b/x/ccv/consumer/keeper/genesis.go index 86fcb97b89..849a07662d 100644 --- a/x/ccv/consumer/keeper/genesis.go +++ b/x/ccv/consumer/keeper/genesis.go @@ -48,7 +48,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state *types.GenesisState) []abci.V // Set default value for valset update ID k.SetHeightValsetUpdateID(ctx, uint64(ctx.BlockHeight()), uint64(0)) // set provider client id. - k.SetProviderClient(ctx, clientID) + k.SetProviderClientID(ctx, clientID) } else { // verify that latest consensus state on provider client matches the initial validator set of restarted chain // thus, IBC genesis MUST run before CCV consumer genesis @@ -87,7 +87,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state *types.GenesisState) []abci.V k.SetUnbondingTime(ctx, unbondingTime) // set provider client id - k.SetProviderClient(ctx, state.ProviderClientId) + k.SetProviderClientID(ctx, state.ProviderClientId) // set provider channel id. k.SetProviderChannel(ctx, state.ProviderChannelId) // set all unbonding sequences @@ -110,7 +110,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { } if channelID, ok := k.GetProviderChannel(ctx); ok { - clientID, ok := k.GetProviderClient(ctx) + clientID, ok := k.GetProviderClientID(ctx) if !ok { panic("provider client does not exist") } @@ -131,7 +131,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { gs.MaturingPackets = maturingPackets return gs } - clientID, ok := k.GetProviderClient(ctx) + clientID, ok := k.GetProviderClientID(ctx) // if provider clientID and channelID don't exist on the consumer chain, then CCV protocol is disabled for this chain // return a disabled genesis state if !ok { diff --git a/x/ccv/consumer/keeper/genesis_test.go b/x/ccv/consumer/keeper/genesis_test.go index 9b9c0c8114..88268145d7 100644 --- a/x/ccv/consumer/keeper/genesis_test.go +++ b/x/ccv/consumer/keeper/genesis_test.go @@ -33,7 +33,7 @@ func (suite *KeeperTestSuite) TestGenesis() { portId := suite.consumerChain.App.(*app.App).ConsumerKeeper.GetPort(ctx) suite.Require().Equal(consumertypes.PortID, portId) - clientId, ok := suite.consumerChain.App.(*app.App).ConsumerKeeper.GetProviderClient(ctx) + clientId, ok := suite.consumerChain.App.(*app.App).ConsumerKeeper.GetProviderClientID(ctx) suite.Require().True(ok) clientState, ok := suite.consumerChain.App.GetIBCKeeper().ClientKeeper.GetClientState(ctx, clientId) suite.Require().True(ok) diff --git a/x/ccv/consumer/keeper/keeper.go b/x/ccv/consumer/keeper/keeper.go index 2885f34382..9c7343333c 100644 --- a/x/ccv/consumer/keeper/keeper.go +++ b/x/ccv/consumer/keeper/keeper.go @@ -164,17 +164,17 @@ func (k Keeper) DeleteUnbondingTime(ctx sdk.Context) { store.Delete(types.UnbondingTimeKey()) } -// SetProviderClient sets the provider clientID that is validating the chain. +// SetProviderClientID sets the provider clientID that is validating the chain. // Set in InitGenesis -func (k Keeper) SetProviderClient(ctx sdk.Context, clientID string) { +func (k Keeper) SetProviderClientID(ctx sdk.Context, clientID string) { store := ctx.KVStore(k.storeKey) - store.Set(types.ProviderClientKey(), []byte(clientID)) + store.Set(types.ProviderClientIDKey(), []byte(clientID)) } -// GetProviderClient gets the provider clientID that is validating the chain. -func (k Keeper) GetProviderClient(ctx sdk.Context) (string, bool) { +// GetProviderClientID gets the provider clientID that is validating the chain. +func (k Keeper) GetProviderClientID(ctx sdk.Context) (string, bool) { store := ctx.KVStore(k.storeKey) - clientIdBytes := store.Get(types.ProviderClientKey()) + clientIdBytes := store.Get(types.ProviderClientIDKey()) if clientIdBytes == nil { return "", false } @@ -289,7 +289,7 @@ func (k Keeper) VerifyProviderChain(ctx sdk.Context, channelID string, connectio return sdkerrors.Wrapf(conntypes.ErrConnectionNotFound, "connection not found for connection ID: %s", connectionID) } // Verify that client id is expected clientID - expectedClientId, ok := k.GetProviderClient(ctx) + expectedClientId, ok := k.GetProviderClientID(ctx) if !ok { return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "could not find provider client id") } diff --git a/x/ccv/consumer/keeper/keeper_test.go b/x/ccv/consumer/keeper/keeper_test.go index d96656f762..3eca6c626f 100644 --- a/x/ccv/consumer/keeper/keeper_test.go +++ b/x/ccv/consumer/keeper/keeper_test.go @@ -99,9 +99,9 @@ func (suite *KeeperTestSuite) SetupTest() { suite.Require().True(found, "consumer client not found") suite.path.EndpointB.ClientID = consumerClient // - set consumer endpoint's clientID - providerClient, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClient(suite.consumerChain.GetContext()) + providerClientID, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.consumerChain.GetContext()) suite.Require().True(found, "provider client not found") - suite.path.EndpointA.ClientID = providerClient + suite.path.EndpointA.ClientID = providerClientID // - client config providerUnbondingPeriod := suite.providerChain.App.(*appProvider.App).GetStakingKeeper().UnbondingTime(suite.providerChain.GetContext()) suite.path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).UnbondingPeriod = providerUnbondingPeriod @@ -146,7 +146,7 @@ func (suite *KeeperTestSuite) TestUnbondingTime() { } func (suite *KeeperTestSuite) TestProviderClient() { - providerClient, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClient(suite.ctx) + providerClient, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.ctx) suite.Require().True(ok) clientState, _ := suite.consumerChain.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.ctx, providerClient) diff --git a/x/ccv/consumer/module_test.go b/x/ccv/consumer/module_test.go index 61b3638b56..40fd42615c 100644 --- a/x/ccv/consumer/module_test.go +++ b/x/ccv/consumer/module_test.go @@ -93,7 +93,7 @@ func (suite *ConsumerTestSuite) SetupTest() { suite.Require().True(found, "consumer client not found") suite.path.EndpointB.ClientID = consumerClient // - set consumer endpoint's clientID - providerClient, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClient(suite.consumerChain.GetContext()) + providerClient, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.consumerChain.GetContext()) suite.Require().True(found, "provider client not found") suite.path.EndpointA.ClientID = providerClient // - client config diff --git a/x/ccv/consumer/types/keys.go b/x/ccv/consumer/types/keys.go index 9e49ae20b8..5f8be6f5b8 100644 --- a/x/ccv/consumer/types/keys.go +++ b/x/ccv/consumer/types/keys.go @@ -89,8 +89,8 @@ func UnbondingTimeKey() []byte { return []byte{UnbondingTimeByteKey} } -// ProviderClientKey returns the key for storing clientID of the provider -func ProviderClientKey() []byte { +// ProviderClientIDKey returns the key for storing clientID of the provider +func ProviderClientIDKey() []byte { return []byte{ProviderClientByteKey} } diff --git a/x/ccv/consumer/types/keys_test.go b/x/ccv/consumer/types/keys_test.go index ff97eb7e57..f3bcc0dd15 100644 --- a/x/ccv/consumer/types/keys_test.go +++ b/x/ccv/consumer/types/keys_test.go @@ -38,7 +38,7 @@ func getSingleByteKeys() [][]byte { keys[i], i = PortKey(), i+1 keys[i], i = LastDistributionTransmissionKey(), i+1 keys[i], i = UnbondingTimeKey(), i+1 - keys[i], i = ProviderClientKey(), i+1 + keys[i], i = ProviderClientIDKey(), i+1 keys[i], i = ProviderChannelKey(), i+1 keys[i], i = PendingChangesKey(), i+1 keys[i], i = []byte{HistoricalInfoBytePrefix}, i+1 diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 45aac7d579..33e7e00c8c 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -97,7 +97,7 @@ func (suite *KeeperTestSuite) SetupTest() { suite.Require().True(found, "consumer client not found") suite.path.EndpointB.ClientID = consumerClient // - set consumer endpoint's clientID - providerClient, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClient(suite.consumerChain.GetContext()) + providerClient, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.consumerChain.GetContext()) suite.Require().True(found, "provider client not found") suite.path.EndpointA.ClientID = providerClient // - client config diff --git a/x/ccv/provider/provider_test.go b/x/ccv/provider/provider_test.go index 8139aec6ff..37a15a1d89 100644 --- a/x/ccv/provider/provider_test.go +++ b/x/ccv/provider/provider_test.go @@ -92,7 +92,7 @@ func (suite *ProviderTestSuite) SetupTest() { suite.Require().True(found, "consumer client not found") suite.path.EndpointB.ClientID = consumerClient // - set consumer endpoint's clientID - providerClient, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClient(suite.consumerChain.GetContext()) + providerClient, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.consumerChain.GetContext()) suite.Require().True(found, "provider client not found") suite.path.EndpointA.ClientID = providerClient // - client config From 6ceff72781e2fce2996c2c3fae4b1b59494fc4c3 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Mon, 22 Aug 2022 08:50:18 -0700 Subject: [PATCH 22/24] providerClient -> providerClientID --- x/ccv/consumer/keeper/keeper_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/ccv/consumer/keeper/keeper_test.go b/x/ccv/consumer/keeper/keeper_test.go index cfe638f564..78cdf364ad 100644 --- a/x/ccv/consumer/keeper/keeper_test.go +++ b/x/ccv/consumer/keeper/keeper_test.go @@ -149,10 +149,10 @@ func TestUnbondingTime(t *testing.T) { // Tests that the provider client managed by the consumer keeper matches the client keeper's client state func (suite *KeeperTestSuite) TestProviderClientMatches() { - providerClient, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClient(suite.ctx) + providerClientID, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClient(suite.ctx) suite.Require().True(ok) - clientState, _ := suite.consumerChain.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.ctx, providerClient) + clientState, _ := suite.consumerChain.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.ctx, providerClientID) suite.Require().Equal(suite.providerClient, clientState, "stored client state does not match genesis provider client") } From 910370857afbe9dc9623e2d617117c9e8de79b9c Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Mon, 22 Aug 2022 08:55:46 -0700 Subject: [PATCH 23/24] changes for merging #276 --- x/ccv/consumer/keeper/keeper_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/x/ccv/consumer/keeper/keeper_test.go b/x/ccv/consumer/keeper/keeper_test.go index 78cdf364ad..88ccc50f41 100644 --- a/x/ccv/consumer/keeper/keeper_test.go +++ b/x/ccv/consumer/keeper/keeper_test.go @@ -103,7 +103,7 @@ func (suite *KeeperTestSuite) SetupTest() { suite.Require().True(found, "consumer client not found") suite.path.EndpointB.ClientID = consumerClient // - set consumer endpoint's clientID - providerClient, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClient(suite.consumerChain.GetContext()) + providerClient, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.consumerChain.GetContext()) suite.Require().True(found, "provider client not found") suite.path.EndpointA.ClientID = providerClient // - client config @@ -149,19 +149,19 @@ func TestUnbondingTime(t *testing.T) { // Tests that the provider client managed by the consumer keeper matches the client keeper's client state func (suite *KeeperTestSuite) TestProviderClientMatches() { - providerClientID, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClient(suite.ctx) + providerClientID, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.ctx) suite.Require().True(ok) clientState, _ := suite.consumerChain.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.ctx, providerClientID) suite.Require().Equal(suite.providerClient, clientState, "stored client state does not match genesis provider client") } -func TestProviderClient(t *testing.T) { +func TestProviderClientID(t *testing.T) { consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) - _, ok := consumerKeeper.GetProviderClient(ctx) + _, ok := consumerKeeper.GetProviderClientID(ctx) require.False(t, ok) - consumerKeeper.SetProviderClient(ctx, "someClientID") - clientID, ok := consumerKeeper.GetProviderClient(ctx) + consumerKeeper.SetProviderClientID(ctx, "someClientID") + clientID, ok := consumerKeeper.GetProviderClientID(ctx) require.True(t, ok) require.Equal(t, "someClientID", clientID) } From 02b3deeb7c20e05524e3bb06965a01794d2e2b38 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Mon, 22 Aug 2022 10:10:45 -0700 Subject: [PATCH 24/24] test comments --- x/ccv/consumer/keeper/keeper_test.go | 11 ++++++++++- x/ccv/consumer/keeper/params_test.go | 1 + x/ccv/consumer/keeper/relay_test.go | 4 +++- x/ccv/consumer/keeper/validators_test.go | 1 + x/ccv/consumer/types/genesis_test.go | 4 ++++ x/ccv/provider/keeper/keeper_test.go | 10 ++++++++-- 6 files changed, 27 insertions(+), 4 deletions(-) diff --git a/x/ccv/consumer/keeper/keeper_test.go b/x/ccv/consumer/keeper/keeper_test.go index 88ccc50f41..0757078588 100644 --- a/x/ccv/consumer/keeper/keeper_test.go +++ b/x/ccv/consumer/keeper/keeper_test.go @@ -136,6 +136,7 @@ func (suite *KeeperTestSuite) SetupCCVChannel() { suite.coordinator.CreateChannels(suite.path) } +// TestUnbondingTime tests getter and setter functionality for the unbonding period of a consumer chain func TestUnbondingTime(t *testing.T) { consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) _, ok := consumerKeeper.GetUnbondingTime(ctx) @@ -147,7 +148,7 @@ func TestUnbondingTime(t *testing.T) { require.Equal(t, storedUnbondingPeriod, unbondingPeriod) } -// Tests that the provider client managed by the consumer keeper matches the client keeper's client state +// TestProviderClientMatches tests that the provider client managed by the consumer keeper matches the client keeper's client state func (suite *KeeperTestSuite) TestProviderClientMatches() { providerClientID, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.ctx) suite.Require().True(ok) @@ -156,6 +157,7 @@ func (suite *KeeperTestSuite) TestProviderClientMatches() { suite.Require().Equal(suite.providerClient, clientState, "stored client state does not match genesis provider client") } +// TestProviderClientID tests getter and setter functionality for the client ID stored on consumer keeper func TestProviderClientID(t *testing.T) { consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) _, ok := consumerKeeper.GetProviderClientID(ctx) @@ -166,6 +168,7 @@ func TestProviderClientID(t *testing.T) { require.Equal(t, "someClientID", clientID) } +// TestProviderChannel tests getter and setter functionality for the channel ID stored on consumer keeper func TestProviderChannel(t *testing.T) { consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) _, ok := consumerKeeper.GetProviderChannel(ctx) @@ -176,6 +179,7 @@ func TestProviderChannel(t *testing.T) { require.Equal(t, "channelID", channelID) } +// TestPendingChanges tests getter, setter, and delete functionality for pending VSCs on a consumer chain func TestPendingChanges(t *testing.T) { pk1, err := cryptocodec.ToTmProtoPublicKey(ed25519.GenPrivKey().PubKey()) require.NoError(t, err) @@ -209,6 +213,7 @@ func TestPendingChanges(t *testing.T) { require.Nil(t, gotPd, "got non-nil pending changes after Delete") } +// TestPacketMaturityTime tests getter, setter, and iterator functionality for the packet maturity time of a received VSC packet func TestPacketMaturityTime(t *testing.T) { consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) consumerKeeper.SetPacketMaturityTime(ctx, 1, 10) @@ -236,6 +241,7 @@ func TestPacketMaturityTime(t *testing.T) { }) } +// TestVerifyProviderChain tests the VerifyProviderChain method for the consumer keeper func (suite *KeeperTestSuite) TestVerifyProviderChain() { var connectionHops []string channelID := "channel-0" @@ -502,6 +508,7 @@ func (suite *KeeperTestSuite) TestValidatorDoubleSigning() { suite.Require().EqualValues(expCommit, gotCommit) } +// TestSendSlashPacket tests the functionality of SendSlashPacket and asserts state changes related to that method func (suite *KeeperTestSuite) TestSendSlashPacket() { suite.SetupCCVChannel() @@ -582,6 +589,7 @@ func (suite *KeeperTestSuite) TestSendSlashPacket() { suite.Require().Len(requests, 0) } +// TestCrossChainValidator tests the getter, setter, and deletion method for cross chain validator records func TestCrossChainValidator(t *testing.T) { // Construct a keeper with a custom codec @@ -632,6 +640,7 @@ func TestCrossChainValidator(t *testing.T) { require.False(t, found) } +// TestPendingSlashRequests tests the getter, setter, appending method, and deletion method for pending slash requests func TestPendingSlashRequests(t *testing.T) { consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) diff --git a/x/ccv/consumer/keeper/params_test.go b/x/ccv/consumer/keeper/params_test.go index 6e19907e67..3de23cb73f 100644 --- a/x/ccv/consumer/keeper/params_test.go +++ b/x/ccv/consumer/keeper/params_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" ) +// TestParams tests the default params set for a consumer chain, and related getters/setters func TestParams(t *testing.T) { consumerKeeper, ctx := testkeeper.GetConsumerKeeperAndCtx(t) consumerKeeper.SetParams(ctx, types.DefaultParams()) diff --git a/x/ccv/consumer/keeper/relay_test.go b/x/ccv/consumer/keeper/relay_test.go index 2187a40db4..4c3654b59e 100644 --- a/x/ccv/consumer/keeper/relay_test.go +++ b/x/ccv/consumer/keeper/relay_test.go @@ -24,6 +24,7 @@ import ( "github.com/tendermint/tendermint/libs/bytes" ) +// TestOnRecvVSCPacket tests the behavior of OnRecvVSCPacket over various packet scenarios func TestOnRecvVSCPacket(t *testing.T) { consumerCCVChannelID := "consumerCCVChannelID" providerCCVChannelID := "providerCCVChannelID" @@ -200,6 +201,7 @@ func TestOnRecvVSCPacket(t *testing.T) { } } +// TestUnbondMaturePackets tests the behavior of UnbondMaturePackets and related state checks func (suite *KeeperTestSuite) TestUnbondMaturePackets() { // setup CCV channel suite.SetupCCVChannel() @@ -290,7 +292,7 @@ func (suite *KeeperTestSuite) TestUnbondMaturePackets() { suite.Require().Equal(uint64(2), commitments[1].Sequence, "did not send VSCMatured packet for VSC packet 2") } -// incrementTimeByUnbondingPeriod increments the overall time by jumpPeriod +// incrementTimeBy increments the overall time by jumpPeriod func incrementTimeBy(s *KeeperTestSuite, jumpPeriod time.Duration) { // Get unboding period from staking keeper consumerUnbondingPeriod, found := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(s.consumerChain.GetContext()) diff --git a/x/ccv/consumer/keeper/validators_test.go b/x/ccv/consumer/keeper/validators_test.go index ecd5382c22..4b034c20e7 100644 --- a/x/ccv/consumer/keeper/validators_test.go +++ b/x/ccv/consumer/keeper/validators_test.go @@ -20,6 +20,7 @@ import ( tmtypes "github.com/tendermint/tendermint/types" ) +// TestApplyCCValidatorChanges tests the ApplyCCValidatorChanges method for a consumer keeper func TestApplyCCValidatorChanges(t *testing.T) { // Construct a keeper with a custom codec _, storeKey, paramsSubspace, ctx := testkeeper.SetupInMemKeeper(t) diff --git a/x/ccv/consumer/types/genesis_test.go b/x/ccv/consumer/types/genesis_test.go index 4a6c34980e..a122619961 100644 --- a/x/ccv/consumer/types/genesis_test.go +++ b/x/ccv/consumer/types/genesis_test.go @@ -29,6 +29,8 @@ var ( upgradePath = []string{"upgrade", "upgradedIBCState"} ) +// TestValidateInitialGenesisState tests a NewInitialGenesisState instantiation, +// and its Validate() method over different genesis scenarios func TestValidateInitialGenesisState(t *testing.T) { // generate validator public key pubKey, err := testutil.GenPubKey() @@ -145,6 +147,8 @@ func TestValidateInitialGenesisState(t *testing.T) { } } +// TestValidateRestartGenesisState tests a NewRestartGenesisState instantiation, +// and its Validate() method over different genesis scenarios func TestValidateRestartGenesisState(t *testing.T) { // generate validator private/public key pubKey, err := testutil.GenPubKey() diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 3bfb4a0dfb..a564534e5f 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -129,6 +129,7 @@ func TestKeeperTestSuite(t *testing.T) { suite.Run(t, new(KeeperTestSuite)) } +// TestValsetUpdateBlockHeight tests the getter, setter, and deletion methods for valset updates mapped to block height func TestValsetUpdateBlockHeight(t *testing.T) { providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) @@ -149,6 +150,7 @@ func TestValsetUpdateBlockHeight(t *testing.T) { require.Equal(t, blockHeight, uint64(4)) } +// TestSlashAcks tests the getter, setter, iteration, and deletion methods for stored slash acknowledgements func TestSlashAcks(t *testing.T) { providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) @@ -190,6 +192,7 @@ func TestSlashAcks(t *testing.T) { require.Len(t, chainsAcks, len(chains)) } +// TestAppendSlashAck tests the append method for stored slash acknowledgements func TestAppendSlashAck(t *testing.T) { providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) @@ -208,6 +211,7 @@ func TestAppendSlashAck(t *testing.T) { require.Len(t, acks, 1) } +// TestPendingVSCs tests the getter, appending, and deletion methods for stored pending VSCs func TestPendingVSCs(t *testing.T) { providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) @@ -261,6 +265,7 @@ func TestPendingVSCs(t *testing.T) { require.False(t, found) } +// TestInitHeight tests the getter and setter methods for the stored block heights (on provider) when a given consumer chain was started func TestInitHeight(t *testing.T) { providerKeeper, ctx := testkeeper.GetProviderKeeperAndCtx(t) @@ -282,7 +287,7 @@ func TestInitHeight(t *testing.T) { } } -// Tests the handling of a double-signing related slash packet, with e2e tests +// TestHandleSlashPacketDoubleSigning tests the handling of a double-signing related slash packet, with e2e tests func (suite *KeeperTestSuite) TestHandleSlashPacketDoubleSigning() { providerKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper providerSlashingKeeper := suite.providerChain.App.(*appProvider.App).SlashingKeeper @@ -323,7 +328,7 @@ func (suite *KeeperTestSuite) TestHandleSlashPacketDoubleSigning() { suite.Require().True(signingInfo.Tombstoned) } -// Tests the handling of a double-signing related slash packet, with mocks and unit tests +// TestHandleSlashPacketDoubleSigning tests the handling of a double-signing related slash packet, with mocks and unit tests func TestHandleSlashPacketDoubleSigning(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -395,6 +400,7 @@ func TestHandleSlashPacketDoubleSigning(t *testing.T) { require.True(t, success) } +// TestHandleSlashPacketErrors tests errors for the HandleSlashPacket method in an e2e testing setting func (suite *KeeperTestSuite) TestHandleSlashPacketErrors() { providerStakingKeeper := suite.providerChain.App.(*appProvider.App).StakingKeeper ProviderKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper