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 }