github.com/Finschia/finschia-sdk@v0.48.1/x/gov/keeper/grpc_query_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	gocontext "context"
     5  	"fmt"
     6  	"strconv"
     7  
     8  	"github.com/Finschia/finschia-sdk/simapp"
     9  	sdk "github.com/Finschia/finschia-sdk/types"
    10  	"github.com/Finschia/finschia-sdk/types/query"
    11  	"github.com/Finschia/finschia-sdk/x/gov/types"
    12  )
    13  
    14  func (suite *KeeperTestSuite) TestGRPCQueryProposal() {
    15  	app, ctx, queryClient := suite.app, suite.ctx, suite.queryClient
    16  
    17  	var (
    18  		req         *types.QueryProposalRequest
    19  		expProposal types.Proposal
    20  	)
    21  
    22  	testCases := []struct {
    23  		msg      string
    24  		malleate func()
    25  		expPass  bool
    26  	}{
    27  		{
    28  			"empty request",
    29  			func() {
    30  				req = &types.QueryProposalRequest{}
    31  			},
    32  			false,
    33  		},
    34  		{
    35  			"non existing proposal request",
    36  			func() {
    37  				req = &types.QueryProposalRequest{ProposalId: 3}
    38  			},
    39  			false,
    40  		},
    41  		{
    42  			"zero proposal id request",
    43  			func() {
    44  				req = &types.QueryProposalRequest{ProposalId: 0}
    45  			},
    46  			false,
    47  		},
    48  		{
    49  			"valid request",
    50  			func() {
    51  				req = &types.QueryProposalRequest{ProposalId: 1}
    52  				testProposal := types.NewTextProposal("Proposal", "testing proposal")
    53  				submittedProposal, err := app.GovKeeper.SubmitProposal(ctx, testProposal)
    54  				suite.Require().NoError(err)
    55  				suite.Require().NotEmpty(submittedProposal)
    56  
    57  				expProposal = submittedProposal
    58  			},
    59  			true,
    60  		},
    61  	}
    62  
    63  	for _, testCase := range testCases {
    64  		suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
    65  			testCase.malleate()
    66  
    67  			proposalRes, err := queryClient.Proposal(gocontext.Background(), req)
    68  
    69  			if testCase.expPass {
    70  				suite.Require().NoError(err)
    71  				suite.Require().Equal(expProposal.String(), proposalRes.Proposal.String())
    72  			} else {
    73  				suite.Require().Error(err)
    74  				suite.Require().Nil(proposalRes)
    75  			}
    76  		})
    77  	}
    78  }
    79  
    80  func (suite *KeeperTestSuite) TestGRPCQueryProposals() {
    81  	app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs
    82  
    83  	testProposals := []types.Proposal{}
    84  
    85  	var (
    86  		req    *types.QueryProposalsRequest
    87  		expRes *types.QueryProposalsResponse
    88  	)
    89  
    90  	testCases := []struct {
    91  		msg      string
    92  		malleate func()
    93  		expPass  bool
    94  	}{
    95  		{
    96  			"empty state request",
    97  			func() {
    98  				req = &types.QueryProposalsRequest{}
    99  			},
   100  			true,
   101  		},
   102  		{
   103  			"request proposals with limit 3",
   104  			func() {
   105  				// create 5 test proposals
   106  				for i := 0; i < 5; i++ {
   107  					num := strconv.Itoa(i + 1)
   108  					testProposal := types.NewTextProposal("Proposal"+num, "testing proposal "+num)
   109  					proposal, err := app.GovKeeper.SubmitProposal(ctx, testProposal)
   110  					suite.Require().NotEmpty(proposal)
   111  					suite.Require().NoError(err)
   112  					testProposals = append(testProposals, proposal)
   113  				}
   114  
   115  				req = &types.QueryProposalsRequest{
   116  					Pagination: &query.PageRequest{Limit: 3},
   117  				}
   118  
   119  				expRes = &types.QueryProposalsResponse{
   120  					Proposals: testProposals[:3],
   121  				}
   122  			},
   123  			true,
   124  		},
   125  		{
   126  			"request 2nd page with limit 4",
   127  			func() {
   128  				req = &types.QueryProposalsRequest{
   129  					Pagination: &query.PageRequest{Offset: 3, Limit: 3},
   130  				}
   131  
   132  				expRes = &types.QueryProposalsResponse{
   133  					Proposals: testProposals[3:],
   134  				}
   135  			},
   136  			true,
   137  		},
   138  		{
   139  			"request with limit 2 and count true",
   140  			func() {
   141  				req = &types.QueryProposalsRequest{
   142  					Pagination: &query.PageRequest{Limit: 2, CountTotal: true},
   143  				}
   144  
   145  				expRes = &types.QueryProposalsResponse{
   146  					Proposals: testProposals[:2],
   147  				}
   148  			},
   149  			true,
   150  		},
   151  		{
   152  			"request with filter of status deposit period",
   153  			func() {
   154  				req = &types.QueryProposalsRequest{
   155  					ProposalStatus: types.StatusDepositPeriod,
   156  				}
   157  
   158  				expRes = &types.QueryProposalsResponse{
   159  					Proposals: testProposals,
   160  				}
   161  			},
   162  			true,
   163  		},
   164  		{
   165  			"request with filter of deposit address",
   166  			func() {
   167  				depositCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 20)))
   168  				deposit := types.NewDeposit(testProposals[0].ProposalId, addrs[0], depositCoins)
   169  				app.GovKeeper.SetDeposit(ctx, deposit)
   170  
   171  				req = &types.QueryProposalsRequest{
   172  					Depositor: addrs[0].String(),
   173  				}
   174  
   175  				expRes = &types.QueryProposalsResponse{
   176  					Proposals: testProposals[:1],
   177  				}
   178  			},
   179  			true,
   180  		},
   181  		{
   182  			"request with filter of deposit address",
   183  			func() {
   184  				testProposals[1].Status = types.StatusVotingPeriod
   185  				app.GovKeeper.SetProposal(ctx, testProposals[1])
   186  				suite.Require().NoError(app.GovKeeper.AddVote(ctx, testProposals[1].ProposalId, addrs[0], types.NewNonSplitVoteOption(types.OptionAbstain)))
   187  
   188  				req = &types.QueryProposalsRequest{
   189  					Voter: addrs[0].String(),
   190  				}
   191  
   192  				expRes = &types.QueryProposalsResponse{
   193  					Proposals: testProposals[1:2],
   194  				}
   195  			},
   196  			true,
   197  		},
   198  	}
   199  
   200  	for _, testCase := range testCases {
   201  		suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
   202  			testCase.malleate()
   203  
   204  			proposals, err := queryClient.Proposals(gocontext.Background(), req)
   205  
   206  			if testCase.expPass {
   207  				suite.Require().NoError(err)
   208  
   209  				suite.Require().Len(proposals.GetProposals(), len(expRes.GetProposals()))
   210  				for i := 0; i < len(proposals.GetProposals()); i++ {
   211  					suite.Require().Equal(proposals.GetProposals()[i].String(), expRes.GetProposals()[i].String())
   212  				}
   213  
   214  			} else {
   215  				suite.Require().Error(err)
   216  				suite.Require().Nil(proposals)
   217  			}
   218  		})
   219  	}
   220  }
   221  
   222  func (suite *KeeperTestSuite) TestGRPCQueryVote() {
   223  	app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs
   224  
   225  	var (
   226  		req      *types.QueryVoteRequest
   227  		expRes   *types.QueryVoteResponse
   228  		proposal types.Proposal
   229  	)
   230  
   231  	testCases := []struct {
   232  		msg      string
   233  		malleate func()
   234  		expPass  bool
   235  	}{
   236  		{
   237  			"empty request",
   238  			func() {
   239  				req = &types.QueryVoteRequest{}
   240  			},
   241  			false,
   242  		},
   243  		{
   244  			"zero proposal id request",
   245  			func() {
   246  				req = &types.QueryVoteRequest{
   247  					ProposalId: 0,
   248  					Voter:      addrs[0].String(),
   249  				}
   250  			},
   251  			false,
   252  		},
   253  		{
   254  			"empty voter request",
   255  			func() {
   256  				req = &types.QueryVoteRequest{
   257  					ProposalId: 1,
   258  					Voter:      "",
   259  				}
   260  			},
   261  			false,
   262  		},
   263  		{
   264  			"non existed proposal",
   265  			func() {
   266  				req = &types.QueryVoteRequest{
   267  					ProposalId: 3,
   268  					Voter:      addrs[0].String(),
   269  				}
   270  			},
   271  			false,
   272  		},
   273  		{
   274  			"no votes present",
   275  			func() {
   276  				var err error
   277  				proposal, err = app.GovKeeper.SubmitProposal(ctx, TestProposal)
   278  				suite.Require().NoError(err)
   279  
   280  				req = &types.QueryVoteRequest{
   281  					ProposalId: proposal.ProposalId,
   282  					Voter:      addrs[0].String(),
   283  				}
   284  
   285  				expRes = &types.QueryVoteResponse{}
   286  			},
   287  			false,
   288  		},
   289  		{
   290  			"valid request",
   291  			func() {
   292  				proposal.Status = types.StatusVotingPeriod
   293  				app.GovKeeper.SetProposal(ctx, proposal)
   294  				suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.NewNonSplitVoteOption(types.OptionAbstain)))
   295  
   296  				req = &types.QueryVoteRequest{
   297  					ProposalId: proposal.ProposalId,
   298  					Voter:      addrs[0].String(),
   299  				}
   300  
   301  				expRes = &types.QueryVoteResponse{Vote: types.Vote{ProposalId: proposal.ProposalId, Voter: addrs[0].String(), Option: types.OptionAbstain, Options: []types.WeightedVoteOption{{Option: types.OptionAbstain, Weight: sdk.MustNewDecFromStr("1.0")}}}}
   302  			},
   303  			true,
   304  		},
   305  		{
   306  			"wrong voter id request",
   307  			func() {
   308  				req = &types.QueryVoteRequest{
   309  					ProposalId: proposal.ProposalId,
   310  					Voter:      addrs[1].String(),
   311  				}
   312  
   313  				expRes = &types.QueryVoteResponse{}
   314  			},
   315  			false,
   316  		},
   317  	}
   318  
   319  	for _, testCase := range testCases {
   320  		suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
   321  			testCase.malleate()
   322  
   323  			vote, err := queryClient.Vote(gocontext.Background(), req)
   324  
   325  			if testCase.expPass {
   326  				suite.Require().NoError(err)
   327  				suite.Require().Equal(expRes, vote)
   328  			} else {
   329  				suite.Require().Error(err)
   330  				suite.Require().Nil(vote)
   331  			}
   332  		})
   333  	}
   334  }
   335  
   336  func (suite *KeeperTestSuite) TestGRPCQueryVotes() {
   337  	app, ctx, queryClient := suite.app, suite.ctx, suite.queryClient
   338  
   339  	addrs := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(30000000))
   340  
   341  	var (
   342  		req      *types.QueryVotesRequest
   343  		expRes   *types.QueryVotesResponse
   344  		proposal types.Proposal
   345  		votes    types.Votes
   346  	)
   347  
   348  	testCases := []struct {
   349  		msg      string
   350  		malleate func()
   351  		expPass  bool
   352  	}{
   353  		{
   354  			"empty request",
   355  			func() {
   356  				req = &types.QueryVotesRequest{}
   357  			},
   358  			false,
   359  		},
   360  		{
   361  			"zero proposal id request",
   362  			func() {
   363  				req = &types.QueryVotesRequest{
   364  					ProposalId: 0,
   365  				}
   366  			},
   367  			false,
   368  		},
   369  		{
   370  			"non existed proposals",
   371  			func() {
   372  				req = &types.QueryVotesRequest{
   373  					ProposalId: 2,
   374  				}
   375  			},
   376  			true,
   377  		},
   378  		{
   379  			"create a proposal and get votes",
   380  			func() {
   381  				var err error
   382  				proposal, err = app.GovKeeper.SubmitProposal(ctx, TestProposal)
   383  				suite.Require().NoError(err)
   384  
   385  				req = &types.QueryVotesRequest{
   386  					ProposalId: proposal.ProposalId,
   387  				}
   388  			},
   389  			true,
   390  		},
   391  		{
   392  			"request after adding 2 votes",
   393  			func() {
   394  				proposal.Status = types.StatusVotingPeriod
   395  				app.GovKeeper.SetProposal(ctx, proposal)
   396  
   397  				votes = []types.Vote{
   398  					{ProposalId: proposal.ProposalId, Voter: addrs[0].String(), Option: types.OptionAbstain, Options: types.NewNonSplitVoteOption(types.OptionAbstain)},
   399  					{ProposalId: proposal.ProposalId, Voter: addrs[1].String(), Option: types.OptionYes, Options: types.NewNonSplitVoteOption(types.OptionYes)},
   400  				}
   401  				accAddr1, err1 := sdk.AccAddressFromBech32(votes[0].Voter)
   402  				accAddr2, err2 := sdk.AccAddressFromBech32(votes[1].Voter)
   403  				suite.Require().NoError(err1)
   404  				suite.Require().NoError(err2)
   405  				suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, accAddr1, votes[0].Options))
   406  				suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, accAddr2, votes[1].Options))
   407  
   408  				req = &types.QueryVotesRequest{
   409  					ProposalId: proposal.ProposalId,
   410  				}
   411  
   412  				expRes = &types.QueryVotesResponse{
   413  					Votes: votes,
   414  				}
   415  			},
   416  			true,
   417  		},
   418  	}
   419  
   420  	for _, testCase := range testCases {
   421  		suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
   422  			testCase.malleate()
   423  
   424  			votes, err := queryClient.Votes(gocontext.Background(), req)
   425  
   426  			if testCase.expPass {
   427  				suite.Require().NoError(err)
   428  				suite.Require().Equal(expRes.GetVotes(), votes.GetVotes())
   429  			} else {
   430  				suite.Require().Error(err)
   431  				suite.Require().Nil(votes)
   432  			}
   433  		})
   434  	}
   435  }
   436  
   437  func (suite *KeeperTestSuite) TestGRPCQueryParams() {
   438  	queryClient := suite.queryClient
   439  
   440  	var (
   441  		req    *types.QueryParamsRequest
   442  		expRes *types.QueryParamsResponse
   443  	)
   444  
   445  	testCases := []struct {
   446  		msg      string
   447  		malleate func()
   448  		expPass  bool
   449  	}{
   450  		{
   451  			"empty request",
   452  			func() {
   453  				req = &types.QueryParamsRequest{}
   454  			},
   455  			false,
   456  		},
   457  		{
   458  			"deposit params request",
   459  			func() {
   460  				req = &types.QueryParamsRequest{ParamsType: types.ParamDeposit}
   461  				expRes = &types.QueryParamsResponse{
   462  					DepositParams: types.DefaultDepositParams(),
   463  					TallyParams:   types.NewTallyParams(sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0)),
   464  				}
   465  			},
   466  			true,
   467  		},
   468  		{
   469  			"voting params request",
   470  			func() {
   471  				req = &types.QueryParamsRequest{ParamsType: types.ParamVoting}
   472  				expRes = &types.QueryParamsResponse{
   473  					VotingParams: types.DefaultVotingParams(),
   474  					TallyParams:  types.NewTallyParams(sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0)),
   475  				}
   476  			},
   477  			true,
   478  		},
   479  		{
   480  			"tally params request",
   481  			func() {
   482  				req = &types.QueryParamsRequest{ParamsType: types.ParamTallying}
   483  				expRes = &types.QueryParamsResponse{
   484  					TallyParams: types.DefaultTallyParams(),
   485  				}
   486  			},
   487  			true,
   488  		},
   489  		{
   490  			"invalid request",
   491  			func() {
   492  				req = &types.QueryParamsRequest{ParamsType: "wrongPath"}
   493  				expRes = &types.QueryParamsResponse{}
   494  			},
   495  			false,
   496  		},
   497  	}
   498  
   499  	for _, testCase := range testCases {
   500  		suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
   501  			testCase.malleate()
   502  
   503  			params, err := queryClient.Params(gocontext.Background(), req)
   504  
   505  			if testCase.expPass {
   506  				suite.Require().NoError(err)
   507  				suite.Require().Equal(expRes.GetDepositParams(), params.GetDepositParams())
   508  				suite.Require().Equal(expRes.GetVotingParams(), params.GetVotingParams())
   509  				suite.Require().Equal(expRes.GetTallyParams(), params.GetTallyParams())
   510  			} else {
   511  				suite.Require().Error(err)
   512  				suite.Require().Nil(params)
   513  			}
   514  		})
   515  	}
   516  }
   517  
   518  func (suite *KeeperTestSuite) TestGRPCQueryDeposit() {
   519  	app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs
   520  
   521  	var (
   522  		req      *types.QueryDepositRequest
   523  		expRes   *types.QueryDepositResponse
   524  		proposal types.Proposal
   525  	)
   526  
   527  	testCases := []struct {
   528  		msg      string
   529  		malleate func()
   530  		expPass  bool
   531  	}{
   532  		{
   533  			"empty request",
   534  			func() {
   535  				req = &types.QueryDepositRequest{}
   536  			},
   537  			false,
   538  		},
   539  		{
   540  			"zero proposal id request",
   541  			func() {
   542  				req = &types.QueryDepositRequest{
   543  					ProposalId: 0,
   544  					Depositor:  addrs[0].String(),
   545  				}
   546  			},
   547  			false,
   548  		},
   549  		{
   550  			"empty deposit address request",
   551  			func() {
   552  				req = &types.QueryDepositRequest{
   553  					ProposalId: 1,
   554  					Depositor:  "",
   555  				}
   556  			},
   557  			false,
   558  		},
   559  		{
   560  			"non existed proposal",
   561  			func() {
   562  				req = &types.QueryDepositRequest{
   563  					ProposalId: 2,
   564  					Depositor:  addrs[0].String(),
   565  				}
   566  			},
   567  			false,
   568  		},
   569  		{
   570  			"no deposits proposal",
   571  			func() {
   572  				var err error
   573  				proposal, err = app.GovKeeper.SubmitProposal(ctx, TestProposal)
   574  				suite.Require().NoError(err)
   575  				suite.Require().NotNil(proposal)
   576  
   577  				req = &types.QueryDepositRequest{
   578  					ProposalId: proposal.ProposalId,
   579  					Depositor:  addrs[0].String(),
   580  				}
   581  			},
   582  			false,
   583  		},
   584  		{
   585  			"valid request",
   586  			func() {
   587  				depositCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 20)))
   588  				deposit := types.NewDeposit(proposal.ProposalId, addrs[0], depositCoins)
   589  				app.GovKeeper.SetDeposit(ctx, deposit)
   590  
   591  				req = &types.QueryDepositRequest{
   592  					ProposalId: proposal.ProposalId,
   593  					Depositor:  addrs[0].String(),
   594  				}
   595  
   596  				expRes = &types.QueryDepositResponse{Deposit: deposit}
   597  			},
   598  			true,
   599  		},
   600  	}
   601  
   602  	for _, testCase := range testCases {
   603  		suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
   604  			testCase.malleate()
   605  
   606  			deposit, err := queryClient.Deposit(gocontext.Background(), req)
   607  
   608  			if testCase.expPass {
   609  				suite.Require().NoError(err)
   610  				suite.Require().Equal(deposit.GetDeposit(), expRes.GetDeposit())
   611  			} else {
   612  				suite.Require().Error(err)
   613  				suite.Require().Nil(expRes)
   614  			}
   615  		})
   616  	}
   617  }
   618  
   619  func (suite *KeeperTestSuite) TestGRPCQueryDeposits() {
   620  	app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs
   621  
   622  	var (
   623  		req      *types.QueryDepositsRequest
   624  		expRes   *types.QueryDepositsResponse
   625  		proposal types.Proposal
   626  	)
   627  
   628  	testCases := []struct {
   629  		msg      string
   630  		malleate func()
   631  		expPass  bool
   632  	}{
   633  		{
   634  			"empty request",
   635  			func() {
   636  				req = &types.QueryDepositsRequest{}
   637  			},
   638  			false,
   639  		},
   640  		{
   641  			"zero proposal id request",
   642  			func() {
   643  				req = &types.QueryDepositsRequest{
   644  					ProposalId: 0,
   645  				}
   646  			},
   647  			false,
   648  		},
   649  		{
   650  			"non existed proposal",
   651  			func() {
   652  				req = &types.QueryDepositsRequest{
   653  					ProposalId: 2,
   654  				}
   655  			},
   656  			true,
   657  		},
   658  		{
   659  			"create a proposal and get deposits",
   660  			func() {
   661  				var err error
   662  				proposal, err = app.GovKeeper.SubmitProposal(ctx, TestProposal)
   663  				suite.Require().NoError(err)
   664  
   665  				req = &types.QueryDepositsRequest{
   666  					ProposalId: proposal.ProposalId,
   667  				}
   668  			},
   669  			true,
   670  		},
   671  		{
   672  			"get deposits with default limit",
   673  			func() {
   674  				depositAmount1 := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 20)))
   675  				deposit1 := types.NewDeposit(proposal.ProposalId, addrs[0], depositAmount1)
   676  				app.GovKeeper.SetDeposit(ctx, deposit1)
   677  
   678  				depositAmount2 := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 30)))
   679  				deposit2 := types.NewDeposit(proposal.ProposalId, addrs[1], depositAmount2)
   680  				app.GovKeeper.SetDeposit(ctx, deposit2)
   681  
   682  				deposits := types.Deposits{deposit1, deposit2}
   683  
   684  				req = &types.QueryDepositsRequest{
   685  					ProposalId: proposal.ProposalId,
   686  				}
   687  
   688  				expRes = &types.QueryDepositsResponse{
   689  					Deposits: deposits,
   690  				}
   691  			},
   692  			true,
   693  		},
   694  	}
   695  
   696  	for _, testCase := range testCases {
   697  		suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
   698  			testCase.malleate()
   699  
   700  			deposits, err := queryClient.Deposits(gocontext.Background(), req)
   701  
   702  			if testCase.expPass {
   703  				suite.Require().NoError(err)
   704  				suite.Require().Equal(expRes.GetDeposits(), deposits.GetDeposits())
   705  			} else {
   706  				suite.Require().Error(err)
   707  				suite.Require().Nil(deposits)
   708  			}
   709  		})
   710  	}
   711  }
   712  
   713  func (suite *KeeperTestSuite) TestGRPCQueryTally() {
   714  	app, ctx, queryClient := suite.app, suite.ctx, suite.queryClient
   715  
   716  	addrs, _ := createValidators(suite.T(), ctx, app, []int64{5, 5, 5})
   717  
   718  	var (
   719  		req      *types.QueryTallyResultRequest
   720  		expRes   *types.QueryTallyResultResponse
   721  		proposal types.Proposal
   722  	)
   723  
   724  	testCases := []struct {
   725  		msg      string
   726  		malleate func()
   727  		expPass  bool
   728  	}{
   729  		{
   730  			"empty request",
   731  			func() {
   732  				req = &types.QueryTallyResultRequest{}
   733  			},
   734  			false,
   735  		},
   736  		{
   737  			"zero proposal id request",
   738  			func() {
   739  				req = &types.QueryTallyResultRequest{ProposalId: 0}
   740  			},
   741  			false,
   742  		},
   743  		{
   744  			"query non existed proposal",
   745  			func() {
   746  				req = &types.QueryTallyResultRequest{ProposalId: 1}
   747  			},
   748  			false,
   749  		},
   750  		{
   751  			"create a proposal and get tally",
   752  			func() {
   753  				var err error
   754  				proposal, err = app.GovKeeper.SubmitProposal(ctx, TestProposal)
   755  				suite.Require().NoError(err)
   756  				suite.Require().NotNil(proposal)
   757  
   758  				req = &types.QueryTallyResultRequest{ProposalId: proposal.ProposalId}
   759  
   760  				expRes = &types.QueryTallyResultResponse{
   761  					Tally: types.EmptyTallyResult(),
   762  				}
   763  			},
   764  			true,
   765  		},
   766  		{
   767  			"request tally after few votes",
   768  			func() {
   769  				proposal.Status = types.StatusVotingPeriod
   770  				app.GovKeeper.SetProposal(ctx, proposal)
   771  
   772  				suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[0], types.NewNonSplitVoteOption(types.OptionYes)))
   773  				suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[1], types.NewNonSplitVoteOption(types.OptionYes)))
   774  				suite.Require().NoError(app.GovKeeper.AddVote(ctx, proposal.ProposalId, addrs[2], types.NewNonSplitVoteOption(types.OptionYes)))
   775  
   776  				req = &types.QueryTallyResultRequest{ProposalId: proposal.ProposalId}
   777  
   778  				expRes = &types.QueryTallyResultResponse{
   779  					Tally: types.TallyResult{
   780  						Yes: sdk.NewInt(3 * 5 * 1000000),
   781  					},
   782  				}
   783  			},
   784  			true,
   785  		},
   786  		{
   787  			"request final tally after status changed",
   788  			func() {
   789  				proposal.Status = types.StatusPassed
   790  				app.GovKeeper.SetProposal(ctx, proposal)
   791  				proposal, _ = app.GovKeeper.GetProposal(ctx, proposal.ProposalId)
   792  
   793  				req = &types.QueryTallyResultRequest{ProposalId: proposal.ProposalId}
   794  
   795  				expRes = &types.QueryTallyResultResponse{
   796  					Tally: proposal.FinalTallyResult,
   797  				}
   798  			},
   799  			true,
   800  		},
   801  	}
   802  
   803  	for _, testCase := range testCases {
   804  		suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
   805  			testCase.malleate()
   806  
   807  			tally, err := queryClient.TallyResult(gocontext.Background(), req)
   808  
   809  			if testCase.expPass {
   810  				suite.Require().NoError(err)
   811  				suite.Require().Equal(expRes.String(), tally.String())
   812  			} else {
   813  				suite.Require().Error(err)
   814  				suite.Require().Nil(tally)
   815  			}
   816  		})
   817  	}
   818  }