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  }