diff --git a/tests/e2e/gov/cli_test.go b/tests/e2e/gov/cli_test.go deleted file mode 100644 index be8e7afc82e3..000000000000 --- a/tests/e2e/gov/cli_test.go +++ /dev/null @@ -1,37 +0,0 @@ -//go:build e2e -// +build e2e - -package gov - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/simapp" - v1 "cosmossdk.io/x/gov/types/v1" - - "github.com/cosmos/cosmos-sdk/testutil/network" -) - -func TestE2ETestSuite(t *testing.T) { - cfg := network.DefaultConfig(simapp.NewTestNetworkFixture) - cfg.NumValidators = 1 - suite.Run(t, NewE2ETestSuite(cfg)) -} - -func TestDepositTestSuite(t *testing.T) { - cfg := network.DefaultConfig(simapp.NewTestNetworkFixture) - cfg.NumValidators = 1 - genesisState := v1.DefaultGenesisState() - maxDepPeriod := time.Duration(20) * time.Second - votingPeriod := time.Duration(8) * time.Second - genesisState.Params.MaxDepositPeriod = &maxDepPeriod - genesisState.Params.VotingPeriod = &votingPeriod - bz, err := cfg.Codec.MarshalJSON(genesisState) - require.NoError(t, err) - cfg.GenesisState["gov"] = bz - suite.Run(t, NewDepositTestSuite(cfg)) -} diff --git a/tests/e2e/gov/deposits.go b/tests/e2e/gov/deposits.go deleted file mode 100644 index b685fa08bc62..000000000000 --- a/tests/e2e/gov/deposits.go +++ /dev/null @@ -1,164 +0,0 @@ -package gov - -import ( - "fmt" - "strconv" - "time" - - "github.com/stretchr/testify/suite" - - "cosmossdk.io/math" - "cosmossdk.io/x/gov/client/cli" - govclitestutil "cosmossdk.io/x/gov/client/testutil" - v1 "cosmossdk.io/x/gov/types/v1" - "cosmossdk.io/x/gov/types/v1beta1" - - "github.com/cosmos/cosmos-sdk/testutil" - "github.com/cosmos/cosmos-sdk/testutil/network" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type DepositTestSuite struct { - suite.Suite - - cfg network.Config - network network.NetworkI -} - -func NewDepositTestSuite(cfg network.Config) *DepositTestSuite { - return &DepositTestSuite{cfg: cfg} -} - -func (s *DepositTestSuite) SetupSuite() { - s.T().Log("setting up test suite") - - var err error - s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) - s.Require().NoError(err) -} - -func (s *DepositTestSuite) submitProposal(val network.ValidatorI, initialDeposit sdk.Coin, name string) uint64 { - var exactArgs []string - - if !initialDeposit.IsZero() { - exactArgs = append(exactArgs, fmt.Sprintf("--%s=%s", cli.FlagDeposit, initialDeposit.String())) - } - - _, err := govclitestutil.MsgSubmitLegacyProposal( - val.GetClientCtx(), - val.GetAddress().String(), - fmt.Sprintf("Text Proposal %s", name), - "Where is the title!?", - v1beta1.ProposalTypeText, - exactArgs..., - ) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - // query proposals, return the last's id - res, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals", val.GetAPIAddress())) - s.Require().NoError(err) - var proposals v1.QueryProposalsResponse - err = s.cfg.Codec.UnmarshalJSON(res, &proposals) - s.Require().NoError(err) - s.Require().GreaterOrEqual(len(proposals.Proposals), 1) - - return proposals.Proposals[len(proposals.Proposals)-1].Id -} - -func (s *DepositTestSuite) TearDownSuite() { - s.T().Log("tearing down test suite") - s.network.Cleanup() -} - -func (s *DepositTestSuite) TestQueryDepositsWithInitialDeposit() { - val := s.network.GetValidators()[0] - depositAmount := sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens) - - // submit proposal with an initial deposit - id := s.submitProposal(val, depositAmount, "TestQueryDepositsWithInitialDeposit") - proposalID := strconv.FormatUint(id, 10) - - // query deposit - deposit := s.queryDeposit(val, proposalID, false, "") - s.Require().NotNil(deposit) - s.Require().Equal(depositAmount.String(), sdk.Coins(deposit.Deposit.Amount).String()) - - // query deposits - deposits := s.queryDeposits(val, proposalID, false, "") - s.Require().NotNil(deposits) - s.Require().Len(deposits.Deposits, 1) - // verify initial deposit - s.Require().Equal(depositAmount.String(), sdk.Coins(deposits.Deposits[0].Amount).String()) -} - -func (s *DepositTestSuite) TestQueryProposalAfterVotingPeriod() { - val := s.network.GetValidators()[0] - depositAmount := sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens.Sub(math.NewInt(50))) - - // submit proposal with an initial deposit - id := s.submitProposal(val, depositAmount, "TestQueryProposalAfterVotingPeriod") - proposalID := strconv.FormatUint(id, 10) - - resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals", val.GetAPIAddress())) - s.Require().NoError(err) - var proposals v1.QueryProposalsResponse - err = s.cfg.Codec.UnmarshalJSON(resp, &proposals) - s.Require().NoError(err) - s.Require().GreaterOrEqual(len(proposals.Proposals), 1) - - // query proposal - resp, err = testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals/%s", val.GetAPIAddress(), proposalID)) - s.Require().NoError(err) - var proposal v1.QueryProposalResponse - err = s.cfg.Codec.UnmarshalJSON(resp, &proposal) - s.Require().NoError(err) - - // waiting for deposit and voting period to end - time.Sleep(25 * time.Second) - - // query proposal - resp, err = testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals/%s", val.GetAPIAddress(), proposalID)) - s.Require().NoError(err) - s.Require().Contains(string(resp), fmt.Sprintf("proposal %s doesn't exist", proposalID)) - - // query deposits - deposits := s.queryDeposits(val, proposalID, false, "") - s.Require().Len(deposits.Deposits, 0) -} - -func (s *DepositTestSuite) queryDeposits(val network.ValidatorI, proposalID string, exceptErr bool, message string) *v1.QueryDepositsResponse { - s.Require().NoError(s.network.WaitForNextBlock()) - - resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals/%s/deposits", val.GetAPIAddress(), proposalID)) - s.Require().NoError(err) - - if exceptErr { - s.Require().Contains(string(resp), message) - return nil - } - - var depositsRes v1.QueryDepositsResponse - err = val.GetClientCtx().Codec.UnmarshalJSON(resp, &depositsRes) - s.Require().NoError(err) - - return &depositsRes -} - -func (s *DepositTestSuite) queryDeposit(val network.ValidatorI, proposalID string, exceptErr bool, message string) *v1.QueryDepositResponse { - s.Require().NoError(s.network.WaitForNextBlock()) - - resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals/%s/deposits/%s", val.GetAPIAddress(), proposalID, val.GetAddress().String())) - s.Require().NoError(err) - - if exceptErr { - s.Require().Contains(string(resp), message) - return nil - } - - var depositRes v1.QueryDepositResponse - err = val.GetClientCtx().Codec.UnmarshalJSON(resp, &depositRes) - s.Require().NoError(err) - - return &depositRes -} diff --git a/tests/e2e/gov/tx.go b/tests/e2e/gov/tx.go deleted file mode 100644 index 9d6f84ce15aa..000000000000 --- a/tests/e2e/gov/tx.go +++ /dev/null @@ -1,372 +0,0 @@ -package gov - -import ( - "encoding/base64" - "fmt" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/math" - "cosmossdk.io/x/gov/client/cli" - govclitestutil "cosmossdk.io/x/gov/client/testutil" - "cosmossdk.io/x/gov/types" - v1 "cosmossdk.io/x/gov/types/v1" - "cosmossdk.io/x/gov/types/v1beta1" - - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/testutil" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/testutil/network" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -type E2ETestSuite struct { - suite.Suite - - cfg network.Config - network network.NetworkI -} - -func NewE2ETestSuite(cfg network.Config) *E2ETestSuite { - return &E2ETestSuite{cfg: cfg} -} - -func (s *E2ETestSuite) SetupSuite() { - s.T().Log("setting up e2e test suite") - - var err error - s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - val := s.network.GetValidators()[0] - clientCtx := val.GetClientCtx() - var resp sdk.TxResponse - - // create a proposal with deposit - out, err := govclitestutil.MsgSubmitLegacyProposal(val.GetClientCtx(), val.GetAddress().String(), - "Text Proposal 1", "Where is the title!?", v1beta1.ProposalTypeText, - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens).String())) - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) - - // vote for proposal - out, err = govclitestutil.MsgVote(val.GetClientCtx(), val.GetAddress().String(), "1", "yes") - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) - - // create a proposal with a small deposit - minimumAcceptedDep := v1.DefaultMinDepositTokens.ToLegacyDec().Mul(v1.DefaultMinDepositRatio).Ceil().TruncateInt() - out, err = govclitestutil.MsgSubmitLegacyProposal(val.GetClientCtx(), val.GetAddress().String(), - "Text Proposal 2", "Where is the title!?", v1beta1.ProposalTypeText, - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, minimumAcceptedDep).String())) - - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) - - // create a proposal3 with deposit - out, err = govclitestutil.MsgSubmitLegacyProposal(val.GetClientCtx(), val.GetAddress().String(), - "Text Proposal 3", "Where is the title!?", v1beta1.ProposalTypeText, - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens).String())) - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) - - // create a proposal4 with deposit to check the cancel proposal cli tx - out, err = govclitestutil.MsgSubmitLegacyProposal(val.GetClientCtx(), val.GetAddress().String(), - "Text Proposal 4", "Where is the title!?", v1beta1.ProposalTypeText, - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens).String())) - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) - - // vote for proposal3 as val - out, err = govclitestutil.MsgVote(val.GetClientCtx(), val.GetAddress().String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) -} - -func (s *E2ETestSuite) TearDownSuite() { - s.T().Log("tearing down e2e test suite") - s.network.Cleanup() -} - -func (s *E2ETestSuite) TestNewCmdSubmitProposal() { - val := s.network.GetValidators()[0] - - // Create a legacy proposal JSON, make sure it doesn't pass this new CLI - // command. - invalidProp := `{ - "title": "", - "description": "Where is the title!?", - "type": "Text", - "deposit": "-324foocoin" -}` - invalidPropFile := testutil.WriteToNewTempFile(s.T(), invalidProp) - defer invalidPropFile.Close() - - // Create a valid new proposal JSON. - propMetadata := []byte{42} - validProp := fmt.Sprintf(` -{ - "messages": [ - { - "@type": "/cosmos.gov.v1.MsgExecLegacyContent", - "authority": "%s", - "content": { - "@type": "/cosmos.gov.v1beta1.TextProposal", - "title": "My awesome title", - "description": "My awesome description" - } - } - ], - "title": "My awesome title", - "summary": "My awesome description", - "metadata": "%s", - "deposit": "%s" -}`, authtypes.NewModuleAddress(types.ModuleName), base64.StdEncoding.EncodeToString(propMetadata), sdk.NewCoin(s.cfg.BondDenom, math.NewInt(100000))) - validPropFile := testutil.WriteToNewTempFile(s.T(), validProp) - defer validPropFile.Close() - - testCases := []struct { - name string - args []string - expectErr bool - expectedCode uint32 - respType proto.Message - }{ - { - "invalid proposal", - []string{ - invalidPropFile.Name(), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, nil, - }, - { - "valid proposal", - []string{ - validPropFile.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, &sdk.TxResponse{}, - }, - } - - for _, tc := range testCases { - s.Run(tc.name, func() { - cmd := cli.NewCmdSubmitProposal() - clientCtx := val.GetClientCtx() - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - txResp := tc.respType.(*sdk.TxResponse) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, txResp.TxHash, tc.expectedCode)) - } - }) - } -} - -func (s *E2ETestSuite) TestNewCmdSubmitLegacyProposal() { - val := s.network.GetValidators()[0] - invalidProp := `{ - "title": "", - "description": "Where is the title!?", - "type": "Text", - "deposit": "-324foocoin" - }` - invalidPropFile := testutil.WriteToNewTempFile(s.T(), invalidProp) - defer invalidPropFile.Close() - validProp := fmt.Sprintf(`{ - "title": "Text Proposal", - "description": "Hello, World!", - "type": "Text", - "deposit": "%s" - }`, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(154310))) - validPropFile := testutil.WriteToNewTempFile(s.T(), validProp) - defer validPropFile.Close() - - testCases := []struct { - name string - args []string - expectErr bool - expectedCode uint32 - respType proto.Message - }{ - { - "invalid proposal (file)", - []string{ - fmt.Sprintf("--%s=%s", cli.FlagProposal, invalidPropFile.Name()), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, nil, - }, - { - "invalid proposal", - []string{ - fmt.Sprintf("--%s='Where is the title!?'", cli.FlagDescription), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", cli.FlagProposalType, v1beta1.ProposalTypeText), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10000)).String()), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, nil, - }, - { - "valid transaction (file)", - //nolint:staticcheck // we are intentionally using a deprecated flag here. - []string{ - fmt.Sprintf("--%s=%s", cli.FlagProposal, validPropFile.Name()), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, &sdk.TxResponse{}, - }, - { - "valid transaction", - []string{ - fmt.Sprintf("--%s='Text Proposal'", cli.FlagTitle), - fmt.Sprintf("--%s='Where is the title!?'", cli.FlagDescription), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", cli.FlagProposalType, v1beta1.ProposalTypeText), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(100000)).String()), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, &sdk.TxResponse{}, - }, - } - - for _, tc := range testCases { - s.Run(tc.name, func() { - cmd := cli.NewCmdSubmitLegacyProposal() - clientCtx := val.GetClientCtx() - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - txResp := tc.respType.(*sdk.TxResponse) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, txResp.TxHash, tc.expectedCode)) - } - }) - } -} - -func (s *E2ETestSuite) TestNewCmdWeightedVote() { - val := s.network.GetValidators()[0] - - testCases := []struct { - name string - args []string - expectErr bool - expectedCode uint32 - }{ - { - "invalid vote", - []string{}, - true, 0, - }, - { - "vote for invalid proposal", - []string{ - "10", - "yes", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 3, - }, - { - "valid vote", - []string{ - "1", - "yes", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, - }, - { - "valid vote with metadata", - []string{ - "1", - "yes", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--metadata=%s", "AQ=="), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, - }, - { - "invalid valid split vote string", - []string{ - "1", - "yes/0.6,no/0.3,abstain/0.05,no_with_veto/0.05", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, - }, - { - "valid split vote", - []string{ - "1", - "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, - }, - } - - for _, tc := range testCases { - s.Run(tc.name, func() { - cmd := cli.NewCmdWeightedVote() - clientCtx := val.GetClientCtx() - var txResp sdk.TxResponse - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, txResp.TxHash, tc.expectedCode)) - } - }) - } -} diff --git a/tests/systemtests/gov_test.go b/tests/systemtests/gov_test.go new file mode 100644 index 000000000000..73bc7fd96efc --- /dev/null +++ b/tests/systemtests/gov_test.go @@ -0,0 +1,411 @@ +//go:build system_test + +package systemtests + +import ( + "encoding/base64" + "fmt" + "testing" + "time" + + "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" +) + +func TestSubmitProposal(t *testing.T) { + // given a running chain + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + // get validator address + valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() + require.NotEmpty(t, valAddr) + + sut.StartChain(t) + + // get gov module address + resp := cli.CustomQuery("q", "auth", "module-account", "gov") + govAddress := gjson.Get(resp, "account.value.address").String() + + invalidProp := `{ + "title": "", + "description": "Where is the title!?", + "type": "Text", + "deposit": "-324foocoin" +}` + invalidPropFile := testutil.WriteToNewTempFile(t, invalidProp) + defer invalidPropFile.Close() + + // Create a valid new proposal JSON. + propMetadata := []byte{42} + validProp := fmt.Sprintf(` +{ + "messages": [ + { + "@type": "/cosmos.gov.v1.MsgExecLegacyContent", + "authority": "%s", + "content": { + "@type": "/cosmos.gov.v1beta1.TextProposal", + "title": "My awesome title", + "description": "My awesome description" + } + } + ], + "title": "My awesome title", + "summary": "My awesome description", + "metadata": "%s", + "deposit": "%s" +}`, govAddress, base64.StdEncoding.EncodeToString(propMetadata), sdk.NewCoin("stake", math.NewInt(100000))) + validPropFile := testutil.WriteToNewTempFile(t, validProp) + defer validPropFile.Close() + + testCases := []struct { + name string + args []string + expectErr bool + errMsg string + }{ + { + "invalid proposal", + []string{ + "tx", "gov", "submit-proposal", + invalidPropFile.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + true, + "invalid character in coin string", + }, + { + "valid proposal", + []string{ + "tx", "gov", "submit-proposal", + validPropFile.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, + "", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if tc.expectErr { + assertOutput := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { + require.Contains(t, gotOutputs[0], tc.errMsg) + return false + } + + cli.WithRunErrorMatcher(assertOutput).Run(tc.args...) + } else { + rsp := cli.Run(tc.args...) + txResult, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) + RequireTxSuccess(t, txResult) + } + }) + } +} + +func TestSubmitLegacyProposal(t *testing.T) { + // given a running chain + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + // get validator address + valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() + require.NotEmpty(t, valAddr) + + sut.StartChain(t) + + invalidProp := `{ + "title": "", + "description": "Where is the title!?", + "type": "Text", + "deposit": "-324foocoin" + }` + invalidPropFile := testutil.WriteToNewTempFile(t, invalidProp) + defer invalidPropFile.Close() + + validProp := fmt.Sprintf(`{ + "title": "Text Proposal", + "description": "Hello, World!", + "type": "Text", + "deposit": "%s" + }`, sdk.NewCoin("stake", math.NewInt(154310))) + validPropFile := testutil.WriteToNewTempFile(t, validProp) + defer validPropFile.Close() + + testCases := []struct { + name string + args []string + expectErr bool + errMsg string + }{ + { + "invalid proposal (file)", + []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s=%s", "proposal", invalidPropFile.Name()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + true, + "proposal title is required", + }, + { + "invalid proposal", + []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s='Where is the title!?'", "description"), + fmt.Sprintf("--%s=%s", "type", "Text"), + fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(10000)).String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + true, + "proposal title is required", + }, + { + "valid transaction (file)", + []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s=%s", "proposal", validPropFile.Name()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, + "", + }, + { + "valid transaction", + []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s='Text Proposal'", "title"), + fmt.Sprintf("--%s='Where is the title!?'", "description"), + fmt.Sprintf("--%s=%s", "type", "Text"), + fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(100000)).String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, + "", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if tc.expectErr { + assertOutput := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { + fmt.Println("gotOut", gotOutputs) + require.Contains(t, gotOutputs[0], tc.errMsg) + return false + } + + cli.WithRunErrorMatcher(assertOutput).Run(tc.args...) + } else { + rsp := cli.Run(tc.args...) + txResult, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) + RequireTxSuccess(t, txResult) + } + }) + } +} + +func TestNewCmdWeightedVote(t *testing.T) { + // given a running chain + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + // get validator address + valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() + require.NotEmpty(t, valAddr) + + sut.StartChain(t) + + // Submit a new proposal for voting + proposalArgs := []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s='Text Proposal'", "title"), + fmt.Sprintf("--%s='Where is the title!?'", "description"), + fmt.Sprintf("--%s=%s", "type", "Text"), + fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(10_000_000)).String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String())} + rsp := cli.Run(proposalArgs...) + txResult, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) + RequireTxSuccess(t, txResult) + + proposalsResp := cli.CustomQuery("q", "gov", "proposals") + proposals := gjson.Get(proposalsResp, "proposals.#.id").Array() + require.NotEmpty(t, proposals) + + proposal1 := cli.CustomQuery("q", "gov", "proposal", "1") + fmt.Println("first proposal", proposal1) + + testCases := []struct { + name string + args []string + expectErr bool + expectedCode uint32 + broadcasted bool + errMsg string + }{ + { + "vote for invalid proposal", + []string{ + "tx", "gov", "weighted-vote", + "10", + "yes", + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + true, 3, true, + "inactive proposal", + }, + { + "valid vote", + []string{ + "tx", "gov", "weighted-vote", + "1", + "yes", + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, 0, true, + "", + }, + { + "valid vote with metadata", + []string{ + "tx", "gov", "weighted-vote", + "1", + "yes", + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--metadata=%s", "AQ=="), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, 0, true, + "", + }, + { + "invalid valid split vote string", + []string{ + "tx", "gov", "weighted-vote", + "1", + "yes/0.6,no/0.3,abstain/0.05,no_with_veto/0.05", + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + true, 0, false, + "is not a valid vote option", + }, + { + "valid split vote", + []string{ + "tx", "gov", "weighted-vote", + "1", + "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05", + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, 0, true, + "", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if !tc.broadcasted { + assertOutput := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { + require.Contains(t, gotOutputs[0], tc.errMsg) + return false + } + cli.WithRunErrorMatcher(assertOutput).Run(tc.args...) + } else { + rsp := cli.Run(tc.args...) + if tc.expectErr { + RequireTxFailure(t, rsp) + } else { + cli.AwaitTxCommitted(rsp) + } + } + }) + } +} + +func TestQueryDeposit(t *testing.T) { + // given a running chain + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + // get validator address + valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() + require.NotEmpty(t, valAddr) + + sut.StartChain(t) + + // Submit a new proposal for voting + proposalArgs := []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s='Text Proposal'", "title"), + fmt.Sprintf("--%s='Where is the title!?'", "description"), + fmt.Sprintf("--%s=%s", "type", "Text"), + fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(10_000_000)).String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String())} + rsp := cli.Run(proposalArgs...) + txResult, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) + RequireTxSuccess(t, txResult) + + // Query initial deposit + resp := cli.CustomQuery("q", "gov", "deposit", "1", valAddr) + depositAmount := gjson.Get(resp, "deposit.amount.0.amount").Int() + require.Equal(t, depositAmount, int64(10_000_000)) + + resp = cli.CustomQuery("q", "gov", "deposits", "1") + deposits := gjson.Get(resp, "deposits").Array() + require.Equal(t, len(deposits), 1) + + time.Sleep(time.Second * 8) + resp = cli.CustomQuery("q", "gov", "deposits", "1") + deposits = gjson.Get(resp, "deposits").Array() + require.Equal(t, len(deposits), 0) +} diff --git a/tests/systemtests/system.go b/tests/systemtests/system.go index d76d482b89e2..028645956d85 100644 --- a/tests/systemtests/system.go +++ b/tests/systemtests/system.go @@ -132,6 +132,11 @@ func (s *SystemUnderTest) SetupChain() { if err != nil { panic(fmt.Sprintf("failed set block max gas: %s", err)) } + // Short period for gov + genesisBz, err = sjson.SetRawBytes(genesisBz, "app_state.gov.params.voting_period", []byte(fmt.Sprintf(`"%s"`, "8s"))) + if err != nil { + panic(fmt.Sprintf("failed set block max gas: %s", err)) + } s.withEachNodeHome(func(i int, home string) { if err := saveGenesis(home, genesisBz); err != nil { panic(err)