package keeper_test import ( "context" "fmt" "testing" "github.com/stretchr/testify/suite" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/upgrade" "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) type UpgradeTestSuite struct { suite.Suite upgradeKeeper keeper.Keeper ctx sdk.Context queryClient types.QueryClient encCfg moduletestutil.TestEncodingConfig } func (suite *UpgradeTestSuite) SetupTest() { suite.encCfg = moduletestutil.MakeTestEncodingConfig(upgrade.AppModuleBasic{}) key := sdk.NewKVStoreKey(types.StoreKey) testCtx := testutil.DefaultContextWithDB(suite.T(), key, sdk.NewTransientStoreKey("transient_test")) suite.ctx = testCtx.Ctx skipUpgradeHeights := make(map[int64]bool) suite.upgradeKeeper = keeper.NewKeeper(skipUpgradeHeights, key, suite.encCfg.Codec, "", nil, authtypes.NewModuleAddress(govtypes.ModuleName).String()) suite.upgradeKeeper.SetModuleVersionMap(suite.ctx, module.VersionMap{ "bank": 0, }) queryHelper := baseapp.NewQueryServerTestHelper(testCtx.Ctx, suite.encCfg.InterfaceRegistry) types.RegisterQueryServer(queryHelper, suite.upgradeKeeper) suite.queryClient = types.NewQueryClient(queryHelper) } func (suite *UpgradeTestSuite) TestQueryCurrentPlan() { var ( req *types.QueryCurrentPlanRequest expResponse types.QueryCurrentPlanResponse ) testCases := []struct { msg string malleate func() expPass bool }{ { "without current upgrade plan", func() { req = &types.QueryCurrentPlanRequest{} expResponse = types.QueryCurrentPlanResponse{} }, true, }, { "with current upgrade plan", func() { plan := types.Plan{Name: "test-plan", Height: 5} suite.upgradeKeeper.ScheduleUpgrade(suite.ctx, plan) req = &types.QueryCurrentPlanRequest{} expResponse = types.QueryCurrentPlanResponse{Plan: &plan} }, true, }, } for _, tc := range testCases { suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { suite.SetupTest() // reset tc.malleate() res, err := suite.queryClient.CurrentPlan(context.Background(), req) if tc.expPass { suite.Require().NoError(err) suite.Require().NotNil(res) suite.Require().Equal(&expResponse, res) } else { suite.Require().Error(err) } }) } } func (suite *UpgradeTestSuite) TestAppliedCurrentPlan() { var ( req *types.QueryAppliedPlanRequest expHeight int64 ) testCases := []struct { msg string malleate func() expPass bool }{ { "with non-existent upgrade plan", func() { req = &types.QueryAppliedPlanRequest{Name: "foo"} }, true, }, { "with applied upgrade plan", func() { expHeight = 5 planName := "test-plan" plan := types.Plan{Name: planName, Height: expHeight} suite.upgradeKeeper.ScheduleUpgrade(suite.ctx, plan) suite.ctx = suite.ctx.WithBlockHeight(expHeight) suite.upgradeKeeper.SetUpgradeHandler(planName, func(ctx sdk.Context, plan types.Plan, vm module.VersionMap) (module.VersionMap, error) { return vm, nil }) suite.upgradeKeeper.ApplyUpgrade(suite.ctx, plan) req = &types.QueryAppliedPlanRequest{Name: planName} }, true, }, } for _, tc := range testCases { suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { suite.SetupTest() // reset tc.malleate() res, err := suite.queryClient.AppliedPlan(context.Background(), req) if tc.expPass { suite.Require().NoError(err) suite.Require().NotNil(res) suite.Require().Equal(expHeight, res.Height) } else { suite.Require().Error(err) } }) } } func (suite *UpgradeTestSuite) TestModuleVersions() { testCases := []struct { msg string req types.QueryModuleVersionsRequest single bool expPass bool }{ { msg: "test full query", req: types.QueryModuleVersionsRequest{}, single: false, expPass: true, }, { msg: "test single module", req: types.QueryModuleVersionsRequest{ModuleName: "bank"}, single: true, expPass: true, }, { msg: "test non-existent module", req: types.QueryModuleVersionsRequest{ModuleName: "abcdefg"}, single: true, expPass: false, }, } vm := suite.upgradeKeeper.GetModuleVersionMap(suite.ctx) mv := suite.upgradeKeeper.GetModuleVersions(suite.ctx) for _, tc := range testCases { suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { suite.SetupTest() // reset res, err := suite.queryClient.ModuleVersions(context.Background(), &tc.req) if tc.expPass { suite.Require().NoError(err) suite.Require().NotNil(res) if tc.single { // test that the single module response is valid suite.Require().Len(res.ModuleVersions, 1) // make sure we got the right values suite.Require().Equal(vm[tc.req.ModuleName], res.ModuleVersions[0].Version) suite.Require().Equal(tc.req.ModuleName, res.ModuleVersions[0].Name) } else { // check that the full response is valid suite.Require().NotEmpty(res.ModuleVersions) suite.Require().Equal(len(mv), len(res.ModuleVersions)) for i, v := range res.ModuleVersions { suite.Require().Equal(mv[i].Version, v.Version) suite.Require().Equal(mv[i].Name, v.Name) } } } else { suite.Require().Error(err) } }) } } func (suite *UpgradeTestSuite) TestAuthority() { res, err := suite.queryClient.Authority(context.Background(), &types.QueryAuthorityRequest{}) suite.Require().NoError(err) suite.Require().Equal(authtypes.NewModuleAddress(govtypes.ModuleName).String(), res.Address) } func TestUpgradeTestSuite(t *testing.T) { suite.Run(t, new(UpgradeTestSuite)) }