2019-11-19 12:54:31 -08:00
|
|
|
package upgrade_test
|
2019-11-08 06:40:56 -08:00
|
|
|
|
|
|
|
import (
|
2019-12-27 09:57:54 -08:00
|
|
|
"errors"
|
2019-11-08 06:40:56 -08:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2019-11-19 12:54:31 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/simapp"
|
2019-11-08 06:40:56 -08:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2019-12-27 09:57:54 -08:00
|
|
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
2019-11-08 06:40:56 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/types/module"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/gov"
|
2019-11-19 12:54:31 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/upgrade"
|
2019-11-08 06:40:56 -08:00
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
type TestSuite struct {
|
|
|
|
suite.Suite
|
2019-11-19 12:54:31 -08:00
|
|
|
|
|
|
|
module module.AppModule
|
|
|
|
keeper upgrade.Keeper
|
2019-11-08 06:40:56 -08:00
|
|
|
querier sdk.Querier
|
|
|
|
handler gov.Handler
|
|
|
|
ctx sdk.Context
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) SetupTest() {
|
2019-11-19 12:54:31 -08:00
|
|
|
checkTx := false
|
|
|
|
app := simapp.Setup(checkTx)
|
|
|
|
|
|
|
|
s.keeper = app.UpgradeKeeper
|
|
|
|
s.handler = upgrade.NewSoftwareUpgradeProposalHandler(s.keeper)
|
|
|
|
s.querier = upgrade.NewQuerier(s.keeper)
|
|
|
|
s.ctx = app.BaseApp.NewContext(checkTx, abci.Header{Height: 10, Time: time.Now()})
|
|
|
|
s.module = upgrade.NewAppModule(s.keeper)
|
2019-11-08 06:40:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestRequireName() {
|
2019-11-19 12:54:31 -08:00
|
|
|
err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{}})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().NotNil(err)
|
2019-12-27 09:57:54 -08:00
|
|
|
s.Require().True(errors.Is(sdkerrors.ErrInvalidRequest, err), err)
|
2019-11-08 06:40:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestRequireFutureTime() {
|
2019-11-19 12:54:31 -08:00
|
|
|
err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Time: s.ctx.BlockHeader().Time}})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().NotNil(err)
|
2019-12-27 09:57:54 -08:00
|
|
|
s.Require().True(errors.Is(sdkerrors.ErrInvalidRequest, err), err)
|
2019-11-08 06:40:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestRequireFutureBlock() {
|
2019-11-19 12:54:31 -08:00
|
|
|
err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Height: s.ctx.BlockHeight()}})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().NotNil(err)
|
2019-12-27 09:57:54 -08:00
|
|
|
s.Require().True(errors.Is(sdkerrors.ErrInvalidRequest, err), err)
|
2019-11-08 06:40:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestCantSetBothTimeAndHeight() {
|
2019-11-19 12:54:31 -08:00
|
|
|
err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Time: time.Now(), Height: s.ctx.BlockHeight() + 1}})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().NotNil(err)
|
2019-12-27 09:57:54 -08:00
|
|
|
s.Require().True(errors.Is(sdkerrors.ErrInvalidRequest, err), err)
|
2019-11-08 06:40:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestDoTimeUpgrade() {
|
|
|
|
s.T().Log("Verify can schedule an upgrade")
|
2019-11-19 12:54:31 -08:00
|
|
|
err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Time: time.Now()}})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().Nil(err)
|
|
|
|
|
|
|
|
s.VerifyDoUpgrade()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestDoHeightUpgrade() {
|
|
|
|
s.T().Log("Verify can schedule an upgrade")
|
2019-11-19 12:54:31 -08:00
|
|
|
err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Height: s.ctx.BlockHeight() + 1}})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().Nil(err)
|
|
|
|
|
|
|
|
s.VerifyDoUpgrade()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestCanOverwriteScheduleUpgrade() {
|
|
|
|
s.T().Log("Can overwrite plan")
|
2019-11-19 12:54:31 -08:00
|
|
|
err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "bad_test", Height: s.ctx.BlockHeight() + 10}})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().Nil(err)
|
2019-11-19 12:54:31 -08:00
|
|
|
err = s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Height: s.ctx.BlockHeight() + 1}})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().Nil(err)
|
|
|
|
|
|
|
|
s.VerifyDoUpgrade()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) VerifyDoUpgrade() {
|
|
|
|
s.T().Log("Verify that a panic happens at the upgrade time/height")
|
2019-11-19 12:54:31 -08:00
|
|
|
newCtx := s.ctx.WithBlockHeight(s.ctx.BlockHeight() + 1).WithBlockTime(time.Now())
|
|
|
|
|
2019-11-08 06:40:56 -08:00
|
|
|
req := abci.RequestBeginBlock{Header: newCtx.BlockHeader()}
|
|
|
|
s.Require().Panics(func() {
|
|
|
|
s.module.BeginBlock(newCtx, req)
|
|
|
|
})
|
|
|
|
|
|
|
|
s.T().Log("Verify that the upgrade can be successfully applied with a handler")
|
2019-11-19 12:54:31 -08:00
|
|
|
s.keeper.SetUpgradeHandler("test", func(ctx sdk.Context, plan upgrade.Plan) {})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().NotPanics(func() {
|
|
|
|
s.module.BeginBlock(newCtx, req)
|
|
|
|
})
|
|
|
|
|
|
|
|
s.VerifyCleared(newCtx)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestHaltIfTooNew() {
|
|
|
|
s.T().Log("Verify that we don't panic with registered plan not in database at all")
|
|
|
|
var called int
|
2019-11-19 12:54:31 -08:00
|
|
|
s.keeper.SetUpgradeHandler("future", func(ctx sdk.Context, plan upgrade.Plan) { called++ })
|
2019-11-08 06:40:56 -08:00
|
|
|
|
2019-11-19 12:54:31 -08:00
|
|
|
newCtx := s.ctx.WithBlockHeight(s.ctx.BlockHeight() + 1).WithBlockTime(time.Now())
|
2019-11-08 06:40:56 -08:00
|
|
|
req := abci.RequestBeginBlock{Header: newCtx.BlockHeader()}
|
|
|
|
s.Require().NotPanics(func() {
|
|
|
|
s.module.BeginBlock(newCtx, req)
|
|
|
|
})
|
|
|
|
s.Require().Equal(0, called)
|
|
|
|
|
|
|
|
s.T().Log("Verify we panic if we have a registered handler ahead of time")
|
2019-11-19 12:54:31 -08:00
|
|
|
err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "future", Height: s.ctx.BlockHeight() + 3}})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Panics(func() {
|
|
|
|
s.module.BeginBlock(newCtx, req)
|
|
|
|
})
|
|
|
|
s.Require().Equal(0, called)
|
|
|
|
|
|
|
|
s.T().Log("Verify we no longer panic if the plan is on time")
|
|
|
|
|
2019-11-19 12:54:31 -08:00
|
|
|
futCtx := s.ctx.WithBlockHeight(s.ctx.BlockHeight() + 3).WithBlockTime(time.Now())
|
2019-11-08 06:40:56 -08:00
|
|
|
req = abci.RequestBeginBlock{Header: futCtx.BlockHeader()}
|
|
|
|
s.Require().NotPanics(func() {
|
|
|
|
s.module.BeginBlock(futCtx, req)
|
|
|
|
})
|
|
|
|
s.Require().Equal(1, called)
|
|
|
|
|
|
|
|
s.VerifyCleared(futCtx)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) VerifyCleared(newCtx sdk.Context) {
|
|
|
|
s.T().Log("Verify that the upgrade plan has been cleared")
|
2019-11-19 12:54:31 -08:00
|
|
|
bz, err := s.querier(newCtx, []string{upgrade.QueryCurrent}, abci.RequestQuery{})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Nil(bz)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestCanClear() {
|
|
|
|
s.T().Log("Verify upgrade is scheduled")
|
2019-11-19 12:54:31 -08:00
|
|
|
err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Time: time.Now()}})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().Nil(err)
|
|
|
|
|
2019-11-19 12:54:31 -08:00
|
|
|
s.handler(s.ctx, upgrade.CancelSoftwareUpgradeProposal{Title: "cancel"})
|
2019-11-08 06:40:56 -08:00
|
|
|
|
|
|
|
s.VerifyCleared(s.ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestCantApplySameUpgradeTwice() {
|
|
|
|
s.TestDoTimeUpgrade()
|
|
|
|
s.T().Log("Verify an upgrade named \"test\" can't be scheduled twice")
|
2019-11-19 12:54:31 -08:00
|
|
|
err := s.handler(s.ctx, upgrade.SoftwareUpgradeProposal{Title: "prop", Plan: upgrade.Plan{Name: "test", Time: time.Now()}})
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().NotNil(err)
|
2019-12-27 09:57:54 -08:00
|
|
|
s.Require().True(errors.Is(sdkerrors.ErrInvalidRequest, err), err)
|
2019-11-08 06:40:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestNoSpuriousUpgrades() {
|
|
|
|
s.T().Log("Verify that no upgrade panic is triggered in the BeginBlocker when we haven't scheduled an upgrade")
|
|
|
|
req := abci.RequestBeginBlock{Header: s.ctx.BlockHeader()}
|
|
|
|
s.Require().NotPanics(func() {
|
|
|
|
s.module.BeginBlock(s.ctx, req)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *TestSuite) TestPlanStringer() {
|
|
|
|
t, err := time.Parse(time.RFC3339, "2020-01-01T00:00:00Z")
|
|
|
|
s.Require().Nil(err)
|
|
|
|
s.Require().Equal(`Upgrade Plan
|
|
|
|
Name: test
|
|
|
|
Time: 2020-01-01T00:00:00Z
|
2019-11-19 12:54:31 -08:00
|
|
|
Info: `, upgrade.Plan{Name: "test", Time: t}.String())
|
2019-11-08 06:40:56 -08:00
|
|
|
s.Require().Equal(`Upgrade Plan
|
|
|
|
Name: test
|
|
|
|
Height: 100
|
2019-11-19 12:54:31 -08:00
|
|
|
Info: `, upgrade.Plan{Name: "test", Height: 100}.String())
|
2019-11-08 06:40:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTestSuite(t *testing.T) {
|
|
|
|
suite.Run(t, new(TestSuite))
|
|
|
|
}
|