Skip to content

Commit

Permalink
test: move provider hooks tests to integration tests (#1816)
Browse files Browse the repository at this point in the history
tests: add provider gov hooks integration tests
  • Loading branch information
MSalopek authored Apr 24, 2024
1 parent c866fe2 commit 7cd900a
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 139 deletions.
5 changes: 5 additions & 0 deletions app/provider/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,11 @@ func (app *App) GetTestAccountKeeper() testutil.TestAccountKeeper {
return app.AccountKeeper
}

// GetTestGovKeeper implements the ProviderApp interface.
func (app *App) GetTestGovKeeper() *govkeeper.Keeper {
return app.GovKeeper
}

// TestingApp functions

// GetBaseApp implements the TestingApp interface.
Expand Down
149 changes: 149 additions & 0 deletions tests/integration/provider_gov_hooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package integration

import (
"time"

"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"

testkeeper "github.com/cosmos/interchain-security/v5/testutil/keeper"
)

// tests AfterProposalSubmission and AfterProposalVotingPeriodEnded hooks
// hooks require adding a proposal in the gov module and regitering a consumer chain with the provider module
func (s *CCVTestSuite) TestAfterPropSubmissionAndVotingPeriodEnded() {
ctx := s.providerChain.GetContext()
providerKeeper := s.providerApp.GetProviderKeeper()
govKeeper := s.providerApp.GetTestGovKeeper()
proposer := s.providerChain.SenderAccount

content := testkeeper.GetTestConsumerAdditionProp()
content.ChainId = "newchain-0"
legacyPropContent, err := v1.NewLegacyContent(
content,
authtypes.NewModuleAddress("gov").String(),
)
s.Require().NoError(err)

proposal, err := v1.NewProposal([]sdk.Msg{legacyPropContent}, 1, time.Now(), time.Now().Add(1*time.Hour), "metadata", "title", "summary", proposer.GetAddress(), false)
s.Require().NoError(err)

err = govKeeper.SetProposal(ctx, proposal)
s.Require().NoError(err)

providerKeeper.Hooks().AfterProposalSubmission(ctx, proposal.Id)

// verify that the proposal ID is created
proposalIdOnProvider := providerKeeper.GetProposedConsumerChain(ctx, proposal.Id)
s.Require().NotEmpty(proposalIdOnProvider)
s.Require().Equal(content.ChainId, proposalIdOnProvider)

providerKeeper.Hooks().AfterProposalVotingPeriodEnded(ctx, proposal.Id)
// verify that the proposal ID is deleted
s.Require().Empty(providerKeeper.GetProposedConsumerChain(ctx, proposal.Id))
}

func (s *CCVTestSuite) TestGetConsumerAdditionLegacyPropFromProp() {
ctx := s.providerChain.GetContext()
proposer := s.providerChain.SenderAccount

// create a dummy bank send message
dummyMsg := &banktypes.MsgSend{
FromAddress: sdk.AccAddress(proposer.GetAddress()).String(),
ToAddress: sdk.AccAddress(proposer.GetAddress()).String(),
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.OneInt())),
}

textProp, err := v1.NewLegacyContent(
v1beta1.NewTextProposal("a title", "a legacy text prop"),
authtypes.NewModuleAddress("gov").String(),
)
s.Require().NoError(err)

addConsumerProp, err := v1.NewLegacyContent(
testkeeper.GetTestConsumerAdditionProp(),
authtypes.NewModuleAddress("gov").String(),
)
s.Require().NoError(err)

testCases := []struct {
name string
propMsg sdk.Msg
expectConsumerPropFound bool
expPanic bool
}{
{
name: "prop not found",
propMsg: nil,
expectConsumerPropFound: false,
expPanic: false,
},
{
name: "msgs in prop contain no legacy props",
propMsg: dummyMsg,
expectConsumerPropFound: false,
expPanic: false,
},
{
name: "msgs contain a legacy prop but not of ConsumerAdditionProposal type",
propMsg: textProp,
expectConsumerPropFound: false,
},
{
name: "msgs contain an invalid legacy prop",
propMsg: &v1.MsgExecLegacyContent{},
expectConsumerPropFound: false,
expPanic: true,
},
{
name: "msg contains a prop of ConsumerAdditionProposal type - hook should create a new proposed chain",
propMsg: addConsumerProp,
expectConsumerPropFound: true,
expPanic: false,
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
providerKeeper := s.providerApp.GetProviderKeeper()
govKeeper := s.providerApp.GetTestGovKeeper()

var proposal v1.Proposal
var err error

if tc.propMsg == nil {
// cover edgecase where proposal has no messages
proposal, err = v1.NewProposal([]sdk.Msg{}, 1, time.Now(), time.Now().Add(1*time.Hour), "metadata", "title", "summary", proposer.GetAddress(), false)
s.Require().NoError(err)
} else {
// cover variolus cases where proposal has messages but only some are consumer addition proposals
proposal, err = v1.NewProposal([]sdk.Msg{tc.propMsg}, 1, time.Now(), time.Now().Add(1*time.Hour), "metadata", "title", "summary", proposer.GetAddress(), false)
s.Require().NoError(err)
}

err = govKeeper.SetProposal(ctx, proposal)
s.Require().NoError(err)

if tc.expPanic {
s.Require().Panics(func() {
// this panics with a nil pointer dereference because the proposal is invalid and cannot be unmarshalled
providerKeeper.Hooks().GetConsumerAdditionLegacyPropFromProp(ctx, proposal.Id)
})
return
}

savedProp, found := providerKeeper.Hooks().GetConsumerAdditionLegacyPropFromProp(ctx, proposal.Id)
if tc.expectConsumerPropFound {
s.Require().True(found)
s.Require().NotEmpty(savedProp, savedProp)
} else {
s.Require().False(found)
s.Require().Empty(savedProp)
}
})
}
}
13 changes: 13 additions & 0 deletions testutil/integration/debug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ func TestHandleConsumerDoubleVotingSlashesUndelegationsAndRelegations(t *testing
runCCVTestByName(t, "TestHandleConsumerDoubleVotingSlashesUndelegationsAndRelegations")
}

//
// Throttle retry tests
//

Expand All @@ -291,3 +292,15 @@ func TestSlashRetries(t *testing.T) {
func TestKeyAssignment(t *testing.T) {
runCCVTestByName(t, "TestKeyAssignment")
}

//
// Provider gov hooks test
//

func TestAfterPropSubmissionAndVotingPeriodEnded(t *testing.T) {
runCCVTestByName(t, "TestAfterPropSubmissionAndVotingPeriodEnded")
}

func TestGetConsumerAdditionLegacyPropFromProp(t *testing.T) {
runCCVTestByName(t, "TestGetConsumerAdditionLegacyPropFromProp")
}
2 changes: 1 addition & 1 deletion testutil/integration/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type ProviderApp interface {
// Returns an account keeper interface with more capabilities than the expected_keepers interface
GetTestAccountKeeper() TestAccountKeeper

// GetTestGovKeeper() govkeeper.Keeper
GetTestGovKeeper() *govkeeper.Keeper
}

// The interface that any consumer app must implement to be compatible with integration tests
Expand Down
138 changes: 0 additions & 138 deletions x/ccv/provider/keeper/hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,141 +81,3 @@ func TestValidatorConsensusKeyInUse(t *testing.T) {
})
}
}

// TODO: move to integration tests
// func TestAfterPropSubmissionAndVotingPeriodEnded(t *testing.T) {
// acct := cryptotestutil.NewCryptoIdentityFromIntSeed(0)

// propMsg, err := v1.NewLegacyContent(
// testkeeper.GetTestConsumerAdditionProp(),
// authtypes.NewModuleAddress("gov").String(),
// )
// require.NoError(t, err)

// prop, err := v1.NewProposal(
// []sdk.Msg{propMsg},
// 0,
// time.Now(),
// time.Now(),
// "",
// "",
// "",
// sdk.AccAddress(acct.SDKValOpAddress()),
// false, // proposal not expedited
// )
// require.NoError(t, err)

// k, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
// defer ctrl.Finish()

// // TODO: not sure how to ho about fetching props on the mock
// // pass the prop to the mocked gov keeper,
// // which is called by both the AfterProposalVotingPeriodEnded and
// // AfterProposalSubmission gov hooks
// // gomock.InOrder(
// // mocks.MockGovKeeper.EXPECT().GetProposal(ctx, prop.Id).Return(prop, true).Times(2),
// // )

// k.Hooks().AfterProposalSubmission(ctx, prop.Id)
// // verify that the proposal ID is created
// require.NotEmpty(t, k.GetProposedConsumerChain(ctx, prop.Id))

// k.Hooks().AfterProposalVotingPeriodEnded(ctx, prop.Id)
// // verify that the proposal ID is deleted
// require.Empty(t, k.GetProposedConsumerChain(ctx, prop.Id))
// }

// func TestGetConsumerAdditionLegacyPropFromProp(t *testing.T) {
// acct := cryptotestutil.NewCryptoIdentityFromIntSeed(0)
// anotherAcct := cryptotestutil.NewCryptoIdentityFromIntSeed(1)

// // create a dummy bank send message
// dummyMsg := &banktypes.MsgSend{
// FromAddress: sdk.AccAddress(acct.SDKValOpAddress()).String(),
// ToAddress: sdk.AccAddress(anotherAcct.SDKValOpAddress()).String(),
// Amount: sdk.NewCoins(sdk.NewCoin("stake", math.OneInt())),
// }

// textProp, err := v1.NewLegacyContent(
// v1beta1.NewTextProposal("a title", "a legacy text prop"),
// authtypes.NewModuleAddress("gov").String(),
// )
// require.NoError(t, err)

// consuProp, err := v1.NewLegacyContent(
// testkeeper.GetTestConsumerAdditionProp(),
// authtypes.NewModuleAddress("gov").String(),
// )
// require.NoError(t, err)

// testCases := map[string]struct {
// propMsg sdk.Msg
// // setup func(sdk.Context, k providerkeeper, proposalID uint64)
// expPanic bool
// expConsuAddProp bool
// }{
// "prop not found": {
// propMsg: nil,
// expPanic: true,
// },
// "msgs in prop contain no legacy props": {
// propMsg: dummyMsg,
// },
// "msgs contain a legacy prop but not of ConsumerAdditionProposal type": {
// propMsg: textProp,
// },
// "msgs contain an invalid legacy prop": {
// propMsg: &v1.MsgExecLegacyContent{},
// expPanic: true,
// },
// "msg contains a prop of ConsumerAdditionProposal type - hook should create a new proposed chain": {
// propMsg: consuProp,
// expConsuAddProp: true,
// },
// }

// for name, tc := range testCases {
// t.Run(name, func(t *testing.T) {
// k, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
// defer ctrl.Finish()

// var (
// prop v1.Proposal
// // propFound bool
// )

// if tc.propMsg != nil {
// // propFound = true
// prop, err = v1.NewProposal(
// []sdk.Msg{tc.propMsg},
// 0,
// time.Now(),
// time.Now(),
// "",
// "",
// "",
// sdk.AccAddress(acct.SDKValOpAddress()),
// false, // proposal not expedited
// )
// require.NoError(t, err)
// }

// // gomock.InOrder(
// // mocks.MockGovKeeper.EXPECT().GetProposal(ctx, prop.Id).Return(prop, propFound),
// // )

// if tc.expPanic {
// defer func() {
// // fail test if not panic was recovered
// if r := recover(); r == nil {
// require.Fail(t, r.(string))
// }
// }()
// }

// // retrieve consumer addition proposal
// _, ok := k.Hooks().GetConsumerAdditionLegacyPropFromProp(ctx, prop.Id)
// require.Equal(t, tc.expConsuAddProp, ok)
// })
// }
// }

0 comments on commit 7cd900a

Please sign in to comment.