github.com/Finschia/finschia-sdk@v0.48.1/x/distribution/keeper/grpc_query_test.go (about) 1 package keeper_test 2 3 import ( 4 gocontext "context" 5 "fmt" 6 "testing" 7 8 "github.com/stretchr/testify/suite" 9 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 10 11 "github.com/Finschia/finschia-sdk/baseapp" 12 "github.com/Finschia/finschia-sdk/simapp" 13 sdk "github.com/Finschia/finschia-sdk/types" 14 "github.com/Finschia/finschia-sdk/types/query" 15 "github.com/Finschia/finschia-sdk/x/distribution/types" 16 "github.com/Finschia/finschia-sdk/x/staking" 17 "github.com/Finschia/finschia-sdk/x/staking/teststaking" 18 stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" 19 ) 20 21 type KeeperTestSuite struct { 22 suite.Suite 23 24 app *simapp.SimApp 25 ctx sdk.Context 26 queryClient types.QueryClient 27 addrs []sdk.AccAddress 28 valAddrs []sdk.ValAddress 29 } 30 31 func (suite *KeeperTestSuite) SetupTest() { 32 app := simapp.Setup(false) 33 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 34 35 queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry()) 36 types.RegisterQueryServer(queryHelper, app.DistrKeeper) 37 queryClient := types.NewQueryClient(queryHelper) 38 39 suite.app = app 40 suite.ctx = ctx 41 suite.queryClient = queryClient 42 43 suite.addrs = simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1000000000)) 44 suite.valAddrs = simapp.ConvertAddrsToValAddrs(suite.addrs) 45 } 46 47 func (suite *KeeperTestSuite) TestGRPCParams() { 48 app, ctx, queryClient := suite.app, suite.ctx, suite.queryClient 49 50 var ( 51 params types.Params 52 req *types.QueryParamsRequest 53 expParams types.Params 54 ) 55 56 testCases := []struct { 57 msg string 58 malleate func() 59 expPass bool 60 }{ 61 { 62 "empty params request", 63 func() { 64 req = &types.QueryParamsRequest{} 65 expParams = types.DefaultParams() 66 }, 67 true, 68 }, 69 { 70 "valid request", 71 func() { 72 params = types.Params{ 73 CommunityTax: sdk.NewDecWithPrec(3, 1), 74 BaseProposerReward: sdk.NewDecWithPrec(2, 1), 75 BonusProposerReward: sdk.NewDecWithPrec(1, 1), 76 WithdrawAddrEnabled: true, 77 } 78 79 app.DistrKeeper.SetParams(ctx, params) 80 req = &types.QueryParamsRequest{} 81 expParams = params 82 }, 83 true, 84 }, 85 } 86 87 for _, testCase := range testCases { 88 suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { 89 testCase.malleate() 90 91 paramsRes, err := queryClient.Params(gocontext.Background(), req) 92 93 if testCase.expPass { 94 suite.Require().NoError(err) 95 suite.Require().NotNil(paramsRes) 96 suite.Require().Equal(paramsRes.Params, expParams) 97 } else { 98 suite.Require().Error(err) 99 } 100 }) 101 } 102 } 103 104 func (suite *KeeperTestSuite) TestGRPCValidatorOutstandingRewards() { 105 app, ctx, queryClient, valAddrs := suite.app, suite.ctx, suite.queryClient, suite.valAddrs 106 107 valCommission := sdk.DecCoins{ 108 sdk.NewDecCoinFromDec("mytoken", sdk.NewDec(5000)), 109 sdk.NewDecCoinFromDec("stake", sdk.NewDec(300)), 110 } 111 112 // set outstanding rewards 113 app.DistrKeeper.SetValidatorOutstandingRewards(ctx, valAddrs[0], types.ValidatorOutstandingRewards{Rewards: valCommission}) 114 rewards := app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]) 115 116 var req *types.QueryValidatorOutstandingRewardsRequest 117 118 testCases := []struct { 119 msg string 120 malleate func() 121 expPass bool 122 }{ 123 { 124 "empty request", 125 func() { 126 req = &types.QueryValidatorOutstandingRewardsRequest{} 127 }, 128 false, 129 }, { 130 "valid request", 131 func() { 132 req = &types.QueryValidatorOutstandingRewardsRequest{ValidatorAddress: valAddrs[0].String()} 133 }, 134 true, 135 }, 136 } 137 138 for _, testCase := range testCases { 139 suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { 140 testCase.malleate() 141 142 validatorOutstandingRewards, err := queryClient.ValidatorOutstandingRewards(gocontext.Background(), req) 143 144 if testCase.expPass { 145 suite.Require().NoError(err) 146 suite.Require().Equal(rewards, validatorOutstandingRewards.Rewards) 147 suite.Require().Equal(valCommission, validatorOutstandingRewards.Rewards.Rewards) 148 } else { 149 suite.Require().Error(err) 150 suite.Require().Nil(validatorOutstandingRewards) 151 } 152 }) 153 } 154 } 155 156 func (suite *KeeperTestSuite) TestGRPCValidatorCommission() { 157 app, ctx, queryClient, valAddrs := suite.app, suite.ctx, suite.queryClient, suite.valAddrs 158 159 commission := sdk.DecCoins{{Denom: "token1", Amount: sdk.NewDec(4)}, {Denom: "token2", Amount: sdk.NewDec(2)}} 160 app.DistrKeeper.SetValidatorAccumulatedCommission(ctx, valAddrs[0], types.ValidatorAccumulatedCommission{Commission: commission}) 161 162 var req *types.QueryValidatorCommissionRequest 163 164 testCases := []struct { 165 msg string 166 malleate func() 167 expPass bool 168 }{ 169 { 170 "empty request", 171 func() { 172 req = &types.QueryValidatorCommissionRequest{} 173 }, 174 false, 175 }, 176 { 177 "valid request", 178 func() { 179 req = &types.QueryValidatorCommissionRequest{ValidatorAddress: valAddrs[0].String()} 180 }, 181 true, 182 }, 183 } 184 185 for _, testCase := range testCases { 186 suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { 187 testCase.malleate() 188 189 commissionRes, err := queryClient.ValidatorCommission(gocontext.Background(), req) 190 191 if testCase.expPass { 192 suite.Require().NoError(err) 193 suite.Require().NotNil(commissionRes) 194 suite.Require().Equal(commissionRes.Commission.Commission, commission) 195 } else { 196 suite.Require().Error(err) 197 suite.Require().Nil(commissionRes) 198 } 199 }) 200 } 201 } 202 203 func (suite *KeeperTestSuite) TestGRPCValidatorSlashes() { 204 app, ctx, queryClient, valAddrs := suite.app, suite.ctx, suite.queryClient, suite.valAddrs 205 206 slashes := []types.ValidatorSlashEvent{ 207 types.NewValidatorSlashEvent(3, sdk.NewDecWithPrec(5, 1)), 208 types.NewValidatorSlashEvent(5, sdk.NewDecWithPrec(5, 1)), 209 types.NewValidatorSlashEvent(7, sdk.NewDecWithPrec(5, 1)), 210 types.NewValidatorSlashEvent(9, sdk.NewDecWithPrec(5, 1)), 211 } 212 213 for i, slash := range slashes { 214 app.DistrKeeper.SetValidatorSlashEvent(ctx, valAddrs[0], uint64(i+2), 0, slash) 215 } 216 217 var ( 218 req *types.QueryValidatorSlashesRequest 219 expRes *types.QueryValidatorSlashesResponse 220 ) 221 222 testCases := []struct { 223 msg string 224 malleate func() 225 expPass bool 226 }{ 227 { 228 "empty request", 229 func() { 230 req = &types.QueryValidatorSlashesRequest{} 231 expRes = &types.QueryValidatorSlashesResponse{} 232 }, 233 false, 234 }, 235 { 236 "Ending height lesser than start height request", 237 func() { 238 req = &types.QueryValidatorSlashesRequest{ 239 ValidatorAddress: valAddrs[1].String(), 240 StartingHeight: 10, 241 EndingHeight: 1, 242 } 243 expRes = &types.QueryValidatorSlashesResponse{Pagination: &query.PageResponse{}} 244 }, 245 false, 246 }, 247 { 248 "no slash event validator request", 249 func() { 250 req = &types.QueryValidatorSlashesRequest{ 251 ValidatorAddress: valAddrs[1].String(), 252 StartingHeight: 1, 253 EndingHeight: 10, 254 } 255 expRes = &types.QueryValidatorSlashesResponse{Pagination: &query.PageResponse{}} 256 }, 257 true, 258 }, 259 { 260 "request slashes with offset 2 and limit 2", 261 func() { 262 pageReq := &query.PageRequest{ 263 Offset: 2, 264 Limit: 2, 265 } 266 267 req = &types.QueryValidatorSlashesRequest{ 268 ValidatorAddress: valAddrs[0].String(), 269 StartingHeight: 1, 270 EndingHeight: 10, 271 Pagination: pageReq, 272 } 273 274 expRes = &types.QueryValidatorSlashesResponse{ 275 Slashes: slashes[2:], 276 } 277 }, 278 true, 279 }, 280 { 281 "request slashes with page limit 3 and count total", 282 func() { 283 pageReq := &query.PageRequest{ 284 Limit: 3, 285 CountTotal: true, 286 } 287 288 req = &types.QueryValidatorSlashesRequest{ 289 ValidatorAddress: valAddrs[0].String(), 290 StartingHeight: 1, 291 EndingHeight: 10, 292 Pagination: pageReq, 293 } 294 295 expRes = &types.QueryValidatorSlashesResponse{ 296 Slashes: slashes[:3], 297 } 298 }, 299 true, 300 }, 301 { 302 "request slashes with page limit 4 and count total", 303 func() { 304 pageReq := &query.PageRequest{ 305 Limit: 4, 306 CountTotal: true, 307 } 308 309 req = &types.QueryValidatorSlashesRequest{ 310 ValidatorAddress: valAddrs[0].String(), 311 StartingHeight: 1, 312 EndingHeight: 10, 313 Pagination: pageReq, 314 } 315 316 expRes = &types.QueryValidatorSlashesResponse{ 317 Slashes: slashes[:4], 318 } 319 }, 320 true, 321 }, 322 } 323 324 for _, testCase := range testCases { 325 suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { 326 testCase.malleate() 327 328 slashesRes, err := queryClient.ValidatorSlashes(gocontext.Background(), req) 329 330 if testCase.expPass { 331 suite.Require().NoError(err) 332 suite.Require().Equal(expRes.GetSlashes(), slashesRes.GetSlashes()) 333 } else { 334 suite.Require().Error(err) 335 suite.Require().Nil(slashesRes) 336 } 337 }) 338 } 339 } 340 341 func (suite *KeeperTestSuite) TestGRPCDelegationRewards() { 342 app, ctx, addrs, valAddrs := suite.app, suite.ctx, suite.addrs, suite.valAddrs 343 344 tstaking := teststaking.NewHelper(suite.T(), ctx, app.StakingKeeper) 345 tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) 346 tstaking.CreateValidator(valAddrs[0], valConsPk1, sdk.NewInt(100), true) 347 348 staking.EndBlocker(ctx, app.StakingKeeper) 349 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 350 351 queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry()) 352 types.RegisterQueryServer(queryHelper, app.DistrKeeper) 353 queryClient := types.NewQueryClient(queryHelper) 354 355 val := app.StakingKeeper.Validator(ctx, valAddrs[0]) 356 357 initial := int64(10) 358 tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}} 359 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 360 361 // test command delegation rewards grpc 362 var ( 363 req *types.QueryDelegationRewardsRequest 364 expRes *types.QueryDelegationRewardsResponse 365 ) 366 367 testCases := []struct { 368 msg string 369 malleate func() 370 expPass bool 371 }{ 372 { 373 "empty request", 374 func() { 375 req = &types.QueryDelegationRewardsRequest{} 376 }, 377 false, 378 }, 379 { 380 "empty delegator request", 381 func() { 382 req = &types.QueryDelegationRewardsRequest{ 383 DelegatorAddress: "", 384 ValidatorAddress: valAddrs[0].String(), 385 } 386 }, 387 false, 388 }, 389 { 390 "empty validator request", 391 func() { 392 req = &types.QueryDelegationRewardsRequest{ 393 DelegatorAddress: addrs[1].String(), 394 ValidatorAddress: "", 395 } 396 }, 397 false, 398 }, 399 { 400 "request with wrong delegator and validator", 401 func() { 402 req = &types.QueryDelegationRewardsRequest{ 403 DelegatorAddress: addrs[1].String(), 404 ValidatorAddress: valAddrs[1].String(), 405 } 406 }, 407 false, 408 }, 409 { 410 "valid request", 411 func() { 412 req = &types.QueryDelegationRewardsRequest{ 413 DelegatorAddress: addrs[0].String(), 414 ValidatorAddress: valAddrs[0].String(), 415 } 416 417 expRes = &types.QueryDelegationRewardsResponse{ 418 Rewards: sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}}, 419 } 420 }, 421 true, 422 }, 423 } 424 425 for _, testCase := range testCases { 426 suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { 427 testCase.malleate() 428 429 rewards, err := queryClient.DelegationRewards(gocontext.Background(), req) 430 431 if testCase.expPass { 432 suite.Require().NoError(err) 433 suite.Require().Equal(expRes, rewards) 434 } else { 435 suite.Require().Error(err) 436 suite.Require().Nil(rewards) 437 } 438 }) 439 } 440 441 // test command delegator total rewards grpc 442 var ( 443 totalRewardsReq *types.QueryDelegationTotalRewardsRequest 444 expTotalRewardsRes *types.QueryDelegationTotalRewardsResponse 445 ) 446 447 testCases = []struct { 448 msg string 449 malleate func() 450 expPass bool 451 }{ 452 { 453 "empty request", 454 func() { 455 totalRewardsReq = &types.QueryDelegationTotalRewardsRequest{} 456 }, 457 false, 458 }, 459 { 460 "valid total delegation rewards", 461 func() { 462 totalRewardsReq = &types.QueryDelegationTotalRewardsRequest{ 463 DelegatorAddress: addrs[0].String(), 464 } 465 466 expectedDelReward := types.NewDelegationDelegatorReward(valAddrs[0], 467 sdk.DecCoins{sdk.NewInt64DecCoin("stake", 5)}) 468 469 expTotalRewardsRes = &types.QueryDelegationTotalRewardsResponse{ 470 Rewards: []types.DelegationDelegatorReward{expectedDelReward}, 471 Total: expectedDelReward.Reward, 472 } 473 }, 474 true, 475 }, 476 } 477 478 for _, testCase := range testCases { 479 suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { 480 testCase.malleate() 481 482 totalRewardsRes, err := queryClient.DelegationTotalRewards(gocontext.Background(), totalRewardsReq) 483 484 if testCase.expPass { 485 suite.Require().NoError(err) 486 suite.Require().Equal(totalRewardsRes, expTotalRewardsRes) 487 } else { 488 489 suite.Require().Error(err) 490 suite.Require().Nil(totalRewardsRes) 491 } 492 }) 493 } 494 495 // test command validator delegators grpc 496 var ( 497 delegatorValidatorsReq *types.QueryDelegatorValidatorsRequest 498 expDelegatorValidatorsRes *types.QueryDelegatorValidatorsResponse 499 ) 500 501 testCases = []struct { 502 msg string 503 malleate func() 504 expPass bool 505 }{ 506 { 507 "empty request", 508 func() { 509 delegatorValidatorsReq = &types.QueryDelegatorValidatorsRequest{} 510 }, 511 false, 512 }, 513 { 514 "request no delegations address", 515 func() { 516 delegatorValidatorsReq = &types.QueryDelegatorValidatorsRequest{ 517 DelegatorAddress: addrs[1].String(), 518 } 519 520 expDelegatorValidatorsRes = &types.QueryDelegatorValidatorsResponse{} 521 }, 522 true, 523 }, 524 { 525 "valid request", 526 func() { 527 delegatorValidatorsReq = &types.QueryDelegatorValidatorsRequest{ 528 DelegatorAddress: addrs[0].String(), 529 } 530 expDelegatorValidatorsRes = &types.QueryDelegatorValidatorsResponse{ 531 Validators: []string{valAddrs[0].String()}, 532 } 533 }, 534 true, 535 }, 536 } 537 538 for _, testCase := range testCases { 539 suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { 540 testCase.malleate() 541 542 validators, err := queryClient.DelegatorValidators(gocontext.Background(), delegatorValidatorsReq) 543 544 if testCase.expPass { 545 suite.Require().NoError(err) 546 suite.Require().Equal(expDelegatorValidatorsRes, validators) 547 } else { 548 suite.Require().Error(err) 549 suite.Require().Nil(validators) 550 } 551 }) 552 } 553 } 554 555 func (suite *KeeperTestSuite) TestGRPCDelegatorWithdrawAddress() { 556 app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs 557 558 err := app.DistrKeeper.SetWithdrawAddr(ctx, addrs[0], addrs[1]) 559 suite.Require().Nil(err) 560 561 var req *types.QueryDelegatorWithdrawAddressRequest 562 563 testCases := []struct { 564 msg string 565 malleate func() 566 expPass bool 567 }{ 568 { 569 "empty request", 570 func() { 571 req = &types.QueryDelegatorWithdrawAddressRequest{} 572 }, 573 false, 574 }, 575 { 576 "valid request", 577 func() { 578 req = &types.QueryDelegatorWithdrawAddressRequest{DelegatorAddress: addrs[0].String()} 579 }, 580 true, 581 }, 582 } 583 584 for _, testCase := range testCases { 585 suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { 586 testCase.malleate() 587 588 withdrawAddress, err := queryClient.DelegatorWithdrawAddress(gocontext.Background(), req) 589 590 if testCase.expPass { 591 suite.Require().NoError(err) 592 suite.Require().Equal(withdrawAddress.WithdrawAddress, addrs[1].String()) 593 } else { 594 suite.Require().Error(err) 595 suite.Require().Nil(withdrawAddress) 596 } 597 }) 598 } 599 } 600 601 func (suite *KeeperTestSuite) TestGRPCCommunityPool() { 602 app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs 603 604 var ( 605 req *types.QueryCommunityPoolRequest 606 expPool *types.QueryCommunityPoolResponse 607 ) 608 609 testCases := []struct { 610 msg string 611 malleate func() 612 expPass bool 613 }{ 614 { 615 "valid request empty community pool", 616 func() { 617 req = &types.QueryCommunityPoolRequest{} 618 expPool = &types.QueryCommunityPoolResponse{} 619 }, 620 true, 621 }, 622 { 623 "valid request", 624 func() { 625 amount := sdk.NewCoins(sdk.NewInt64Coin("stake", 100)) 626 suite.Require().NoError(simapp.FundAccount(app, ctx, addrs[0], amount)) 627 628 err := app.DistrKeeper.FundCommunityPool(ctx, amount, addrs[0]) 629 suite.Require().Nil(err) 630 req = &types.QueryCommunityPoolRequest{} 631 632 expPool = &types.QueryCommunityPoolResponse{Pool: sdk.NewDecCoinsFromCoins(amount...)} 633 }, 634 true, 635 }, 636 } 637 638 for _, testCase := range testCases { 639 suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { 640 testCase.malleate() 641 642 pool, err := queryClient.CommunityPool(gocontext.Background(), req) 643 644 if testCase.expPass { 645 suite.Require().NoError(err) 646 suite.Require().Equal(expPool, pool) 647 } else { 648 suite.Require().Error(err) 649 suite.Require().Nil(pool) 650 } 651 }) 652 } 653 } 654 655 func TestDistributionTestSuite(t *testing.T) { 656 suite.Run(t, new(KeeperTestSuite)) 657 }