Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: move provider hooks tests to integration tests #1816

Merged
merged 1 commit into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
Dismissed Show dismissed Hide dismissed
Dismissed Show dismissed Hide dismissed
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)
Dismissed Show dismissed Hide dismissed
Dismissed Show dismissed Hide dismissed
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)
// })
// }
// }
Loading