Skip to content

Commit

Permalink
Merge PR cosmos#4448: Implement Gov EndBlocker Failed Handler Test
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderbez authored May 30, 2019
1 parent b44392b commit 2414413
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
47 changes: 47 additions & 0 deletions x/gov/endblocker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,50 @@ func TestProposalPassedEndblocker(t *testing.T) {
resTags := EndBlocker(ctx, input.keeper)
require.Equal(t, sdk.MakeTag(tags.ProposalResult, tags.ActionProposalPassed), resTags[1])
}

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])

input.keeper.ck.SetSendEnabled(ctx, true)
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.TokensFromTendermintPower(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
resTags := EndBlocker(ctx, input.keeper)
require.Equal(t, sdk.MakeTag(tags.ProposalResult, tags.ActionProposalFailed), resTags[1])
}
23 changes: 23 additions & 0 deletions x/gov/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gov

import (
"bytes"
"fmt"
"log"
"sort"
"testing"
Expand Down Expand Up @@ -155,6 +156,28 @@ func testProposal() Content {
return NewTextProposal("Test", "description")
}

const contextKeyBadProposal = "contextKeyBadProposal"

// badProposalHandler implements a governance proposal handler that is identical
// to the actual handler except this fails if the context doesn't contain a value
// for the key contextKeyBadProposal or if the value is false.
func badProposalHandler(ctx sdk.Context, c Content) sdk.Error {
switch c.ProposalType() {
case ProposalTypeText, ProposalTypeSoftwareUpgrade:
v := ctx.Value(contextKeyBadProposal)

if v == nil || !v.(bool) {
return sdk.ErrInternal("proposal failed")
}

return nil

default:
errMsg := fmt.Sprintf("unrecognized gov proposal type: %s", c.ProposalType())
return sdk.ErrUnknownRequest(errMsg)
}
}

// checks if two proposals are equal (note: slow, for tests only)
func ProposalEqual(proposalA Proposal, proposalB Proposal) bool {
return bytes.Equal(types.ModuleCdc.MustMarshalBinaryBare(proposalA),
Expand Down

0 comments on commit 2414413

Please sign in to comment.