github.com/Finschia/finschia-sdk@v0.48.1/x/gov/client/testutil/suite.go (about)

     1  package testutil
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/gogo/protobuf/proto"
     8  	"github.com/stretchr/testify/suite"
     9  
    10  	ostcli "github.com/Finschia/ostracon/libs/cli"
    11  
    12  	"github.com/Finschia/finschia-sdk/client/flags"
    13  	"github.com/Finschia/finschia-sdk/testutil"
    14  	clitestutil "github.com/Finschia/finschia-sdk/testutil/cli"
    15  	"github.com/Finschia/finschia-sdk/testutil/network"
    16  	sdk "github.com/Finschia/finschia-sdk/types"
    17  	"github.com/Finschia/finschia-sdk/x/gov/client/cli"
    18  	"github.com/Finschia/finschia-sdk/x/gov/types"
    19  )
    20  
    21  type IntegrationTestSuite struct {
    22  	suite.Suite
    23  
    24  	cfg     network.Config
    25  	network *network.Network
    26  }
    27  
    28  func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
    29  	return &IntegrationTestSuite{cfg: cfg}
    30  }
    31  
    32  func (s *IntegrationTestSuite) SetupSuite() {
    33  	s.T().Log("setting up integration test suite")
    34  
    35  	s.network = network.New(s.T(), s.cfg)
    36  
    37  	_, err := s.network.WaitForHeight(1)
    38  	s.Require().NoError(err)
    39  
    40  	val := s.network.Validators[0]
    41  
    42  	// create a proposal with deposit
    43  	_, err = MsgSubmitProposal(val.ClientCtx, val.Address.String(),
    44  		"Text Proposal 1", "Where is the title!?", types.ProposalTypeText,
    45  		fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens).String()))
    46  	s.Require().NoError(err)
    47  	_, err = s.network.WaitForHeight(1)
    48  	s.Require().NoError(err)
    49  
    50  	// vote for proposal
    51  	_, err = MsgVote(val.ClientCtx, val.Address.String(), "1", "yes")
    52  	s.Require().NoError(err)
    53  
    54  	// create a proposal without deposit
    55  	_, err = MsgSubmitProposal(val.ClientCtx, val.Address.String(),
    56  		"Text Proposal 2", "Where is the title!?", types.ProposalTypeText)
    57  	s.Require().NoError(err)
    58  	_, err = s.network.WaitForHeight(1)
    59  	s.Require().NoError(err)
    60  
    61  	// create a proposal3 with deposit
    62  	_, err = MsgSubmitProposal(val.ClientCtx, val.Address.String(),
    63  		"Text Proposal 3", "Where is the title!?", types.ProposalTypeText,
    64  		fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens).String()))
    65  	s.Require().NoError(err)
    66  	_, err = s.network.WaitForHeight(1)
    67  	s.Require().NoError(err)
    68  
    69  	// vote for proposal3 as val
    70  	_, err = MsgVote(val.ClientCtx, val.Address.String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05")
    71  	s.Require().NoError(err)
    72  }
    73  
    74  func (s *IntegrationTestSuite) TearDownSuite() {
    75  	s.T().Log("tearing down integration test suite")
    76  	s.network.Cleanup()
    77  }
    78  
    79  func (s *IntegrationTestSuite) TestCmdParams() {
    80  	val := s.network.Validators[0]
    81  
    82  	testCases := []struct {
    83  		name           string
    84  		args           []string
    85  		expectedOutput string
    86  	}{
    87  		{
    88  			"json output",
    89  			[]string{fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
    90  			`{"voting_params":{"voting_period":"172800000000000"},"tally_params":{"quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto_threshold":"0.334000000000000000"},"deposit_params":{"min_deposit":[{"denom":"stake","amount":"10000000"}],"max_deposit_period":"172800000000000"}}`,
    91  		},
    92  		{
    93  			"text output",
    94  			[]string{},
    95  			`
    96  deposit_params:
    97    max_deposit_period: "172800000000000"
    98    min_deposit:
    99    - amount: "10000000"
   100      denom: stake
   101  tally_params:
   102    quorum: "0.334000000000000000"
   103    threshold: "0.500000000000000000"
   104    veto_threshold: "0.334000000000000000"
   105  voting_params:
   106    voting_period: "172800000000000"
   107  	`,
   108  		},
   109  	}
   110  
   111  	for _, tc := range testCases {
   112  		tc := tc
   113  
   114  		s.Run(tc.name, func() {
   115  			cmd := cli.GetCmdQueryParams()
   116  			clientCtx := val.ClientCtx
   117  
   118  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   119  			s.Require().NoError(err)
   120  			s.Require().Equal(strings.TrimSpace(tc.expectedOutput), strings.TrimSpace(out.String()))
   121  		})
   122  	}
   123  }
   124  
   125  func (s *IntegrationTestSuite) TestCmdParam() {
   126  	val := s.network.Validators[0]
   127  
   128  	testCases := []struct {
   129  		name           string
   130  		args           []string
   131  		expectedOutput string
   132  	}{
   133  		{
   134  			"voting params",
   135  			[]string{
   136  				"voting",
   137  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   138  			},
   139  			`{"voting_period":"172800000000000"}`,
   140  		},
   141  		{
   142  			"tally params",
   143  			[]string{
   144  				"tallying",
   145  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   146  			},
   147  			`{"quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto_threshold":"0.334000000000000000"}`,
   148  		},
   149  		{
   150  			"deposit params",
   151  			[]string{
   152  				"deposit",
   153  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   154  			},
   155  			`{"min_deposit":[{"denom":"stake","amount":"10000000"}],"max_deposit_period":"172800000000000"}`,
   156  		},
   157  	}
   158  
   159  	for _, tc := range testCases {
   160  		tc := tc
   161  
   162  		s.Run(tc.name, func() {
   163  			cmd := cli.GetCmdQueryParam()
   164  			clientCtx := val.ClientCtx
   165  
   166  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   167  			s.Require().NoError(err)
   168  			s.Require().Equal(strings.TrimSpace(tc.expectedOutput), strings.TrimSpace(out.String()))
   169  		})
   170  	}
   171  }
   172  
   173  func (s *IntegrationTestSuite) TestCmdProposer() {
   174  	val := s.network.Validators[0]
   175  
   176  	testCases := []struct {
   177  		name           string
   178  		args           []string
   179  		expectErr      bool
   180  		expectedOutput string
   181  	}{
   182  		{
   183  			"without proposal id",
   184  			[]string{
   185  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   186  			},
   187  			true,
   188  			``,
   189  		},
   190  		{
   191  			"json output",
   192  			[]string{
   193  				"1",
   194  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   195  			},
   196  			false,
   197  			fmt.Sprintf("{\"proposal_id\":\"%s\",\"proposer\":\"%s\"}", "1", val.Address.String()),
   198  		},
   199  	}
   200  
   201  	for _, tc := range testCases {
   202  		tc := tc
   203  
   204  		s.Run(tc.name, func() {
   205  			cmd := cli.GetCmdQueryProposer()
   206  			clientCtx := val.ClientCtx
   207  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   208  
   209  			if tc.expectErr {
   210  				s.Require().Error(err)
   211  			} else {
   212  				s.Require().NoError(err)
   213  				s.Require().Equal(strings.TrimSpace(tc.expectedOutput), strings.TrimSpace(out.String()))
   214  			}
   215  		})
   216  	}
   217  }
   218  
   219  func (s *IntegrationTestSuite) TestCmdTally() {
   220  	val := s.network.Validators[0]
   221  
   222  	testCases := []struct {
   223  		name           string
   224  		args           []string
   225  		expectErr      bool
   226  		expectedOutput types.TallyResult
   227  	}{
   228  		{
   229  			"without proposal id",
   230  			[]string{
   231  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   232  			},
   233  			true,
   234  			types.TallyResult{},
   235  		},
   236  		{
   237  			"json output",
   238  			[]string{
   239  				"2",
   240  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   241  			},
   242  			false,
   243  			types.NewTallyResult(sdk.NewInt(0), sdk.NewInt(0), sdk.NewInt(0), sdk.NewInt(0)),
   244  		},
   245  		{
   246  			"json output",
   247  			[]string{
   248  				"1",
   249  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   250  			},
   251  			false,
   252  			types.NewTallyResult(s.cfg.BondedTokens, sdk.NewInt(0), sdk.NewInt(0), sdk.NewInt(0)),
   253  		},
   254  	}
   255  
   256  	for _, tc := range testCases {
   257  		tc := tc
   258  
   259  		s.Run(tc.name, func() {
   260  			cmd := cli.GetCmdQueryTally()
   261  			clientCtx := val.ClientCtx
   262  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   263  
   264  			if tc.expectErr {
   265  				s.Require().Error(err)
   266  			} else {
   267  				var tally types.TallyResult
   268  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &tally), out.String())
   269  				s.Require().Equal(tally, tc.expectedOutput)
   270  			}
   271  		})
   272  	}
   273  }
   274  
   275  func (s *IntegrationTestSuite) TestNewCmdSubmitProposal() {
   276  	val := s.network.Validators[0]
   277  	invalidProp := `{
   278  	  "title": "",
   279  		"description": "Where is the title!?",
   280  		"type": "Text",
   281  	  "deposit": "-324foocoin"
   282  	}`
   283  	invalidPropFile := testutil.WriteToNewTempFile(s.T(), invalidProp)
   284  	validProp := fmt.Sprintf(`{
   285  	  "title": "Text Proposal",
   286  		"description": "Hello, World!",
   287  		"type": "Text",
   288  	  "deposit": "%s"
   289  	}`, sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(5431)))
   290  	validPropFile := testutil.WriteToNewTempFile(s.T(), validProp)
   291  	testCases := []struct {
   292  		name         string
   293  		args         []string
   294  		expectErr    bool
   295  		expectedCode uint32
   296  		respType     proto.Message
   297  	}{
   298  		{
   299  			"invalid proposal (file)",
   300  			[]string{
   301  				fmt.Sprintf("--%s=%s", cli.FlagProposal, invalidPropFile.Name()),
   302  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   303  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   304  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   305  			},
   306  			true, 0, nil,
   307  		},
   308  		{
   309  			"invalid proposal",
   310  			[]string{
   311  				fmt.Sprintf("--%s='Where is the title!?'", cli.FlagDescription),
   312  				fmt.Sprintf("--%s=%s", cli.FlagProposalType, types.ProposalTypeText),
   313  				fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(5431)).String()),
   314  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   315  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   316  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   317  			},
   318  			true, 0, nil,
   319  		},
   320  		{
   321  			"valid transaction (file)",
   322  			[]string{
   323  				fmt.Sprintf("--%s=%s", cli.FlagProposal, validPropFile.Name()),
   324  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   325  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   326  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   327  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   328  			},
   329  			false, 0, &sdk.TxResponse{},
   330  		},
   331  		{
   332  			"valid transaction",
   333  			[]string{
   334  				fmt.Sprintf("--%s='Text Proposal'", cli.FlagTitle),
   335  				fmt.Sprintf("--%s='Where is the title!?'", cli.FlagDescription),
   336  				fmt.Sprintf("--%s=%s", cli.FlagProposalType, types.ProposalTypeText),
   337  				fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(5431)).String()),
   338  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   339  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   340  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   341  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   342  			},
   343  			false, 0, &sdk.TxResponse{},
   344  		},
   345  	}
   346  
   347  	for _, tc := range testCases {
   348  		tc := tc
   349  
   350  		s.Run(tc.name, func() {
   351  			cmd := cli.NewCmdSubmitProposal()
   352  			clientCtx := val.ClientCtx
   353  
   354  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   355  			if tc.expectErr {
   356  				s.Require().Error(err)
   357  			} else {
   358  				s.Require().NoError(err)
   359  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   360  				txResp := tc.respType.(*sdk.TxResponse)
   361  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
   362  			}
   363  		})
   364  	}
   365  }
   366  
   367  func (s *IntegrationTestSuite) TestCmdGetProposal() {
   368  	val := s.network.Validators[0]
   369  
   370  	title := "Text Proposal 1"
   371  
   372  	testCases := []struct {
   373  		name      string
   374  		args      []string
   375  		expectErr bool
   376  	}{
   377  		{
   378  			"get non existing proposal",
   379  			[]string{
   380  				"10",
   381  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   382  			},
   383  			true,
   384  		},
   385  		{
   386  			"get proposal with json response",
   387  			[]string{
   388  				"1",
   389  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   390  			},
   391  			false,
   392  		},
   393  	}
   394  
   395  	for _, tc := range testCases {
   396  		tc := tc
   397  
   398  		s.Run(tc.name, func() {
   399  			cmd := cli.GetCmdQueryProposal()
   400  			clientCtx := val.ClientCtx
   401  
   402  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   403  			if tc.expectErr {
   404  				s.Require().Error(err)
   405  			} else {
   406  				s.Require().NoError(err)
   407  				var proposal types.Proposal
   408  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &proposal), out.String())
   409  				s.Require().Equal(title, proposal.GetTitle())
   410  			}
   411  		})
   412  	}
   413  }
   414  
   415  func (s *IntegrationTestSuite) TestCmdGetProposals() {
   416  	val := s.network.Validators[0]
   417  
   418  	testCases := []struct {
   419  		name      string
   420  		args      []string
   421  		expectErr bool
   422  	}{
   423  		{
   424  			"get proposals as json response",
   425  			[]string{
   426  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   427  			},
   428  			false,
   429  		},
   430  		{
   431  			"get proposals with invalid status",
   432  			[]string{
   433  				"--status=unknown",
   434  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   435  			},
   436  			true,
   437  		},
   438  		{
   439  			"wrong number of arguments",
   440  			[]string{
   441  				"extra",
   442  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   443  			},
   444  			true,
   445  		},
   446  	}
   447  
   448  	for _, tc := range testCases {
   449  		tc := tc
   450  
   451  		s.Run(tc.name, func() {
   452  			cmd := cli.GetCmdQueryProposals()
   453  			clientCtx := val.ClientCtx
   454  
   455  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   456  			if tc.expectErr {
   457  				s.Require().Error(err)
   458  			} else {
   459  				s.Require().NoError(err)
   460  				var proposals types.QueryProposalsResponse
   461  
   462  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &proposals), out.String())
   463  				s.Require().Len(proposals.Proposals, 3)
   464  			}
   465  		})
   466  	}
   467  }
   468  
   469  func (s *IntegrationTestSuite) TestCmdQueryDeposits() {
   470  	val := s.network.Validators[0]
   471  
   472  	testCases := []struct {
   473  		name      string
   474  		args      []string
   475  		expectErr bool
   476  	}{
   477  		{
   478  			"get deposits of non existing proposal",
   479  			[]string{
   480  				"10",
   481  			},
   482  			true,
   483  		},
   484  		{
   485  			"get deposits(valid req)",
   486  			[]string{
   487  				"1",
   488  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   489  			},
   490  			false,
   491  		},
   492  	}
   493  
   494  	for _, tc := range testCases {
   495  		tc := tc
   496  		s.Run(tc.name, func() {
   497  			cmd := cli.GetCmdQueryDeposits()
   498  			clientCtx := val.ClientCtx
   499  
   500  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   501  
   502  			if tc.expectErr {
   503  				s.Require().Error(err)
   504  			} else {
   505  				s.Require().NoError(err)
   506  
   507  				var deposits types.QueryDepositsResponse
   508  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &deposits), out.String())
   509  				s.Require().Len(deposits.Deposits, 1)
   510  			}
   511  		})
   512  	}
   513  }
   514  
   515  func (s *IntegrationTestSuite) TestCmdQueryDeposit() {
   516  	val := s.network.Validators[0]
   517  	depositAmount := sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens)
   518  
   519  	testCases := []struct {
   520  		name      string
   521  		args      []string
   522  		expectErr bool
   523  	}{
   524  		{
   525  			"get deposit with no depositer",
   526  			[]string{
   527  				"1",
   528  			},
   529  			true,
   530  		},
   531  		{
   532  			"get deposit with wrong deposit address",
   533  			[]string{
   534  				"1",
   535  				"wrong address",
   536  			},
   537  			true,
   538  		},
   539  		{
   540  			"get deposit (valid req)",
   541  			[]string{
   542  				"1",
   543  				val.Address.String(),
   544  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   545  			},
   546  			false,
   547  		},
   548  	}
   549  
   550  	for _, tc := range testCases {
   551  		tc := tc
   552  		s.Run(tc.name, func() {
   553  			cmd := cli.GetCmdQueryDeposit()
   554  			clientCtx := val.ClientCtx
   555  
   556  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   557  
   558  			if tc.expectErr {
   559  				s.Require().Error(err)
   560  			} else {
   561  				s.Require().NoError(err)
   562  
   563  				var deposit types.Deposit
   564  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &deposit), out.String())
   565  				s.Require().Equal(depositAmount.String(), deposit.Amount.String())
   566  			}
   567  		})
   568  	}
   569  }
   570  
   571  func (s *IntegrationTestSuite) TestNewCmdDeposit() {
   572  	val := s.network.Validators[0]
   573  
   574  	testCases := []struct {
   575  		name         string
   576  		args         []string
   577  		expectErr    bool
   578  		expectedCode uint32
   579  	}{
   580  		{
   581  			"without proposal id",
   582  			[]string{
   583  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), // 10stake
   584  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   585  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   586  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   587  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   588  			},
   589  			true, 0,
   590  		},
   591  		{
   592  			"without deposit amount",
   593  			[]string{
   594  				"1",
   595  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   596  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   597  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   598  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   599  			},
   600  			true, 0,
   601  		},
   602  		{
   603  			"deposit on non existing proposal",
   604  			[]string{
   605  				"10",
   606  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), // 10stake
   607  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   608  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   609  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   610  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   611  			},
   612  			false, 2,
   613  		},
   614  		{
   615  			"deposit on non existing proposal",
   616  			[]string{
   617  				"1",
   618  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), // 10stake
   619  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   620  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   621  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   622  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   623  			},
   624  			false, 0,
   625  		},
   626  	}
   627  
   628  	for _, tc := range testCases {
   629  		tc := tc
   630  		var resp sdk.TxResponse
   631  
   632  		s.Run(tc.name, func() {
   633  			cmd := cli.NewCmdDeposit()
   634  			clientCtx := val.ClientCtx
   635  
   636  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   637  			if tc.expectErr {
   638  				s.Require().Error(err)
   639  			} else {
   640  				s.Require().NoError(err)
   641  
   642  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
   643  				s.Require().Equal(tc.expectedCode, resp.Code, out.String())
   644  			}
   645  		})
   646  	}
   647  }
   648  
   649  func (s *IntegrationTestSuite) TestCmdQueryVotes() {
   650  	val := s.network.Validators[0]
   651  
   652  	testCases := []struct {
   653  		name      string
   654  		args      []string
   655  		expectErr bool
   656  	}{
   657  		{
   658  			"get votes with no proposal id",
   659  			[]string{},
   660  			true,
   661  		},
   662  		{
   663  			"get votes of non existed proposal",
   664  			[]string{
   665  				"10",
   666  			},
   667  			true,
   668  		},
   669  		{
   670  			"vote for invalid proposal",
   671  			[]string{
   672  				"1",
   673  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   674  			},
   675  			false,
   676  		},
   677  	}
   678  
   679  	for _, tc := range testCases {
   680  		tc := tc
   681  		s.Run(tc.name, func() {
   682  			cmd := cli.GetCmdQueryVotes()
   683  			clientCtx := val.ClientCtx
   684  
   685  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   686  
   687  			if tc.expectErr {
   688  				s.Require().Error(err)
   689  			} else {
   690  				s.Require().NoError(err)
   691  
   692  				var votes types.QueryVotesResponse
   693  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &votes), out.String())
   694  				s.Require().Len(votes.Votes, 1)
   695  			}
   696  		})
   697  	}
   698  }
   699  
   700  func (s *IntegrationTestSuite) TestCmdQueryVote() {
   701  	val := s.network.Validators[0]
   702  
   703  	testCases := []struct {
   704  		name           string
   705  		args           []string
   706  		expectErr      bool
   707  		expVoteOptions types.WeightedVoteOptions
   708  	}{
   709  		{
   710  			"get vote of non existing proposal",
   711  			[]string{
   712  				"10",
   713  				val.Address.String(),
   714  			},
   715  			true,
   716  			types.NewNonSplitVoteOption(types.OptionYes),
   717  		},
   718  		{
   719  			"get vote by wrong voter",
   720  			[]string{
   721  				"1",
   722  				"wrong address",
   723  			},
   724  			true,
   725  			types.NewNonSplitVoteOption(types.OptionYes),
   726  		},
   727  		{
   728  			"vote for valid proposal",
   729  			[]string{
   730  				"1",
   731  				val.Address.String(),
   732  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   733  			},
   734  			false,
   735  			types.NewNonSplitVoteOption(types.OptionYes),
   736  		},
   737  		{
   738  			"split vote for valid proposal",
   739  			[]string{
   740  				"3",
   741  				val.Address.String(),
   742  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   743  			},
   744  			false,
   745  			types.WeightedVoteOptions{
   746  				types.WeightedVoteOption{Option: types.OptionYes, Weight: sdk.NewDecWithPrec(60, 2)},
   747  				types.WeightedVoteOption{Option: types.OptionNo, Weight: sdk.NewDecWithPrec(30, 2)},
   748  				types.WeightedVoteOption{Option: types.OptionAbstain, Weight: sdk.NewDecWithPrec(5, 2)},
   749  				types.WeightedVoteOption{Option: types.OptionNoWithVeto, Weight: sdk.NewDecWithPrec(5, 2)},
   750  			},
   751  		},
   752  	}
   753  
   754  	for _, tc := range testCases {
   755  		tc := tc
   756  		s.Run(tc.name, func() {
   757  			cmd := cli.GetCmdQueryVote()
   758  			clientCtx := val.ClientCtx
   759  
   760  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   761  
   762  			if tc.expectErr {
   763  				s.Require().Error(err)
   764  			} else {
   765  				s.Require().NoError(err)
   766  
   767  				var vote types.Vote
   768  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &vote), out.String())
   769  				s.Require().Equal(len(vote.Options), len(tc.expVoteOptions))
   770  				for i, option := range tc.expVoteOptions {
   771  					s.Require().Equal(option.Option, vote.Options[i].Option)
   772  					s.Require().True(option.Weight.Equal(vote.Options[i].Weight))
   773  				}
   774  			}
   775  		})
   776  	}
   777  }
   778  
   779  func (s *IntegrationTestSuite) TestNewCmdVote() {
   780  	val := s.network.Validators[0]
   781  
   782  	testCases := []struct {
   783  		name         string
   784  		args         []string
   785  		expectErr    bool
   786  		expectedCode uint32
   787  	}{
   788  		{
   789  			"invalid vote",
   790  			[]string{},
   791  			true, 0,
   792  		},
   793  		{
   794  			"vote for invalid proposal",
   795  			[]string{
   796  				"10",
   797  				"yes",
   798  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   799  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   800  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   801  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   802  			},
   803  			false, 2,
   804  		},
   805  		{
   806  			"valid vote",
   807  			[]string{
   808  				"1",
   809  				"yes",
   810  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   811  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   812  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   813  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   814  			},
   815  			false, 0,
   816  		},
   817  	}
   818  
   819  	for _, tc := range testCases {
   820  		tc := tc
   821  		s.Run(tc.name, func() {
   822  			cmd := cli.NewCmdVote()
   823  			clientCtx := val.ClientCtx
   824  			var txResp sdk.TxResponse
   825  
   826  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   827  
   828  			if tc.expectErr {
   829  				s.Require().Error(err)
   830  			} else {
   831  				s.Require().NoError(err)
   832  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String())
   833  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
   834  			}
   835  		})
   836  	}
   837  }
   838  
   839  func (s *IntegrationTestSuite) TestNewCmdWeightedVote() {
   840  	val := s.network.Validators[0]
   841  
   842  	testCases := []struct {
   843  		name         string
   844  		args         []string
   845  		expectErr    bool
   846  		expectedCode uint32
   847  	}{
   848  		{
   849  			"invalid vote",
   850  			[]string{},
   851  			true, 0,
   852  		},
   853  		{
   854  			"vote for invalid proposal",
   855  			[]string{
   856  				"10",
   857  				"yes",
   858  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   859  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   860  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   861  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   862  			},
   863  			false, 2,
   864  		},
   865  		{
   866  			"valid vote",
   867  			[]string{
   868  				"1",
   869  				"yes",
   870  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   871  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   872  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   873  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   874  			},
   875  			false, 0,
   876  		},
   877  		{
   878  			"invalid valid split vote string",
   879  			[]string{
   880  				"1",
   881  				"yes/0.6,no/0.3,abstain/0.05,no_with_veto/0.05",
   882  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   883  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   884  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   885  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   886  			},
   887  			true, 0,
   888  		},
   889  		{
   890  			"valid split vote",
   891  			[]string{
   892  				"1",
   893  				"yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05",
   894  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   895  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   896  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   897  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   898  			},
   899  			false, 0,
   900  		},
   901  	}
   902  
   903  	for _, tc := range testCases {
   904  		tc := tc
   905  		s.Run(tc.name, func() {
   906  			cmd := cli.NewCmdWeightedVote()
   907  			clientCtx := val.ClientCtx
   908  			var txResp sdk.TxResponse
   909  
   910  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   911  
   912  			if tc.expectErr {
   913  				s.Require().Error(err)
   914  			} else {
   915  				s.Require().NoError(err)
   916  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String())
   917  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
   918  			}
   919  		})
   920  	}
   921  }