From 324da02ba97692e9abaaf8c72befd5342fd00b44 Mon Sep 17 00:00:00 2001 From: Jeancarlo Barrios Date: Mon, 9 May 2022 08:43:03 -0600 Subject: [PATCH] feat(group): add test for keeper and cli (#11679) ## Description Closes: #XXXX --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable) --- codec/amino.go | 1 - x/group/client/testutil/query.go | 4 +- x/group/client/testutil/tx.go | 697 +++++++++++++++++++++---------- x/group/keeper/keeper_test.go | 47 +++ 4 files changed, 520 insertions(+), 229 deletions(-) diff --git a/codec/amino.go b/codec/amino.go index fe22fd14f..506e598da 100644 --- a/codec/amino.go +++ b/codec/amino.go @@ -47,7 +47,6 @@ func MarshalJSONIndent(cdc *LegacyAmino, obj interface{}) ([]byte, error) { if err = json.Indent(&out, bz, "", " "); err != nil { return nil, err } - return out.Bytes(), nil } diff --git a/x/group/client/testutil/query.go b/x/group/client/testutil/query.go index 5ca1c06e6..f9562dfe7 100644 --- a/x/group/client/testutil/query.go +++ b/x/group/client/testutil/query.go @@ -793,7 +793,7 @@ func (s *IntegrationTestSuite) TestTallyResult() { var txResp sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) s.Require().Equal(uint32(0), txResp.Code, out.String()) - proposalId := s.getProposalIdFromTxResponse(txResp) + proposalID := s.getProposalIDFromTxResponse(txResp) testCases := []struct { name string @@ -828,7 +828,7 @@ func (s *IntegrationTestSuite) TestTallyResult() { { "valid proposal id with no votes", []string{ - proposalId, + proposalID, fmt.Sprintf("--%s=json", tmcli.OutputFlag), }, false, diff --git a/x/group/client/testutil/tx.go b/x/group/client/testutil/tx.go index a32c6b420..07c7413dd 100644 --- a/x/group/client/testutil/tx.go +++ b/x/group/client/testutil/tx.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/gogo/protobuf/proto" + "github.com/google/uuid" "github.com/stretchr/testify/suite" tmcli "github.com/tendermint/tendermint/libs/cli" @@ -35,6 +36,7 @@ type IntegrationTestSuite struct { proposal *group.Proposal vote *group.Vote voter *group.Member + commonFlags []string } const validMetadata = "metadata" @@ -48,6 +50,12 @@ func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") + s.commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + var err error s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) s.Require().NoError(err) @@ -75,12 +83,6 @@ func (s *IntegrationTestSuite) SetupSuite() { ) s.Require().NoError(err) - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } - memberWeight := "3" // create a group validMembers := fmt.Sprintf(` @@ -101,7 +103,7 @@ func (s *IntegrationTestSuite) SetupSuite() { validMetadata, validMembersFile.Name(), }, - commonFlags..., + s.commonFlags..., ), ) @@ -118,20 +120,8 @@ func (s *IntegrationTestSuite) SetupSuite() { if threshold > 3 { threshold = 3 } - out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreateGroupPolicyCmd(), - append( - []string{ - val.Address.String(), - "1", - validMetadata, - fmt.Sprintf("{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"%d\", \"windows\":{\"voting_period\":\"30000s\"}}", threshold), - }, - commonFlags..., - ), - ) - s.Require().NoError(err, out.String()) - s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) - s.Require().Equal(uint32(0), txResp.Code, out.String()) + + s.createGroupThresholdPolicyWithBalance(val.Address.String(), "1", threshold, 1000) out, err = cli.ExecTestCLICmd(val.ClientCtx, client.QueryGroupPoliciesByGroupCmd(), []string{"1", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) s.Require().NoError(err, out.String()) @@ -146,7 +136,7 @@ func (s *IntegrationTestSuite) SetupSuite() { validMetadata, fmt.Sprintf("{\"@type\":\"/cosmos.group.v1.PercentageDecisionPolicy\", \"percentage\":\"%f\", \"windows\":{\"voting_period\":\"30000s\"}}", percentage), }, - commonFlags..., + s.commonFlags..., ), ) s.Require().NoError(err, out.String()) @@ -170,7 +160,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.groupPolicies[0].Address, val.Address.String(), ""), }, - commonFlags..., + s.commonFlags..., ), ) s.Require().NoError(err, out.String()) @@ -186,7 +176,7 @@ func (s *IntegrationTestSuite) SetupSuite() { "VOTE_OPTION_YES", "", }, - commonFlags..., + s.commonFlags..., ), ) s.Require().NoError(err, out.String()) @@ -223,12 +213,6 @@ func (s *IntegrationTestSuite) TestTxCreateGroup() { val := s.network.Validators[0] clientCtx := val.ClientCtx - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } - validMembers := fmt.Sprintf(`{"members": [{ "address": "%s", "weight": "1", @@ -271,7 +255,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroup() { "", validMembersFile.Name(), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -287,7 +271,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroup() { validMembersFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -302,7 +286,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroup() { strings.Repeat("a", 256), "", }, - commonFlags..., + s.commonFlags..., ), true, "group metadata: limit exceeded", @@ -317,7 +301,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroup() { "null", invalidMembersAddressFile.Name(), }, - commonFlags..., + s.commonFlags..., ), true, "message validation failed: address: empty address string is not allowed", @@ -332,7 +316,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroup() { "null", invalidMembersWeightFile.Name(), }, - commonFlags..., + s.commonFlags..., ), true, "expected a positive decimal, got 0: invalid decimal string", @@ -347,7 +331,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroup() { "null", invalidMembersMetadataFile.Name(), }, - commonFlags..., + s.commonFlags..., ), true, "member metadata: limit exceeded", @@ -381,12 +365,6 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupAdmin() { clientCtx := val.ClientCtx require := s.Require() - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } - groupIDs := make([]string, 2) for i := 0; i < 2; i++ { validMembers := fmt.Sprintf(`{"members": [{ @@ -402,14 +380,14 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupAdmin() { validMetadata, validMembersFile.Name(), }, - commonFlags..., + s.commonFlags..., ), ) require.NoError(err, out.String()) var txResp sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) s.Require().Equal(uint32(0), txResp.Code, out.String()) - groupIDs[i] = s.getGroupIdFromTxResponse(txResp) + groupIDs[i] = s.getGroupIDFromTxResponse(txResp) } testCases := []struct { @@ -428,7 +406,7 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupAdmin() { groupIDs[0], s.network.Validators[1].Address.String(), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -444,7 +422,7 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupAdmin() { s.network.Validators[1].Address.String(), fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -459,7 +437,7 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupAdmin() { "", s.network.Validators[1].Address.String(), }, - commonFlags..., + s.commonFlags..., ), true, "strconv.ParseUint: parsing \"\": invalid syntax", @@ -474,7 +452,7 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupAdmin() { "12345", s.network.Validators[1].Address.String(), }, - commonFlags..., + s.commonFlags..., ), true, "not found", @@ -507,12 +485,6 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupMetadata() { val := s.network.Validators[0] clientCtx := val.ClientCtx - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } - testCases := []struct { name string args []string @@ -526,10 +498,10 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupMetadata() { append( []string{ val.Address.String(), - "2", + "1", validMetadata, }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -541,11 +513,11 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupMetadata() { append( []string{ val.Address.String(), - "2", + "1", validMetadata, fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -560,7 +532,7 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupMetadata() { strconv.FormatUint(s.group.Id, 10), strings.Repeat("a", 256), }, - commonFlags..., + s.commonFlags..., ), true, "group metadata: limit exceeded", @@ -593,11 +565,11 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupMembers() { val := s.network.Validators[0] clientCtx := val.ClientCtx - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } + weights := []string{"1", "1", "1"} + accounts := s.createAccounts(3) + + groupID := s.createGroupWithMembers(weights, accounts) + groupPolicyAddress := s.createGroupThresholdPolicyWithBalance(accounts[0], groupID, 3, 100) validUpdatedMembersFileName := testutil.WriteToNewTempFile(s.T(), fmt.Sprintf(`{"members": [{ "address": "%s", @@ -607,13 +579,13 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupMembers() { "address": "%s", "weight": "1", "metadata": "%s" - }]}`, val.Address.String(), validMetadata, s.groupPolicies[0].Address, validMetadata)).Name() + }]}`, accounts[0], validMetadata, groupPolicyAddress, validMetadata)).Name() invalidMembersMetadata := fmt.Sprintf(`{"members": [{ "address": "%s", "weight": "1", "metadata": "%s" - }]}`, val.Address.String(), tooLongMetadata) + }]}`, accounts[0], tooLongMetadata) invalidMembersMetadataFileName := testutil.WriteToNewTempFile(s.T(), invalidMembersMetadata).Name() testCases := []struct { @@ -628,11 +600,11 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupMembers() { "correct data", append( []string{ - val.Address.String(), - "2", + accounts[0], + groupID, validUpdatedMembersFileName, }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -643,8 +615,8 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupMembers() { "with amino-json", append( []string{ - val.Address.String(), - "2", + accounts[0], + groupID, testutil.WriteToNewTempFile(s.T(), fmt.Sprintf(`{"members": [{ "address": "%s", "weight": "2", @@ -652,7 +624,7 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupMembers() { }]}`, s.groupPolicies[0].Address, validMetadata)).Name(), fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -663,11 +635,11 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupMembers() { "group member metadata too long", append( []string{ - val.Address.String(), - strconv.FormatUint(s.group.Id, 10), + accounts[0], + groupID, invalidMembersMetadataFileName, }, - commonFlags..., + s.commonFlags..., ), true, "group member metadata: limit exceeded", @@ -678,11 +650,11 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupMembers() { "group doesn't exist", append( []string{ - val.Address.String(), + accounts[0], "12345", validUpdatedMembersFileName, }, - commonFlags..., + s.commonFlags..., ), true, "not found", @@ -715,12 +687,6 @@ func (s *IntegrationTestSuite) TestTxCreateGroupWithPolicy() { val := s.network.Validators[0] clientCtx := val.ClientCtx - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } - validMembers := fmt.Sprintf(`{"members": [{ "address": "%s", "weight": "1", @@ -766,7 +732,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupWithPolicy() { "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", fmt.Sprintf("--%s=%v", client.FlagGroupPolicyAsAdmin, false), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -784,7 +750,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupWithPolicy() { "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", fmt.Sprintf("--%s=%v", client.FlagGroupPolicyAsAdmin, true), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -803,7 +769,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupWithPolicy() { fmt.Sprintf("--%s=%v", client.FlagGroupPolicyAsAdmin, false), fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -821,7 +787,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupWithPolicy() { "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", fmt.Sprintf("--%s=%v", client.FlagGroupPolicyAsAdmin, false), }, - commonFlags..., + s.commonFlags..., ), true, "group metadata: limit exceeded", @@ -839,7 +805,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupWithPolicy() { "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", fmt.Sprintf("--%s=%v", client.FlagGroupPolicyAsAdmin, false), }, - commonFlags..., + s.commonFlags..., ), true, "group policy metadata: limit exceeded", @@ -857,7 +823,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupWithPolicy() { "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", fmt.Sprintf("--%s=%v", client.FlagGroupPolicyAsAdmin, false), }, - commonFlags..., + s.commonFlags..., ), true, "message validation failed: address: empty address string is not allowed", @@ -875,7 +841,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupWithPolicy() { "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", fmt.Sprintf("--%s=%v", client.FlagGroupPolicyAsAdmin, false), }, - commonFlags..., + s.commonFlags..., ), true, "expected a positive decimal, got 0: invalid decimal string", @@ -893,7 +859,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupWithPolicy() { "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", fmt.Sprintf("--%s=%v", client.FlagGroupPolicyAsAdmin, false), }, - commonFlags..., + s.commonFlags..., ), true, "member metadata: limit exceeded", @@ -926,12 +892,6 @@ func (s *IntegrationTestSuite) TestTxCreateGroupPolicy() { wrongAdmin := s.network.Validators[1].Address clientCtx := val.ClientCtx - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } - groupID := s.group.Id testCases := []struct { @@ -951,7 +911,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupPolicy() { validMetadata, "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -967,7 +927,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupPolicy() { validMetadata, "{\"@type\":\"/cosmos.group.v1.PercentageDecisionPolicy\", \"percentage\":\"0.5\", \"windows\":{\"voting_period\":\"1s\"}}", }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -984,7 +944,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupPolicy() { "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -1000,7 +960,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupPolicy() { validMetadata, "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", }, - commonFlags..., + s.commonFlags..., ), true, "key not found", @@ -1016,7 +976,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupPolicy() { strings.Repeat("a", 500), "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", }, - commonFlags..., + s.commonFlags..., ), true, "group policy metadata: limit exceeded", @@ -1032,7 +992,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupPolicy() { validMetadata, "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"windows\":{\"voting_period\":\"1s\"}}", }, - commonFlags..., + s.commonFlags..., ), true, "not found", @@ -1048,7 +1008,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupPolicy() { validMetadata, "{\"@type\":\"/cosmos.group.v1.PercentageDecisionPolicy\", \"percentage\":\"-0.5\", \"windows\":{\"voting_period\":\"1s\"}}", }, - commonFlags..., + s.commonFlags..., ), true, "expected a positive decimal", @@ -1064,7 +1024,7 @@ func (s *IntegrationTestSuite) TestTxCreateGroupPolicy() { validMetadata, "{\"@type\":\"/cosmos.group.v1.PercentageDecisionPolicy\", \"percentage\":\"2\", \"windows\":{\"voting_period\":\"1s\"}}", }, - commonFlags..., + s.commonFlags..., ), true, "percentage must be > 0 and <= 1", @@ -1099,12 +1059,8 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupPolicyAdmin() { clientCtx := val.ClientCtx groupPolicy := s.groupPolicies[3] - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - fmt.Sprintf("--%s=%d", flags.FlagGas, 300000), - } + commonFlags := s.commonFlags + commonFlags = append(commonFlags, fmt.Sprintf("--%s=%d", flags.FlagGas, 300000)) testCases := []struct { name string @@ -1203,12 +1159,8 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupPolicyDecisionPolicy() { clientCtx := val.ClientCtx groupPolicy := s.groupPolicies[2] - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - fmt.Sprintf("--%s=%d", flags.FlagGas, 300000), - } + commonFlags := s.commonFlags + commonFlags = append(commonFlags, fmt.Sprintf("--%s=%d", flags.FlagGas, 300000)) testCases := []struct { name string @@ -1352,12 +1304,8 @@ func (s *IntegrationTestSuite) TestTxUpdateGroupPolicyMetadata() { clientCtx := val.ClientCtx groupPolicy := s.groupPolicies[2] - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - fmt.Sprintf("--%s=%d", flags.FlagGas, 300000), - } + commonFlags := s.commonFlags + commonFlags = append(commonFlags, fmt.Sprintf("--%s=%d", flags.FlagGas, 300000)) testCases := []struct { name string @@ -1469,12 +1417,6 @@ func (s *IntegrationTestSuite) TestTxSubmitProposal() { val := s.network.Validators[0] clientCtx := val.ClientCtx - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } - testCases := []struct { name string args []string @@ -1493,7 +1435,7 @@ func (s *IntegrationTestSuite) TestTxSubmitProposal() { "", ), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -1511,7 +1453,7 @@ func (s *IntegrationTestSuite) TestTxSubmitProposal() { ), fmt.Sprintf("--%s=try", client.FlagExec), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -1528,7 +1470,7 @@ func (s *IntegrationTestSuite) TestTxSubmitProposal() { ""), fmt.Sprintf("--%s=try", client.FlagExec), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -1546,7 +1488,7 @@ func (s *IntegrationTestSuite) TestTxSubmitProposal() { ), fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -1563,7 +1505,7 @@ func (s *IntegrationTestSuite) TestTxSubmitProposal() { tooLongMetadata, ), }, - commonFlags..., + s.commonFlags..., ), true, "metadata: limit exceeded", @@ -1579,7 +1521,7 @@ func (s *IntegrationTestSuite) TestTxSubmitProposal() { val.Address.String(), s.groupPolicies[0].Address, ""), }, - commonFlags..., + s.commonFlags..., ), true, "msg does not have group policy authorization", @@ -1596,7 +1538,7 @@ func (s *IntegrationTestSuite) TestTxSubmitProposal() { "", ), }, - commonFlags..., + s.commonFlags..., ), true, "invalid.info: key not found", @@ -1613,7 +1555,7 @@ func (s *IntegrationTestSuite) TestTxSubmitProposal() { "", ), }, - commonFlags..., + s.commonFlags..., ), true, "group policy: decoding bech32 failed", @@ -1630,7 +1572,7 @@ func (s *IntegrationTestSuite) TestTxSubmitProposal() { "", ), }, - commonFlags..., + s.commonFlags..., ), true, "group policy: not found", @@ -1663,24 +1605,24 @@ func (s *IntegrationTestSuite) TestTxVote() { val := s.network.Validators[0] clientCtx := val.ClientCtx - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } - ids := make([]string, 4) + weights := []string{"1", "1", "1"} + accounts := s.createAccounts(3) + + groupID := s.createGroupWithMembers(weights, accounts) + groupPolicyAddress := s.createGroupThresholdPolicyWithBalance(accounts[0], groupID, 3, 100) for i := 0; i < 4; i++ { out, err := cli.ExecTestCLICmd(val.ClientCtx, client.MsgSubmitProposalCmd(), append( []string{ s.createCLIProposal( - s.groupPolicies[1].Address, val.Address.String(), - s.groupPolicies[1].Address, val.Address.String(), - ""), + groupPolicyAddress, accounts[0], + groupPolicyAddress, accounts[0], + "", + ), }, - commonFlags..., + s.commonFlags..., ), ) s.Require().NoError(err, out.String()) @@ -1688,7 +1630,7 @@ func (s *IntegrationTestSuite) TestTxVote() { var txResp sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) s.Require().Equal(uint32(0), txResp.Code, out.String()) - ids[i] = s.getProposalIdFromTxResponse(txResp) + ids[i] = s.getProposalIDFromTxResponse(txResp) } testCases := []struct { @@ -1704,11 +1646,11 @@ func (s *IntegrationTestSuite) TestTxVote() { append( []string{ ids[0], - val.Address.String(), + accounts[0], "VOTE_OPTION_YES", "", }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -1720,12 +1662,12 @@ func (s *IntegrationTestSuite) TestTxVote() { append( []string{ ids[1], - val.Address.String(), + accounts[0], "VOTE_OPTION_YES", "", fmt.Sprintf("--%s=try", client.FlagExec), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -1737,12 +1679,12 @@ func (s *IntegrationTestSuite) TestTxVote() { append( []string{ ids[2], - val.Address.String(), + accounts[0], "VOTE_OPTION_NO", "", fmt.Sprintf("--%s=try", client.FlagExec), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -1754,12 +1696,12 @@ func (s *IntegrationTestSuite) TestTxVote() { append( []string{ ids[3], - val.Address.String(), + accounts[0], "VOTE_OPTION_YES", "", fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -1771,11 +1713,11 @@ func (s *IntegrationTestSuite) TestTxVote() { append( []string{ "abcd", - val.Address.String(), + accounts[0], "VOTE_OPTION_YES", "", }, - commonFlags..., + s.commonFlags..., ), true, "invalid syntax", @@ -1787,11 +1729,11 @@ func (s *IntegrationTestSuite) TestTxVote() { append( []string{ "1234", - val.Address.String(), + accounts[0], "VOTE_OPTION_YES", "", }, - commonFlags..., + s.commonFlags..., ), true, "proposal: not found", @@ -1803,11 +1745,11 @@ func (s *IntegrationTestSuite) TestTxVote() { append( []string{ "2", - val.Address.String(), + accounts[0], "VOTE_OPTION_YES", tooLongMetadata, }, - commonFlags..., + s.commonFlags..., ), true, "metadata: limit exceeded", @@ -1819,11 +1761,11 @@ func (s *IntegrationTestSuite) TestTxVote() { append( []string{ "2", - val.Address.String(), + accounts[0], "INVALID_VOTE_OPTION", "", }, - commonFlags..., + s.commonFlags..., ), true, "not a valid vote option", @@ -1856,12 +1798,6 @@ func (s *IntegrationTestSuite) TestTxWithdrawProposal() { val := s.network.Validators[0] clientCtx := val.ClientCtx - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } - ids := make([]string, 2) for i := 0; i < 2; i++ { @@ -1873,7 +1809,7 @@ func (s *IntegrationTestSuite) TestTxWithdrawProposal() { s.groupPolicies[1].Address, val.Address.String(), ""), }, - commonFlags..., + s.commonFlags..., ), ) s.Require().NoError(err, out.String()) @@ -1881,7 +1817,7 @@ func (s *IntegrationTestSuite) TestTxWithdrawProposal() { var txResp sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) s.Require().Equal(uint32(0), txResp.Code, out.String()) - ids[i] = s.getProposalIdFromTxResponse(txResp) + ids[i] = s.getProposalIDFromTxResponse(txResp) } testCases := []struct { @@ -1899,7 +1835,7 @@ func (s *IntegrationTestSuite) TestTxWithdrawProposal() { ids[0], val.Address.String(), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -1913,7 +1849,7 @@ func (s *IntegrationTestSuite) TestTxWithdrawProposal() { ids[0], val.Address.String(), }, - commonFlags..., + s.commonFlags..., ), true, "cannot withdraw a proposal with the status of PROPOSAL_STATUS_WITHDRAWN", @@ -1927,7 +1863,7 @@ func (s *IntegrationTestSuite) TestTxWithdrawProposal() { "222", "wrongAdmin", }, - commonFlags..., + s.commonFlags..., ), true, "not found", @@ -1941,7 +1877,7 @@ func (s *IntegrationTestSuite) TestTxWithdrawProposal() { "abc", val.Address.String(), }, - commonFlags..., + s.commonFlags..., ), true, "invalid syntax", @@ -1955,7 +1891,7 @@ func (s *IntegrationTestSuite) TestTxWithdrawProposal() { ids[1], "wrongAdmin", }, - commonFlags..., + s.commonFlags..., ), true, "key not found", @@ -1984,7 +1920,7 @@ func (s *IntegrationTestSuite) TestTxWithdrawProposal() { } } -func (s *IntegrationTestSuite) getProposalIdFromTxResponse(txResp sdk.TxResponse) string { +func (s *IntegrationTestSuite) getProposalIDFromTxResponse(txResp sdk.TxResponse) string { s.Require().Greater(len(txResp.Logs), 0) s.Require().NotNil(txResp.Logs[0].Events) events := txResp.Logs[0].Events @@ -2004,12 +1940,6 @@ func (s *IntegrationTestSuite) TestTxExec() { clientCtx := val.ClientCtx require := s.Require() - var commonFlags = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } - var proposalIDs []string // create proposals and vote for i := 0; i < 2; i++ { @@ -2022,7 +1952,7 @@ func (s *IntegrationTestSuite) TestTxExec() { "", ), }, - commonFlags..., + s.commonFlags..., ), ) require.NoError(err, out.String()) @@ -2030,7 +1960,7 @@ func (s *IntegrationTestSuite) TestTxExec() { var txResp sdk.TxResponse require.NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) require.Equal(uint32(0), txResp.Code, out.String()) - proposalID := s.getProposalIdFromTxResponse(txResp) + proposalID := s.getProposalIDFromTxResponse(txResp) proposalIDs = append(proposalIDs, proposalID) out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgVoteCmd(), @@ -2041,7 +1971,7 @@ func (s *IntegrationTestSuite) TestTxExec() { "VOTE_OPTION_YES", "", }, - commonFlags..., + s.commonFlags..., ), ) require.NoError(err, out.String()) @@ -2062,7 +1992,7 @@ func (s *IntegrationTestSuite) TestTxExec() { proposalIDs[0], fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -2077,7 +2007,7 @@ func (s *IntegrationTestSuite) TestTxExec() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -2091,7 +2021,7 @@ func (s *IntegrationTestSuite) TestTxExec() { "abcd", fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), }, - commonFlags..., + s.commonFlags..., ), true, "invalid syntax", @@ -2105,7 +2035,7 @@ func (s *IntegrationTestSuite) TestTxExec() { "1234", fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), }, - commonFlags..., + s.commonFlags..., ), true, "proposal: not found", @@ -2139,31 +2069,8 @@ func (s *IntegrationTestSuite) TestTxLeaveGroup() { clientCtx := val.ClientCtx require := s.Require() - commonFlags := []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), - } - // create 3 accounts with some tokens - members := make([]string, 3) - for i := 1; i <= 3; i++ { - info, _, err := clientCtx.Keyring.NewMnemonic(fmt.Sprintf("member%d", i), keyring.English, sdk.FullFundraiserPath, - keyring.DefaultBIP39Passphrase, hd.Secp256k1) - require.NoError(err) - - pk, err := info.GetPubKey() - require.NoError(err) - - account := sdk.AccAddress(pk.Address()) - members[i-1] = account.String() - - _, err = banktestutil.MsgSendExec(clientCtx, val.Address, account, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(100))), - commonFlags..., - ) - require.NoError(err) - } + members := s.createAccounts(3) // create a group with three members validMembers := fmt.Sprintf(`{"members": [{ @@ -2187,13 +2094,13 @@ func (s *IntegrationTestSuite) TestTxLeaveGroup() { validMetadata, validMembersFile.Name(), }, - commonFlags..., + s.commonFlags..., ), ) require.NoError(err, out.String()) var txResp sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) - groupID := s.getGroupIdFromTxResponse(txResp) + groupID := s.getGroupIDFromTxResponse(txResp) // create group policy out, err = cli.ExecTestCLICmd(clientCtx, client.MsgCreateGroupPolicyCmd(), @@ -2204,7 +2111,7 @@ func (s *IntegrationTestSuite) TestTxLeaveGroup() { "AQ==", "{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"3\", \"windows\":{\"voting_period\":\"1s\"}}", }, - commonFlags..., + s.commonFlags..., ), ) require.NoError(err, out.String()) @@ -2230,7 +2137,7 @@ func (s *IntegrationTestSuite) TestTxLeaveGroup() { groupID, fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), }, - commonFlags..., + s.commonFlags..., ), true, "key not found", @@ -2243,7 +2150,7 @@ func (s *IntegrationTestSuite) TestTxLeaveGroup() { "40", fmt.Sprintf("--%s=%s", flags.FlagFrom, members[0]), }, - commonFlags..., + s.commonFlags..., ), true, "group: not found", @@ -2256,7 +2163,7 @@ func (s *IntegrationTestSuite) TestTxLeaveGroup() { groupID, fmt.Sprintf("--%s=%s", flags.FlagFrom, members[2]), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -2269,7 +2176,7 @@ func (s *IntegrationTestSuite) TestTxLeaveGroup() { groupID, fmt.Sprintf("--%s=%s", flags.FlagFrom, members[2]), }, - commonFlags..., + s.commonFlags..., ), true, "is not part of group", @@ -2282,7 +2189,7 @@ func (s *IntegrationTestSuite) TestTxLeaveGroup() { groupID, fmt.Sprintf("--%s=%s", flags.FlagFrom, members[1]), }, - commonFlags..., + s.commonFlags..., ), false, "", @@ -2306,7 +2213,213 @@ func (s *IntegrationTestSuite) TestTxLeaveGroup() { } } -func (s *IntegrationTestSuite) getGroupIdFromTxResponse(txResp sdk.TxResponse) string { +func (s *IntegrationTestSuite) TestExecProposalsWhenMemberLeavesOrIsUpdated() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + weights := []string{"1", "1", "2"} + accounts := s.createAccounts(3) + testCases := []struct { + name string + votes []string + members []string + malleate func(groupID string) error + expectLogErr bool + errMsg string + respType proto.Message + }{ + { + "member leaves while all others vote yes", + []string{"VOTE_OPTION_YES", "VOTE_OPTION_YES", "VOTE_OPTION_YES"}, + accounts, + func(groupID string) error { + leavingMemberIdx := 1 + args := append( + []string{ + accounts[leavingMemberIdx], + groupID, + + fmt.Sprintf("--%s=%s", flags.FlagFrom, accounts[leavingMemberIdx]), + }, + s.commonFlags..., + ) + out, err := cli.ExecTestCLICmd(clientCtx, client.MsgLeaveGroupCmd(), args) + s.Require().NoError(err, out.String()) + var resp sdk.TxResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) + s.Require().Equal(uint32(0), resp.Code, out.String()) + + return err + }, + false, + "", + &sdk.TxResponse{}, + }, + { + "member leaves while all others vote yes and no", + []string{"VOTE_OPTION_NO", "VOTE_OPTION_YES", "VOTE_OPTION_YES"}, + accounts, + func(groupID string) error { + leavingMemberIdx := 1 + args := append( + []string{ + accounts[leavingMemberIdx], + groupID, + + fmt.Sprintf("--%s=%s", flags.FlagFrom, accounts[leavingMemberIdx]), + }, + s.commonFlags..., + ) + out, err := cli.ExecTestCLICmd(clientCtx, client.MsgLeaveGroupCmd(), args) + s.Require().NoError(err, out.String()) + var resp sdk.TxResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) + s.Require().Equal(uint32(0), resp.Code, out.String()) + + return err + }, + true, + "PROPOSAL_EXECUTOR_RESULT_NOT_RUN", + &sdk.TxResponse{}, + }, + { + "member that leaves does affect the threshold policy outcome", + []string{"VOTE_OPTION_YES", "VOTE_OPTION_YES"}, + accounts, + func(groupID string) error { + leavingMemberIdx := 2 + args := append( + []string{ + accounts[leavingMemberIdx], + groupID, + + fmt.Sprintf("--%s=%s", flags.FlagFrom, accounts[leavingMemberIdx]), + }, + s.commonFlags..., + ) + out, err := cli.ExecTestCLICmd(clientCtx, client.MsgLeaveGroupCmd(), args) + s.Require().NoError(err, out.String()) + var resp sdk.TxResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) + s.Require().Equal(uint32(0), resp.Code, out.String()) + + return err + }, + false, + "", + &sdk.TxResponse{}, + }, + { + "update group policy voids the proposal", + []string{"VOTE_OPTION_YES", "VOTE_OPTION_NO"}, + accounts, + func(groupID string) error { + updateGroup := s.newValidMembers(weights[0:1], accounts[0:1]) + + updateGroupByte, err := json.Marshal(updateGroup) + s.Require().NoError(err) + + validUpdateMemberFileName := testutil.WriteToNewTempFile(s.T(), string(updateGroupByte)).Name() + + args := append( + []string{ + accounts[0], + groupID, + validUpdateMemberFileName, + }, + s.commonFlags..., + ) + out, err := cli.ExecTestCLICmd(clientCtx, client.MsgUpdateGroupMembersCmd(), args) + s.Require().NoError(err, out.String()) + var resp sdk.TxResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) + s.Require().Equal(uint32(0), resp.Code, out.String()) + + return err + }, + true, + "PROPOSAL_EXECUTOR_RESULT_NOT_RUN", + &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmdSubmitProposal := client.MsgSubmitProposalCmd() + cmdMsgExec := client.MsgExecCmd() + + groupID := s.createGroupWithMembers(weights, accounts) + groupPolicyAddress := s.createGroupThresholdPolicyWithBalance(accounts[0], groupID, 3, 100) + + // Submit proposal + proposal := s.createCLIProposal( + groupPolicyAddress, tc.members[0], + groupPolicyAddress, tc.members[0], + "", + ) + submitProposalArgs := append([]string{ + proposal, + }, + s.commonFlags..., + ) + var submitProposalResp sdk.TxResponse + out, err := cli.ExecTestCLICmd(clientCtx, cmdSubmitProposal, submitProposalArgs) + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &submitProposalResp), out.String()) + proposalID := s.getProposalIDFromTxResponse(submitProposalResp) + + for i, vote := range tc.votes { + memberAddress := tc.members[i] + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgVoteCmd(), + append( + []string{ + proposalID, + memberAddress, + vote, + "", + }, + s.commonFlags..., + ), + ) + + var txResp sdk.TxResponse + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + } + + err = tc.malleate(groupID) + s.Require().NoError(err) + + err = s.network.WaitForNextBlock() + s.Require().NoError(err) + + args := append( + []string{ + proposalID, + fmt.Sprintf("--%s=%s", flags.FlagFrom, tc.members[0]), + }, + s.commonFlags..., + ) + out, err = cli.ExecTestCLICmd(clientCtx, cmdMsgExec, args) + s.Require().NoError(err) + + var execResp sdk.TxResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &execResp), out.String()) + + if tc.expectLogErr { + s.Require().Contains(execResp.RawLog, tc.errMsg) + } + + }) + } + +} + +func (s *IntegrationTestSuite) getGroupIDFromTxResponse(txResp sdk.TxResponse) string { s.Require().Greater(len(txResp.Logs), 0) s.Require().NotNil(txResp.Logs[0].Events) events := txResp.Logs[0].Events @@ -2330,7 +2443,7 @@ func (s *IntegrationTestSuite) createCLIProposal(groupPolicyAddress, proposer, s msg := banktypes.MsgSend{ FromAddress: sendFrom, ToAddress: sendTo, - Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))), + Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(20))), } msgJSON, err := s.cfg.Codec.MarshalInterfaceJSON(&msg) s.Require().NoError(err) @@ -2347,3 +2460,135 @@ func (s *IntegrationTestSuite) createCLIProposal(groupPolicyAddress, proposer, s return testutil.WriteToNewTempFile(s.T(), string(bz)).Name() } + +func (s *IntegrationTestSuite) createAccounts(quantity int) []string { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + accounts := make([]string, quantity) + + for i := 1; i <= quantity; i++ { + memberNumber := uuid.New().String() + + info, _, err := clientCtx.Keyring.NewMnemonic(fmt.Sprintf("member%s", memberNumber), keyring.English, sdk.FullFundraiserPath, + keyring.DefaultBIP39Passphrase, hd.Secp256k1) + s.Require().NoError(err) + + pk, err := info.GetPubKey() + s.Require().NoError(err) + + account := sdk.AccAddress(pk.Address()) + accounts[i-1] = account.String() + + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + val.Address, + account, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(2000))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + s.Require().NoError(err) + } + return accounts +} + +func (s *IntegrationTestSuite) createGroupWithMembers(membersWeight, membersAddress []string) string { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + s.Require().Equal(len(membersWeight), len(membersAddress)) + + membersValid := s.newValidMembers(membersWeight, membersAddress) + membersByte, err := json.Marshal(membersValid) + + s.Require().NoError(err) + + validMembersFile := testutil.WriteToNewTempFile(s.T(), string(membersByte)) + out, err := cli.ExecTestCLICmd(clientCtx, client.MsgCreateGroupCmd(), + append( + []string{ + membersAddress[0], + validMetadata, + validMembersFile.Name(), + }, + s.commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + var txResp sdk.TxResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + return s.getGroupIDFromTxResponse(txResp) +} + +func (s *IntegrationTestSuite) createGroupThresholdPolicyWithBalance(adminAddress, groupID string, threshold int, tokens int64) string { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + out, err := cli.ExecTestCLICmd(clientCtx, client.MsgCreateGroupPolicyCmd(), + append( + []string{ + adminAddress, + groupID, + validMetadata, + fmt.Sprintf("{\"@type\":\"/cosmos.group.v1.ThresholdDecisionPolicy\", \"threshold\":\"%d\", \"windows\":{\"voting_period\":\"30000s\"}}", threshold), + }, + s.commonFlags..., + ), + ) + var txResp = sdk.TxResponse{} + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.QueryGroupPoliciesByGroupCmd(), []string{groupID, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + s.Require().NoError(err, out.String()) + + var res group.QueryGroupPoliciesByGroupResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + groupPolicyAddress := res.GroupPolicies[0].Address + + addr, err := sdk.AccAddressFromBech32(groupPolicyAddress) + s.Require().NoError(err) + _, err = banktestutil.MsgSendExec(clientCtx, val.Address, addr, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(tokens))), + s.commonFlags..., + ) + s.Require().NoError(err) + return groupPolicyAddress +} + +// fundAllGroupPolicies sends tokens to all group policies of a given group ID. +func (s *IntegrationTestSuite) fundAllGroupPolicies(groupID string, tokens sdk.Coin) { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + out, err := cli.ExecTestCLICmd(val.ClientCtx, client.QueryGroupPoliciesByGroupCmd(), []string{groupID, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + s.Require().NoError(err, out.String()) + var res group.QueryGroupPoliciesByGroupResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + + for _, policy := range res.GroupPolicies { + address := policy.Address + addr, err := sdk.AccAddressFromBech32(address) + s.Require().NoError(err) + _, err = banktestutil.MsgSendExec(clientCtx, val.Address, addr, + sdk.NewCoins(tokens), + s.commonFlags..., + ) + s.Require().NoError(err) + } +} + +func (s *IntegrationTestSuite) newValidMembers(weights, membersAddress []string) group.MemberRequests { + s.Require().Equal(len(weights), len(membersAddress)) + membersValid := group.MemberRequests{} + for i, address := range membersAddress { + membersValid.Members = append(membersValid.Members, group.MemberRequest{ + Address: address, + Weight: weights[i], + Metadata: validMetadata, + }) + } + return membersValid +} diff --git a/x/group/keeper/keeper_test.go b/x/group/keeper/keeper_test.go index 6d044b481..578718a7a 100644 --- a/x/group/keeper/keeper_test.go +++ b/x/group/keeper/keeper_test.go @@ -2831,6 +2831,53 @@ func (s *TestSuite) TestLeaveGroup() { } } +func (s *TestSuite) TestPruneProposals() { + addrs := s.addrs + expirationTime := time.Hour * 24 * 15 // 15 days + groupID := s.groupID + accountAddr := s.groupPolicyAddr + + msgSend := &banktypes.MsgSend{ + FromAddress: s.groupPolicyAddr.String(), + ToAddress: addrs[0].String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)}, + } + + policyReq := &group.MsgCreateGroupPolicy{ + Admin: addrs[0].String(), + GroupId: groupID, + } + + policy := group.NewThresholdDecisionPolicy("100", time.Microsecond, time.Microsecond) + err := policyReq.SetDecisionPolicy(policy) + s.Require().NoError(err) + _, err = s.keeper.CreateGroupPolicy(s.ctx, policyReq) + s.Require().NoError(err) + + req := &group.MsgSubmitProposal{ + GroupPolicyAddress: accountAddr.String(), + Proposers: []string{addrs[1].String()}, + } + err = req.SetMsgs([]sdk.Msg{msgSend}) + s.Require().NoError(err) + submittedProposal, err := s.keeper.SubmitProposal(s.ctx, req) + s.Require().NoError(err) + queryProposal := group.QueryProposalRequest{ProposalId: submittedProposal.ProposalId} + prePrune, err := s.keeper.Proposal(s.ctx, &queryProposal) + s.Require().NoError(err) + s.Require().Equal(prePrune.Proposal.Id, submittedProposal.ProposalId) + // Move Forward in time for 15 days, after voting period end + max_execution_period + s.sdkCtx = s.sdkCtx.WithBlockTime(s.sdkCtx.BlockTime().Add(expirationTime)) + + // Prune Expired Proposals + err = s.keeper.PruneProposals(s.sdkCtx) + s.Require().NoError(err) + postPrune, err := s.keeper.Proposal(s.ctx, &queryProposal) + s.Require().Nil(postPrune) + s.Require().Error(err) + s.Require().Contains(err.Error(), "load proposal: not found") +} + func submitProposal( ctx context.Context, s *TestSuite, msgs []sdk.Msg, proposers []string) uint64 {