package keeper_test import ( "strings" "testing" "time" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/stretchr/testify/suite" "github.com/kava-labs/kava/x/community/keeper" "github.com/kava-labs/kava/x/community/testutil" "github.com/kava-labs/kava/x/community/types" ) // Test suite used for all keeper tests type KeeperTestSuite struct { testutil.Suite } // The default state used by each test func (suite *KeeperTestSuite) SetupTest() { suite.Suite.SetupTest() } func TestKeeperTestSuite(t *testing.T) { suite.Run(t, new(KeeperTestSuite)) } func (suite *KeeperTestSuite) TestCommunityPool() { suite.SetupTest() maccAddr := suite.App.GetAccountKeeper().GetModuleAddress(types.ModuleAccountName) funds := sdk.NewCoins( sdk.NewCoin("ukava", sdkmath.NewInt(10000)), sdk.NewCoin("usdx", sdkmath.NewInt(100)), ) sender := suite.CreateFundedAccount(funds) suite.Run("FundCommunityPool", func() { err := suite.Keeper.FundCommunityPool(suite.Ctx, sender, funds) suite.Require().NoError(err) // check that community pool received balance suite.App.CheckBalance(suite.T(), suite.Ctx, maccAddr, funds) suite.Equal(funds, suite.Keeper.GetModuleAccountBalance(suite.Ctx)) // check that sender had balance deducted suite.App.CheckBalance(suite.T(), suite.Ctx, sender, sdk.NewCoins()) }) // send it back suite.Run("DistributeFromCommunityPool - valid", func() { err := suite.Keeper.DistributeFromCommunityPool(suite.Ctx, sender, funds) suite.Require().NoError(err) // community pool has funds deducted suite.App.CheckBalance(suite.T(), suite.Ctx, maccAddr, sdk.NewCoins()) suite.Equal(sdk.NewCoins(), suite.Keeper.GetModuleAccountBalance(suite.Ctx)) // receiver receives the funds suite.App.CheckBalance(suite.T(), suite.Ctx, sender, funds) }) // can't send more than we have! suite.Run("DistributeFromCommunityPool - insufficient funds", func() { suite.Equal(sdk.NewCoins(), suite.Keeper.GetModuleAccountBalance(suite.Ctx)) err := suite.Keeper.DistributeFromCommunityPool(suite.Ctx, sender, funds) suite.Require().ErrorContains(err, "insufficient funds") }) } func (suite *KeeperTestSuite) TestGetAndSetStakingRewardsState() { keeper := suite.Keeper defaultParams := keeper.GetStakingRewardsState(suite.Ctx) suite.Equal(time.Time{}, defaultParams.LastAccumulationTime, "expected default returned accumulation time to be zero") suite.Equal(sdkmath.LegacyZeroDec(), defaultParams.LastTruncationError, "expected default truncation error to be zero") suite.NotPanics(func() { keeper.SetStakingRewardsState(suite.Ctx, defaultParams) }, "expected setting default state to not panic") invalidParams := defaultParams invalidParams.LastTruncationError = sdkmath.LegacyDec{} suite.Panics(func() { keeper.SetStakingRewardsState(suite.Ctx, invalidParams) }, "expected setting invalid state to panic") validParams := defaultParams validParams.LastAccumulationTime = time.Date(2023, 9, 29, 11, 42, 53, 123456789, time.UTC) validParams.LastTruncationError = sdkmath.LegacyMustNewDecFromStr("0.50000000000000000") suite.NotPanics(func() { keeper.SetStakingRewardsState(suite.Ctx, validParams) }, "expected setting valid state to not panic") suite.Equal(validParams, keeper.GetStakingRewardsState(suite.Ctx), "expected fetched state to equal set state") } func (suite *KeeperTestSuite) TestGetAuthority_Default() { suite.Equal( authtypes.NewModuleAddress(govtypes.ModuleName), suite.Keeper.GetAuthority(), "expected fetched authority to equal x/gov address", ) } func (suite *KeeperTestSuite) TestGetAuthority_Any() { tests := []struct { name string authority sdk.AccAddress }{ { name: "gov", authority: authtypes.NewModuleAddress(govtypes.ModuleName), }, { name: "random", authority: sdk.AccAddress("random"), }, } for _, tc := range tests { suite.Run(tc.name, func() { suite.NotPanics(func() { suite.Keeper = keeper.NewKeeper( suite.App.AppCodec(), suite.App.GetKVStoreKey(types.StoreKey), suite.App.GetAccountKeeper(), suite.App.GetBankKeeper(), suite.App.GetCDPKeeper(), suite.App.GetDistrKeeper(), suite.App.GetHardKeeper(), suite.App.GetMintKeeper(), suite.App.GetKavadistKeeper(), suite.App.GetStakingKeeper(), tc.authority, ) }) suite.Equalf( tc.authority, suite.Keeper.GetAuthority(), "expected fetched authority to equal %s address", tc.authority, ) }) } } func (suite *KeeperTestSuite) TestNewKeeper_InvalidAuthority() { tests := []struct { name string authority sdk.AccAddress panicStr string }{ { name: "empty", authority: sdk.AccAddress{}, panicStr: "invalid authority address: addresses cannot be empty: unknown address", }, { name: "too long", authority: sdk.AccAddress(strings.Repeat("a", address.MaxAddrLen+1)), panicStr: "invalid authority address: address max length is 255, got 256: unknown address", }, } for _, tc := range tests { suite.Run(tc.name, func() { suite.PanicsWithValue( tc.panicStr, func() { suite.Keeper = keeper.NewKeeper( suite.App.AppCodec(), suite.App.GetKVStoreKey(types.StoreKey), suite.App.GetAccountKeeper(), suite.App.GetBankKeeper(), suite.App.GetCDPKeeper(), suite.App.GetDistrKeeper(), suite.App.GetHardKeeper(), suite.App.GetMintKeeper(), suite.App.GetKavadistKeeper(), suite.App.GetStakingKeeper(), tc.authority, ) }) }) } }