cosmos-sdk/x/gov/endblocker_test.go

335 lines
12 KiB
Go

package gov
import (
"testing"
"time"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking"
)
func TestTickExpiredDepositPeriod(t *testing.T) {
input := getMockApp(t, 10, GenesisState{}, nil)
header := abci.Header{Height: input.mApp.LastBlockHeight() + 1}
input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header})
ctx := input.mApp.BaseApp.NewContext(false, abci.Header{})
govHandler := NewHandler(input.keeper)
inactiveQueue := input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newProposalMsg := NewMsgSubmitProposal(
ContentFromProposalType("test", "test", ProposalTypeText),
sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)},
input.addrs[0],
)
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newHeader := ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newHeader = ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod)
ctx = ctx.WithBlockHeader(newHeader)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.True(t, inactiveQueue.Valid())
inactiveQueue.Close()
EndBlocker(ctx, input.keeper)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
}
func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
input := getMockApp(t, 10, GenesisState{}, nil)
header := abci.Header{Height: input.mApp.LastBlockHeight() + 1}
input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header})
ctx := input.mApp.BaseApp.NewContext(false, abci.Header{})
govHandler := NewHandler(input.keeper)
inactiveQueue := input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newProposalMsg := NewMsgSubmitProposal(
ContentFromProposalType("test", "test", ProposalTypeText),
sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)},
input.addrs[0],
)
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newHeader := ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newProposalMsg2 := NewMsgSubmitProposal(
ContentFromProposalType("test2", "test2", ProposalTypeText),
sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)},
input.addrs[0],
)
res = govHandler(ctx, newProposalMsg2)
require.True(t, res.IsOK())
newHeader = ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.True(t, inactiveQueue.Valid())
inactiveQueue.Close()
EndBlocker(ctx, input.keeper)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newHeader = ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.True(t, inactiveQueue.Valid())
inactiveQueue.Close()
EndBlocker(ctx, input.keeper)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
}
func TestTickPassedDepositPeriod(t *testing.T) {
input := getMockApp(t, 10, GenesisState{}, nil)
header := abci.Header{Height: input.mApp.LastBlockHeight() + 1}
input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header})
ctx := input.mApp.BaseApp.NewContext(false, abci.Header{})
govHandler := NewHandler(input.keeper)
inactiveQueue := input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
activeQueue := input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, activeQueue.Valid())
activeQueue.Close()
newProposalMsg := NewMsgSubmitProposal(
ContentFromProposalType("test2", "test2", ProposalTypeText),
sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)},
input.addrs[0],
)
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
var proposalID uint64
input.keeper.cdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &proposalID)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newHeader := ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
newDepositMsg := NewMsgDeposit(input.addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)})
res = govHandler(ctx, newDepositMsg)
require.True(t, res.IsOK())
activeQueue = input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, activeQueue.Valid())
activeQueue.Close()
}
func TestTickPassedVotingPeriod(t *testing.T) {
input := getMockApp(t, 10, GenesisState{}, nil)
SortAddresses(input.addrs)
header := abci.Header{Height: input.mApp.LastBlockHeight() + 1}
input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header})
ctx := input.mApp.BaseApp.NewContext(false, abci.Header{})
govHandler := NewHandler(input.keeper)
inactiveQueue := input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
activeQueue := input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, activeQueue.Valid())
activeQueue.Close()
proposalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(5))}
newProposalMsg := NewMsgSubmitProposal(testProposal(), proposalCoins, input.addrs[0])
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
var proposalID uint64
input.keeper.cdc.MustUnmarshalBinaryLengthPrefixed(res.Data, &proposalID)
newHeader := ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)
newDepositMsg := NewMsgDeposit(input.addrs[1], proposalID, proposalCoins)
res = govHandler(ctx, newDepositMsg)
require.True(t, res.IsOK())
newHeader = ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(input.keeper.GetVotingParams(ctx).VotingPeriod)
ctx = ctx.WithBlockHeader(newHeader)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
inactiveQueue.Close()
activeQueue = input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.True(t, activeQueue.Valid())
var activeProposalID uint64
require.NoError(t, input.keeper.cdc.UnmarshalBinaryLengthPrefixed(activeQueue.Value(), &activeProposalID))
proposal, ok := input.keeper.GetProposal(ctx, activeProposalID)
require.True(t, ok)
require.Equal(t, StatusVotingPeriod, proposal.Status)
depositsIterator := input.keeper.GetDepositsIterator(ctx, proposalID)
require.True(t, depositsIterator.Valid())
depositsIterator.Close()
activeQueue.Close()
EndBlocker(ctx, input.keeper)
activeQueue = input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, activeQueue.Valid())
activeQueue.Close()
}
func TestProposalPassedEndblocker(t *testing.T) {
input := getMockApp(t, 1, GenesisState{}, nil)
SortAddresses(input.addrs)
handler := NewHandler(input.keeper)
stakingHandler := staking.NewHandler(input.sk)
header := abci.Header{Height: input.mApp.LastBlockHeight() + 1}
input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header})
ctx := input.mApp.BaseApp.NewContext(false, abci.Header{})
valAddr := sdk.ValAddress(input.addrs[0])
createValidators(t, stakingHandler, ctx, []sdk.ValAddress{valAddr}, []int64{10})
staking.EndBlocker(ctx, input.sk)
macc := input.keeper.GetGovernanceAccount(ctx)
require.NotNil(t, macc)
initialModuleAccCoins := macc.GetCoins()
proposal, err := input.keeper.SubmitProposal(ctx, testProposal())
require.NoError(t, err)
proposalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(10))}
newDepositMsg := NewMsgDeposit(input.addrs[0], proposal.ProposalID, proposalCoins)
res := handler(ctx, newDepositMsg)
require.True(t, res.IsOK())
macc = input.keeper.GetGovernanceAccount(ctx)
require.NotNil(t, macc)
moduleAccCoins := macc.GetCoins()
deposits := initialModuleAccCoins.Add(proposal.TotalDeposit).Add(proposalCoins)
require.True(t, moduleAccCoins.IsEqual(deposits))
err = input.keeper.AddVote(ctx, proposal.ProposalID, input.addrs[0], OptionYes)
require.NoError(t, err)
newHeader := ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(input.keeper.GetVotingParams(ctx).VotingPeriod)
ctx = ctx.WithBlockHeader(newHeader)
EndBlocker(ctx, input.keeper)
macc = input.keeper.GetGovernanceAccount(ctx)
require.NotNil(t, macc)
require.True(t, macc.GetCoins().IsEqual(initialModuleAccCoins))
}
func TestEndBlockerProposalHandlerFailed(t *testing.T) {
input := getMockApp(t, 1, GenesisState{}, nil)
SortAddresses(input.addrs)
// hijack the router to one that will fail in a proposal's handler
input.keeper.router = NewRouter().AddRoute(RouterKey, badProposalHandler)
handler := NewHandler(input.keeper)
stakingHandler := staking.NewHandler(input.sk)
header := abci.Header{Height: input.mApp.LastBlockHeight() + 1}
input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header})
ctx := input.mApp.BaseApp.NewContext(false, abci.Header{})
valAddr := sdk.ValAddress(input.addrs[0])
createValidators(t, stakingHandler, ctx, []sdk.ValAddress{valAddr}, []int64{10})
staking.EndBlocker(ctx, input.sk)
// Create a proposal where the handler will pass for the test proposal
// because the value of contextKeyBadProposal is true.
ctx = ctx.WithValue(contextKeyBadProposal, true)
proposal, err := input.keeper.SubmitProposal(ctx, testProposal())
require.NoError(t, err)
proposalCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(10)))
newDepositMsg := NewMsgDeposit(input.addrs[0], proposal.ProposalID, proposalCoins)
res := handler(ctx, newDepositMsg)
require.True(t, res.IsOK())
err = input.keeper.AddVote(ctx, proposal.ProposalID, input.addrs[0], OptionYes)
require.NoError(t, err)
newHeader := ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(input.keeper.GetVotingParams(ctx).VotingPeriod)
ctx = ctx.WithBlockHeader(newHeader)
// Set the contextKeyBadProposal value to false so that the handler will fail
// during the processing of the proposal in the EndBlocker.
ctx = ctx.WithValue(contextKeyBadProposal, false)
// validate that the proposal fails/has been rejected
EndBlocker(ctx, input.keeper)
}