github.com/cosmos/cosmos-sdk@v0.50.10/x/gov/keeper/common_test.go (about) 1 package keeper_test 2 3 import ( 4 "fmt" 5 "testing" 6 7 cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" 8 cmttime "github.com/cometbft/cometbft/types/time" 9 "github.com/golang/mock/gomock" 10 "github.com/stretchr/testify/require" 11 12 "cosmossdk.io/math" 13 storetypes "cosmossdk.io/store/types" 14 15 "github.com/cosmos/cosmos-sdk/baseapp" 16 "github.com/cosmos/cosmos-sdk/codec/address" 17 "github.com/cosmos/cosmos-sdk/runtime" 18 "github.com/cosmos/cosmos-sdk/testutil" 19 "github.com/cosmos/cosmos-sdk/testutil/testdata" 20 sdk "github.com/cosmos/cosmos-sdk/types" 21 moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" 22 authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 23 banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 24 disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types" 25 "github.com/cosmos/cosmos-sdk/x/gov/keeper" 26 govtestutil "github.com/cosmos/cosmos-sdk/x/gov/testutil" 27 "github.com/cosmos/cosmos-sdk/x/gov/types" 28 v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 29 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" 30 minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" 31 ) 32 33 var ( 34 _, _, addr = testdata.KeyTestPubAddr() 35 govAcct = authtypes.NewModuleAddress(types.ModuleName) 36 distAcct = authtypes.NewModuleAddress(disttypes.ModuleName) 37 TestProposal = getTestProposal() 38 ) 39 40 // getTestProposal creates and returns a test proposal message. 41 func getTestProposal() []sdk.Msg { 42 legacyProposalMsg, err := v1.NewLegacyContent(v1beta1.NewTextProposal("Title", "description"), authtypes.NewModuleAddress(types.ModuleName).String()) 43 if err != nil { 44 panic(err) 45 } 46 47 return []sdk.Msg{ 48 banktypes.NewMsgSend(govAcct, addr, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000)))), 49 legacyProposalMsg, 50 } 51 } 52 53 // setupGovKeeper creates a govKeeper as well as all its dependencies. 54 func setupGovKeeper(t *testing.T) ( 55 *keeper.Keeper, 56 *govtestutil.MockAccountKeeper, 57 *govtestutil.MockBankKeeper, 58 *govtestutil.MockStakingKeeper, 59 *govtestutil.MockDistributionKeeper, 60 moduletestutil.TestEncodingConfig, 61 sdk.Context, 62 ) { 63 key := storetypes.NewKVStoreKey(types.StoreKey) 64 storeService := runtime.NewKVStoreService(key) 65 testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) 66 ctx := testCtx.Ctx.WithBlockHeader(cmtproto.Header{Time: cmttime.Now()}) 67 encCfg := moduletestutil.MakeTestEncodingConfig() 68 v1.RegisterInterfaces(encCfg.InterfaceRegistry) 69 v1beta1.RegisterInterfaces(encCfg.InterfaceRegistry) 70 banktypes.RegisterInterfaces(encCfg.InterfaceRegistry) 71 72 // Create MsgServiceRouter, but don't populate it before creating the gov 73 // keeper. 74 msr := baseapp.NewMsgServiceRouter() 75 76 // gomock initializations 77 ctrl := gomock.NewController(t) 78 acctKeeper := govtestutil.NewMockAccountKeeper(ctrl) 79 bankKeeper := govtestutil.NewMockBankKeeper(ctrl) 80 stakingKeeper := govtestutil.NewMockStakingKeeper(ctrl) 81 distributionKeeper := govtestutil.NewMockDistributionKeeper(ctrl) 82 83 acctKeeper.EXPECT().GetModuleAddress(types.ModuleName).Return(govAcct).AnyTimes() 84 acctKeeper.EXPECT().GetModuleAddress(disttypes.ModuleName).Return(distAcct).AnyTimes() 85 acctKeeper.EXPECT().GetModuleAccount(gomock.Any(), types.ModuleName).Return(authtypes.NewEmptyModuleAccount(types.ModuleName)).AnyTimes() 86 acctKeeper.EXPECT().AddressCodec().Return(address.NewBech32Codec("cosmos")).AnyTimes() 87 88 trackMockBalances(bankKeeper, distributionKeeper) 89 stakingKeeper.EXPECT().TokensFromConsensusPower(ctx, gomock.Any()).DoAndReturn(func(ctx sdk.Context, power int64) math.Int { 90 return sdk.TokensFromConsensusPower(power, math.NewIntFromUint64(1000000)) 91 }).AnyTimes() 92 93 stakingKeeper.EXPECT().BondDenom(ctx).Return("stake", nil).AnyTimes() 94 stakingKeeper.EXPECT().IterateBondedValidatorsByPower(gomock.Any(), gomock.Any()).AnyTimes() 95 stakingKeeper.EXPECT().IterateDelegations(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() 96 stakingKeeper.EXPECT().TotalBondedTokens(gomock.Any()).Return(math.NewInt(10000000), nil).AnyTimes() 97 distributionKeeper.EXPECT().FundCommunityPool(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 98 99 // Gov keeper initializations 100 101 govKeeper := keeper.NewKeeper(encCfg.Codec, storeService, acctKeeper, bankKeeper, stakingKeeper, distributionKeeper, msr, types.DefaultConfig(), govAcct.String()) 102 require.NoError(t, govKeeper.ProposalID.Set(ctx, 1)) 103 govRouter := v1beta1.NewRouter() // Also register legacy gov handlers to test them too. 104 govRouter.AddRoute(types.RouterKey, v1beta1.ProposalHandler) 105 govKeeper.SetLegacyRouter(govRouter) 106 err := govKeeper.Params.Set(ctx, v1.DefaultParams()) 107 require.NoError(t, err) 108 err = govKeeper.Constitution.Set(ctx, "constitution") 109 require.NoError(t, err) 110 111 // Register all handlers for the MegServiceRouter. 112 msr.SetInterfaceRegistry(encCfg.InterfaceRegistry) 113 v1.RegisterMsgServer(msr, keeper.NewMsgServerImpl(govKeeper)) 114 banktypes.RegisterMsgServer(msr, nil) // Nil is fine here as long as we never execute the proposal's Msgs. 115 116 return govKeeper, acctKeeper, bankKeeper, stakingKeeper, distributionKeeper, encCfg, ctx 117 } 118 119 // trackMockBalances sets up expected calls on the Mock BankKeeper, and also 120 // locally tracks accounts balances (not modules balances). 121 func trackMockBalances(bankKeeper *govtestutil.MockBankKeeper, distributionKeeper *govtestutil.MockDistributionKeeper) { 122 balances := make(map[string]sdk.Coins) 123 balances[distAcct.String()] = sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(0))) 124 125 // We don't track module account balances. 126 bankKeeper.EXPECT().MintCoins(gomock.Any(), minttypes.ModuleName, gomock.Any()).AnyTimes() 127 bankKeeper.EXPECT().BurnCoins(gomock.Any(), types.ModuleName, gomock.Any()).AnyTimes() 128 bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), minttypes.ModuleName, types.ModuleName, gomock.Any()).AnyTimes() 129 130 // But we do track normal account balances. 131 bankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), types.ModuleName, gomock.Any()).DoAndReturn(func(_ sdk.Context, sender sdk.AccAddress, _ string, coins sdk.Coins) error { 132 newBalance, negative := balances[sender.String()].SafeSub(coins...) 133 if negative { 134 return fmt.Errorf("not enough balance") 135 } 136 balances[sender.String()] = newBalance 137 return nil 138 }).AnyTimes() 139 bankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ sdk.Context, module string, rcpt sdk.AccAddress, coins sdk.Coins) error { 140 balances[rcpt.String()] = balances[rcpt.String()].Add(coins...) 141 return nil 142 }).AnyTimes() 143 bankKeeper.EXPECT().GetAllBalances(gomock.Any(), gomock.Any()).DoAndReturn(func(_ sdk.Context, addr sdk.AccAddress) sdk.Coins { 144 return balances[addr.String()] 145 }).AnyTimes() 146 bankKeeper.EXPECT().GetBalance(gomock.Any(), gomock.Any(), sdk.DefaultBondDenom).DoAndReturn(func(_ sdk.Context, addr sdk.AccAddress, _ string) sdk.Coin { 147 balances := balances[addr.String()] 148 for _, balance := range balances { 149 if balance.Denom == sdk.DefaultBondDenom { 150 return balance 151 } 152 } 153 return sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(0)) 154 }).AnyTimes() 155 156 distributionKeeper.EXPECT().FundCommunityPool(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ sdk.Context, coins sdk.Coins, sender sdk.AccAddress) error { 157 // sender balance 158 newBalance, negative := balances[sender.String()].SafeSub(coins...) 159 if negative { 160 return fmt.Errorf("not enough balance") 161 } 162 balances[sender.String()] = newBalance 163 // receiver balance 164 balances[distAcct.String()] = balances[distAcct.String()].Add(coins...) 165 return nil 166 }).AnyTimes() 167 }