diff --git a/tests/e2e/gov/cli_test.go b/tests/e2e/gov/cli_test.go index ffea40b2351f..c092d20de95f 100644 --- a/tests/e2e/gov/cli_test.go +++ b/tests/e2e/gov/cli_test.go @@ -8,8 +8,8 @@ import ( "time" "cosmossdk.io/simapp" + "github.com/cosmos/cosmos-sdk/testutil/network" - "github.com/cosmos/cosmos-sdk/x/gov/client/testutil" v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" "github.com/stretchr/testify/require" @@ -19,7 +19,7 @@ import ( func TestIntegrationTestSuite(t *testing.T) { cfg := network.DefaultConfig(simapp.NewTestNetworkFixture) cfg.NumValidators = 1 - suite.Run(t, testutil.NewIntegrationTestSuite(cfg)) + suite.Run(t, NewIntegrationTestSuite(cfg)) } func TestDepositTestSuite(t *testing.T) { @@ -33,5 +33,5 @@ func TestDepositTestSuite(t *testing.T) { bz, err := cfg.Codec.MarshalJSON(genesisState) require.NoError(t, err) cfg.GenesisState["gov"] = bz - suite.Run(t, testutil.NewDepositTestSuite(cfg)) + suite.Run(t, NewDepositTestSuite(cfg)) } diff --git a/x/gov/client/testutil/deposits.go b/tests/e2e/gov/deposits.go similarity index 96% rename from x/gov/client/testutil/deposits.go rename to tests/e2e/gov/deposits.go index 3483bdd90dd4..ee5eea0dc622 100644 --- a/x/gov/client/testutil/deposits.go +++ b/tests/e2e/gov/deposits.go @@ -1,4 +1,4 @@ -package testutil +package gov import ( "fmt" @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govclitestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil" v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" ) @@ -72,7 +73,7 @@ func (s *DepositTestSuite) submitProposal(val *network.Validator, initialDeposit exactArgs = append(exactArgs, fmt.Sprintf("--%s=%s", cli.FlagDeposit, initialDeposit.String())) } - _, err := MsgSubmitLegacyProposal( + _, err := govclitestutil.MsgSubmitLegacyProposal( val.ClientCtx, val.Address.String(), fmt.Sprintf("Text Proposal %d", id), @@ -96,7 +97,7 @@ func (s *DepositTestSuite) TestQueryDepositsWithoutInitialDeposit() { // deposit amount depositAmount := sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens.Add(sdk.NewInt(50))).String() - _, err := MsgDeposit(clientCtx, val.Address.String(), proposalID, depositAmount) + _, err := govclitestutil.MsgDeposit(clientCtx, val.Address.String(), proposalID, depositAmount) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) diff --git a/x/gov/client/testutil/grpc.go b/tests/e2e/gov/grpc.go similarity index 99% rename from x/gov/client/testutil/grpc.go rename to tests/e2e/gov/grpc.go index 17dec9e427e3..a185d46e6a82 100644 --- a/x/gov/client/testutil/grpc.go +++ b/tests/e2e/gov/grpc.go @@ -1,4 +1,4 @@ -package testutil +package gov import ( "fmt" diff --git a/x/gov/client/testutil/query.go b/tests/e2e/gov/query.go similarity index 99% rename from x/gov/client/testutil/query.go rename to tests/e2e/gov/query.go index 3cf65d03acac..b19a0b25295e 100644 --- a/x/gov/client/testutil/query.go +++ b/tests/e2e/gov/query.go @@ -1,4 +1,4 @@ -package testutil +package gov import ( "fmt" diff --git a/x/gov/client/testutil/tx.go b/tests/e2e/gov/tx.go similarity index 96% rename from x/gov/client/testutil/tx.go rename to tests/e2e/gov/tx.go index 8ac10c5125ef..dfd3ec1e6a60 100644 --- a/x/gov/client/testutil/tx.go +++ b/tests/e2e/gov/tx.go @@ -1,4 +1,4 @@ -package testutil +package gov import ( "encoding/base64" @@ -15,6 +15,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govclitestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil" "github.com/cosmos/cosmos-sdk/x/gov/types" v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" @@ -42,32 +43,32 @@ func (s *IntegrationTestSuite) SetupSuite() { val := s.network.Validators[0] // create a proposal with deposit - _, err = MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(), + _, err = govclitestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.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(s.network.WaitForNextBlock()) // vote for proposal - _, err = MsgVote(val.ClientCtx, val.Address.String(), "1", "yes") + _, err = govclitestutil.MsgVote(val.ClientCtx, val.Address.String(), "1", "yes") s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) // create a proposal without deposit - _, err = MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(), + _, err = govclitestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(), "Text Proposal 2", "Where is the title!?", v1beta1.ProposalTypeText) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) // create a proposal3 with deposit - _, err = MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(), + _, err = govclitestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.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(s.network.WaitForNextBlock()) // vote for proposal3 as val - _, err = MsgVote(val.ClientCtx, val.Address.String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") + _, err = govclitestutil.MsgVote(val.ClientCtx, val.Address.String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) } diff --git a/x/gov/client/cli/query_test.go b/x/gov/client/cli/query_test.go new file mode 100644 index 000000000000..de38b14ac9cd --- /dev/null +++ b/x/gov/client/cli/query_test.go @@ -0,0 +1,412 @@ +package cli_test + +import ( + "fmt" + "strings" + + tmcli "github.com/tendermint/tendermint/libs/cli" + + "github.com/cosmos/cosmos-sdk/testutil" + "github.com/cosmos/cosmos-sdk/x/gov/client/cli" +) + +func (s *CLITestSuite) TestCmdParams() { + testCases := []struct { + name string + args []string + expCmdOutput string + }{ + { + "json output", + []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + "--output=json", + }, + { + "text output", + []string{}, + "", + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryParams() + cmd.SetArgs(tc.args) + + if len(tc.args) != 0 { + s.Require().Contains(fmt.Sprint(cmd), strings.TrimSpace(tc.expCmdOutput)) + } + }) + } +} + +func (s *CLITestSuite) TestCmdParam() { + testCases := []struct { + name string + args []string + expCmdOutput string + }{ + { + "voting params", + []string{ + "voting", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + `voting --output=json`, + }, + { + "tally params", + []string{ + "tallying", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + `tallying --output=json`, + }, + { + "deposit params", + []string{ + "deposit", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + `deposit --output=json`, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryParam() + cmd.SetArgs(tc.args) + s.Require().Contains(fmt.Sprint(cmd), strings.TrimSpace(tc.expCmdOutput)) + }) + } +} + +func (s *CLITestSuite) TestCmdProposer() { + testCases := []struct { + name string + args []string + expCmdOutput string + }{ + { + "without proposal id", + []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "--output=json", + }, + { + "json output", + []string{ + "1", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "1 --output=json", + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryProposer() + cmd.SetArgs(tc.args) + s.Require().Contains(fmt.Sprint(cmd), strings.TrimSpace(tc.expCmdOutput)) + }) + } +} + +func (s *CLITestSuite) TestCmdTally() { + testCases := []struct { + name string + args []string + expCmdOutput string + }{ + { + "without proposal id", + []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "--output=json", + }, + { + "json output", + []string{ + "2", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "2 --output=json", + }, + { + "json output", + []string{ + "1", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "1 --output=json", + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryTally() + cmd.SetArgs(tc.args) + s.Require().Contains(fmt.Sprint(cmd), strings.TrimSpace(tc.expCmdOutput)) + }) + } +} + +func (s *CLITestSuite) TestCmdGetProposal() { + testCases := []struct { + name string + args []string + expCmdOutput string + }{ + { + "get non existing proposal", + []string{ + "10", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "10 --output=json", + }, + { + "get proposal with json response", + []string{ + "1", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "1 --output=json", + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryProposal() + cmd.SetArgs(tc.args) + s.Require().Contains(fmt.Sprint(cmd), strings.TrimSpace(tc.expCmdOutput)) + }) + } +} + +func (s *CLITestSuite) TestCmdGetProposals() { + testCases := []struct { + name string + args []string + expCmdOutput string + }{ + { + "get proposals as json response", + []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "--output=json", + }, + { + "get proposals with invalid status", + []string{ + "--status=unknown", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "--status=unknown --output=json", + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryProposals() + cmd.SetArgs(tc.args) + s.Require().Contains(fmt.Sprint(cmd), strings.TrimSpace(tc.expCmdOutput)) + }) + } +} + +func (s *CLITestSuite) TestCmdQueryDeposits() { + testCases := []struct { + name string + args []string + expCmdOutput string + }{ + { + "get deposits of non existing proposal", + []string{ + "10", + }, + "10", + }, + { + "get deposits(valid req)", + []string{ + "1", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "1 --output=json", + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryDeposits() + cmd.SetArgs(tc.args) + + if len(tc.args) != 0 { + s.Require().Contains(fmt.Sprint(cmd), strings.TrimSpace(tc.expCmdOutput)) + } + }) + } +} + +func (s *CLITestSuite) TestCmdQueryDeposit() { + val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) + + testCases := []struct { + name string + args []string + expCmdOutput string + }{ + { + "get deposit with no depositer", + []string{ + "1", + }, + "1", + }, + { + "get deposit with wrong deposit address", + []string{ + "1", + "wrong address", + }, + "1 wrong address", + }, + { + "get deposit (valid req)", + []string{ + "1", + val[0].Address.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + fmt.Sprintf("1 %s --output=json", val[0].Address.String()), + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryDeposit() + cmd.SetArgs(tc.args) + + if len(tc.args) != 0 { + s.Require().Contains(fmt.Sprint(cmd), strings.TrimSpace(tc.expCmdOutput)) + } + }) + } +} + +func (s *CLITestSuite) TestCmdQueryVotes() { + testCases := []struct { + name string + args []string + expCmdOutput string + }{ + { + "get votes with no proposal id", + []string{}, + "true", + }, + { + "get votes of non existed proposal", + []string{ + "10", + }, + "10", + }, + { + "vote for invalid proposal", + []string{ + "1", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "1 --output=json", + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryVotes() + cmd.SetArgs(tc.args) + + if len(tc.args) != 0 { + s.Require().Contains(fmt.Sprint(cmd), strings.TrimSpace(tc.expCmdOutput)) + } + }) + } +} + +func (s *CLITestSuite) TestCmdQueryVote() { + val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) + + testCases := []struct { + name string + args []string + expCmdOutput string + }{ + { + "get vote of non existing proposal", + []string{ + "10", + val[0].Address.String(), + }, + fmt.Sprintf("10 %s", val[0].Address.String()), + }, + { + "get vote by wrong voter", + []string{ + "1", + "wrong address", + }, + "1 wrong address", + }, + { + "vote for valid proposal", + []string{ + "1", + val[0].Address.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + fmt.Sprintf("1 %s --output=json", val[0].Address.String()), + }, + { + "split vote for valid proposal", + []string{ + "3", + val[0].Address.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + fmt.Sprintf("3 %s --output=json", val[0].Address.String()), + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryVote() + cmd.SetArgs(tc.args) + + if len(tc.args) != 0 { + s.Require().Contains(fmt.Sprint(cmd), strings.TrimSpace(tc.expCmdOutput)) + } + }) + } +} diff --git a/x/gov/client/cli/tx_test.go b/x/gov/client/cli/tx_test.go new file mode 100644 index 000000000000..1b881c3762ab --- /dev/null +++ b/x/gov/client/cli/tx_test.go @@ -0,0 +1,523 @@ +package cli_test + +import ( + "bytes" + "context" + "encoding/base64" + "fmt" + "io" + "testing" + + "github.com/cosmos/gogoproto/proto" + "github.com/stretchr/testify/suite" + abci "github.com/tendermint/tendermint/abci/types" + tmbytes "github.com/tendermint/tendermint/libs/bytes" + rpcclient "github.com/tendermint/tendermint/rpc/client" + rpcclientmock "github.com/tendermint/tendermint/rpc/client/mock" + coretypes "github.com/tendermint/tendermint/rpc/core/types" + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/testutil" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + sdk "github.com/cosmos/cosmos-sdk/types" + testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/gov" + "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govclitestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil" + "github.com/cosmos/cosmos-sdk/x/gov/types" + v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" +) + +var _ client.TendermintRPC = (*mockTendermintRPC)(nil) + +type mockTendermintRPC struct { + rpcclientmock.Client + + responseQuery abci.ResponseQuery +} + +func newMockTendermintRPC(respQuery abci.ResponseQuery) mockTendermintRPC { + return mockTendermintRPC{responseQuery: respQuery} +} + +func (mockTendermintRPC) BroadcastTxSync(context.Context, tmtypes.Tx) (*coretypes.ResultBroadcastTx, error) { + return &coretypes.ResultBroadcastTx{Code: 0}, nil +} + +func (m mockTendermintRPC) ABCIQueryWithOptions( + _ context.Context, + _ string, _ tmbytes.HexBytes, + _ rpcclient.ABCIQueryOptions, +) (*coretypes.ResultABCIQuery, error) { + return &coretypes.ResultABCIQuery{Response: m.responseQuery}, nil +} + +type CLITestSuite struct { + suite.Suite + + kr keyring.Keyring + encCfg testutilmod.TestEncodingConfig + baseCtx client.Context + clientCtx client.Context +} + +func TestCLITestSuite(t *testing.T) { + suite.Run(t, new(CLITestSuite)) +} + +func (s *CLITestSuite) SetupSuite() { + s.encCfg = testutilmod.MakeTestEncodingConfig(gov.AppModuleBasic{}) + s.kr = keyring.NewInMemory(s.encCfg.Codec) + s.baseCtx = client.Context{}. + WithKeyring(s.kr). + WithTxConfig(s.encCfg.TxConfig). + WithCodec(s.encCfg.Codec). + WithClient(mockTendermintRPC{Client: rpcclientmock.Client{}}). + WithAccountRetriever(client.MockAccountRetriever{}). + WithOutput(io.Discard). + WithChainID("test-chain") + + var outBuf bytes.Buffer + ctxGen := func() client.Context { + bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{}) + c := newMockTendermintRPC(abci.ResponseQuery{ + Value: bz, + }) + return s.baseCtx.WithClient(c) + } + s.clientCtx = ctxGen().WithOutput(&outBuf) + + val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) + + // create a proposal with deposit + _, err := govclitestutil.MsgSubmitLegacyProposal(s.clientCtx, val[0].Address.String(), + "Text Proposal 1", "Where is the title!?", v1beta1.ProposalTypeText, + fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin("stake", v1.DefaultMinDepositTokens).String())) + s.Require().NoError(err) + + // vote for proposal + _, err = govclitestutil.MsgVote(s.clientCtx, val[0].Address.String(), "1", "yes") + s.Require().NoError(err) + + // create a proposal without deposit + _, err = govclitestutil.MsgSubmitLegacyProposal(s.clientCtx, val[0].Address.String(), + "Text Proposal 2", "Where is the title!?", v1beta1.ProposalTypeText) + s.Require().NoError(err) + + // create a proposal3 with deposit + _, err = govclitestutil.MsgSubmitLegacyProposal(s.clientCtx, val[0].Address.String(), + "Text Proposal 3", "Where is the title!?", v1beta1.ProposalTypeText, + fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin("stake", v1.DefaultMinDepositTokens).String())) + s.Require().NoError(err) + + // vote for proposal3 as val + _, err = govclitestutil.MsgVote(s.clientCtx, val[0].Address.String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") + s.Require().NoError(err) +} + +func (s *CLITestSuite) TestNewCmdSubmitProposal() { + val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) + + // 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" + } + } + ], + "metadata": "%s", + "deposit": "%s" + }`, authtypes.NewModuleAddress(types.ModuleName), base64.StdEncoding.EncodeToString(propMetadata), sdk.NewCoin("stake", sdk.NewInt(5431))) + validPropFile := testutil.WriteToNewTempFile(s.T(), validProp) + defer validPropFile.Close() + + testCases := []struct { + name string + args []string + expectErr bool + respType proto.Message + }{ + { + "invalid proposal", + []string{ + invalidPropFile.Name(), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(10))).String()), + }, + true, nil, + }, + { + "valid proposal", + []string{ + validPropFile.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + false, &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.NewCmdSubmitProposal() + + out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *CLITestSuite) TestNewCmdSubmitLegacyProposal() { + val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) + + 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("stake", sdk.NewInt(5431))) + validPropFile := testutil.WriteToNewTempFile(s.T(), validProp) + defer validPropFile.Close() + + testCases := []struct { + name string + args []string + expectErr bool + 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[0].Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(10))).String()), + }, + true, 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("stake", sdk.NewInt(5431)).String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(10))).String()), + }, + true, 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[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + false, &sdk.TxResponse{}, + }, + { + "valid transaction", + []string{ + fmt.Sprintf("--%s='Text Proposal'", cli.FlagTitle), //nolint:staticcheck // we are intentionally using a deprecated flag here. + 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("stake", sdk.NewInt(5431)).String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + false, &sdk.TxResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.NewCmdSubmitLegacyProposal() + + out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + } + }) + } +} + +func (s *CLITestSuite) TestNewCmdDeposit() { + val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) + + testCases := []struct { + name string + args []string + expectErr bool + }{ + { + "without proposal id", + []string{ + sdk.NewCoin("stake", sdk.NewInt(10)).String(), // 10stake + fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + true, + }, + { + "without deposit amount", + []string{ + "1", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + true, + }, + { + "deposit on non existing proposal", + []string{ + "10", + sdk.NewCoin("stake", sdk.NewInt(10)).String(), // 10stake + fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + false, + }, + } + + for _, tc := range testCases { + tc := tc + var resp sdk.TxResponse + + s.Run(tc.name, func() { + cmd := cli.NewCmdDeposit() + + out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) + } + }) + } +} + +func (s *CLITestSuite) TestNewCmdVote() { + val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) + + 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[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + false, 3, + }, + { + "valid vote", + []string{ + "1", + "yes", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + false, 0, + }, + { + "valid vote with metadata", + []string{ + "1", + "yes", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + false, 0, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.NewCmdVote() + var txResp sdk.TxResponse + + out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + } + }) + } +} + +func (s *CLITestSuite) TestNewCmdWeightedVote() { + val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) + + 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[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + false, 3, + }, + { + "valid vote", + []string{ + "1", + "yes", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + false, 0, + }, + { + "valid vote with metadata", + []string{ + "1", + "yes", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.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("stake", sdk.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[0].Address.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("stake", sdk.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[0].Address.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("stake", sdk.NewInt(10))).String()), + }, + false, 0, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.NewCmdWeightedVote() + var txResp sdk.TxResponse + + out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + } + }) + } +}