cosmos-sdk/x/distribution/keeper/grpc_query_test.go

659 lines
16 KiB
Go

package keeper_test
import (
gocontext "context"
"fmt"
"testing"
"github.com/stretchr/testify/suite"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
type KeeperTestSuite struct {
suite.Suite
app *simapp.SimApp
ctx sdk.Context
queryClient types.QueryClient
addrs []sdk.AccAddress
valAddrs []sdk.ValAddress
}
func (suite *KeeperTestSuite) SetupTest() {
app := simapp.Setup(false)
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry())
types.RegisterQueryServer(queryHelper, app.DistrKeeper)
queryClient := types.NewQueryClient(queryHelper)
suite.app = app
suite.ctx = ctx
suite.queryClient = queryClient
suite.addrs = simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1000000000))
suite.valAddrs = simapp.ConvertAddrsToValAddrs(suite.addrs)
}
func (suite *KeeperTestSuite) TestGRPCParams() {
app, ctx, queryClient := suite.app, suite.ctx, suite.queryClient
var (
params types.Params
req *types.QueryParamsRequest
expParams types.Params
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{
"empty params request",
func() {
req = &types.QueryParamsRequest{}
expParams = types.DefaultParams()
},
true,
},
{
"valid request",
func() {
params = types.Params{
CommunityTax: sdk.NewDecWithPrec(3, 1),
BaseProposerReward: sdk.NewDecWithPrec(2, 1),
BonusProposerReward: sdk.NewDecWithPrec(1, 1),
WithdrawAddrEnabled: true,
}
app.DistrKeeper.SetParams(ctx, params)
req = &types.QueryParamsRequest{}
expParams = params
},
true,
},
}
for _, testCase := range testCases {
suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
testCase.malleate()
paramsRes, err := queryClient.Params(gocontext.Background(), req)
if testCase.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(paramsRes)
suite.Require().Equal(paramsRes.Params, expParams)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestGRPCValidatorOutstandingRewards() {
app, ctx, queryClient, valAddrs := suite.app, suite.ctx, suite.queryClient, suite.valAddrs
valCommission := sdk.DecCoins{
sdk.NewDecCoinFromDec("mytoken", sdk.NewDec(5000)),
sdk.NewDecCoinFromDec("stake", sdk.NewDec(300)),
}
// set outstanding rewards
app.DistrKeeper.SetValidatorOutstandingRewards(ctx, valAddrs[0], types.ValidatorOutstandingRewards{Rewards: valCommission})
rewards := app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0])
var req *types.QueryValidatorOutstandingRewardsRequest
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{
"empty request",
func() {
req = &types.QueryValidatorOutstandingRewardsRequest{}
},
false,
}, {
"valid request",
func() {
req = &types.QueryValidatorOutstandingRewardsRequest{ValidatorAddress: valAddrs[0].String()}
},
true,
},
}
for _, testCase := range testCases {
suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
testCase.malleate()
validatorOutstandingRewards, err := queryClient.ValidatorOutstandingRewards(gocontext.Background(), req)
if testCase.expPass {
suite.Require().NoError(err)
suite.Require().Equal(rewards, validatorOutstandingRewards.Rewards)
suite.Require().Equal(valCommission, validatorOutstandingRewards.Rewards.Rewards)
} else {
suite.Require().Error(err)
suite.Require().Nil(validatorOutstandingRewards)
}
})
}
}
func (suite *KeeperTestSuite) TestGRPCValidatorCommission() {
app, ctx, queryClient, valAddrs := suite.app, suite.ctx, suite.queryClient, suite.valAddrs
commission := sdk.DecCoins{{Denom: "token1", Amount: sdk.NewDec(4)}, {Denom: "token2", Amount: sdk.NewDec(2)}}
app.DistrKeeper.SetValidatorAccumulatedCommission(ctx, valAddrs[0], types.ValidatorAccumulatedCommission{Commission: commission})
var req *types.QueryValidatorCommissionRequest
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{
"empty request",
func() {
req = &types.QueryValidatorCommissionRequest{}
},
false,
},
{
"valid request",
func() {
req = &types.QueryValidatorCommissionRequest{ValidatorAddress: valAddrs[0].String()}
},
true,
},
}
for _, testCase := range testCases {
suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
testCase.malleate()
commissionRes, err := queryClient.ValidatorCommission(gocontext.Background(), req)
if testCase.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(commissionRes)
suite.Require().Equal(commissionRes.Commission.Commission, commission)
} else {
suite.Require().Error(err)
suite.Require().Nil(commissionRes)
}
})
}
}
func (suite *KeeperTestSuite) TestGRPCValidatorSlashes() {
app, ctx, queryClient, valAddrs := suite.app, suite.ctx, suite.queryClient, suite.valAddrs
slashes := []types.ValidatorSlashEvent{
types.NewValidatorSlashEvent(3, sdk.NewDecWithPrec(5, 1)),
types.NewValidatorSlashEvent(5, sdk.NewDecWithPrec(5, 1)),
types.NewValidatorSlashEvent(7, sdk.NewDecWithPrec(5, 1)),
types.NewValidatorSlashEvent(9, sdk.NewDecWithPrec(5, 1)),
}
for i, slash := range slashes {
app.DistrKeeper.SetValidatorSlashEvent(ctx, valAddrs[0], uint64(i+2), 0, slash)
}
var (
req *types.QueryValidatorSlashesRequest
expRes *types.QueryValidatorSlashesResponse
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{
"empty request",
func() {
req = &types.QueryValidatorSlashesRequest{}
expRes = &types.QueryValidatorSlashesResponse{}
},
false,
},
{
"Ending height lesser than start height request",
func() {
req = &types.QueryValidatorSlashesRequest{
ValidatorAddress: valAddrs[1].String(),
StartingHeight: 10,
EndingHeight: 1,
}
expRes = &types.QueryValidatorSlashesResponse{Pagination: &query.PageResponse{}}
},
false,
},
{
"no slash event validator request",
func() {
req = &types.QueryValidatorSlashesRequest{
ValidatorAddress: valAddrs[1].String(),
StartingHeight: 1,
EndingHeight: 10,
}
expRes = &types.QueryValidatorSlashesResponse{Pagination: &query.PageResponse{}}
},
true,
},
{
"request slashes with offset 2 and limit 2",
func() {
pageReq := &query.PageRequest{
Offset: 2,
Limit: 2,
}
req = &types.QueryValidatorSlashesRequest{
ValidatorAddress: valAddrs[0].String(),
StartingHeight: 1,
EndingHeight: 10,
Pagination: pageReq,
}
expRes = &types.QueryValidatorSlashesResponse{
Slashes: slashes[2:],
}
},
true,
},
{
"request slashes with page limit 3 and count total",
func() {
pageReq := &query.PageRequest{
Limit: 3,
CountTotal: true,
}
req = &types.QueryValidatorSlashesRequest{
ValidatorAddress: valAddrs[0].String(),
StartingHeight: 1,
EndingHeight: 10,
Pagination: pageReq,
}
expRes = &types.QueryValidatorSlashesResponse{
Slashes: slashes[:3],
}
},
true,
},
{
"request slashes with page limit 4 and count total",
func() {
pageReq := &query.PageRequest{
Limit: 4,
CountTotal: true,
}
req = &types.QueryValidatorSlashesRequest{
ValidatorAddress: valAddrs[0].String(),
StartingHeight: 1,
EndingHeight: 10,
Pagination: pageReq,
}
expRes = &types.QueryValidatorSlashesResponse{
Slashes: slashes[:4],
}
},
true,
},
}
for _, testCase := range testCases {
suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
testCase.malleate()
slashesRes, err := queryClient.ValidatorSlashes(gocontext.Background(), req)
if testCase.expPass {
suite.Require().NoError(err)
suite.Require().Equal(expRes.GetSlashes(), slashesRes.GetSlashes())
} else {
suite.Require().Error(err)
suite.Require().Nil(slashesRes)
}
})
}
}
func (suite *KeeperTestSuite) TestGRPCDelegationRewards() {
app, ctx, addrs, valAddrs := suite.app, suite.ctx, suite.addrs, suite.valAddrs
tstaking := teststaking.NewHelper(suite.T(), ctx, app.StakingKeeper)
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
tstaking.CreateValidator(valAddrs[0], valConsPk1, sdk.NewInt(100), true)
staking.EndBlocker(ctx, app.StakingKeeper)
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry())
types.RegisterQueryServer(queryHelper, app.DistrKeeper)
queryClient := types.NewQueryClient(queryHelper)
val := app.StakingKeeper.Validator(ctx, valAddrs[0])
initial := int64(10)
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}}
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
// test command delegation rewards grpc
var (
req *types.QueryDelegationRewardsRequest
expRes *types.QueryDelegationRewardsResponse
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{
"empty request",
func() {
req = &types.QueryDelegationRewardsRequest{}
},
false,
},
{
"empty delegator request",
func() {
req = &types.QueryDelegationRewardsRequest{
DelegatorAddress: "",
ValidatorAddress: valAddrs[0].String(),
}
},
false,
},
{
"empty validator request",
func() {
req = &types.QueryDelegationRewardsRequest{
DelegatorAddress: addrs[1].String(),
ValidatorAddress: "",
}
},
false,
},
{
"request with wrong delegator and validator",
func() {
req = &types.QueryDelegationRewardsRequest{
DelegatorAddress: addrs[1].String(),
ValidatorAddress: valAddrs[1].String(),
}
},
false,
},
{
"valid request",
func() {
req = &types.QueryDelegationRewardsRequest{
DelegatorAddress: addrs[0].String(),
ValidatorAddress: valAddrs[0].String(),
}
expRes = &types.QueryDelegationRewardsResponse{
Rewards: sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}},
}
},
true,
},
}
for _, testCase := range testCases {
suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
testCase.malleate()
rewards, err := queryClient.DelegationRewards(gocontext.Background(), req)
if testCase.expPass {
suite.Require().NoError(err)
suite.Require().Equal(expRes, rewards)
} else {
suite.Require().Error(err)
suite.Require().Nil(rewards)
}
})
}
// test command delegator total rewards grpc
var (
totalRewardsReq *types.QueryDelegationTotalRewardsRequest
expTotalRewardsRes *types.QueryDelegationTotalRewardsResponse
)
testCases = []struct {
msg string
malleate func()
expPass bool
}{
{
"empty request",
func() {
totalRewardsReq = &types.QueryDelegationTotalRewardsRequest{}
},
false,
},
{
"valid total delegation rewards",
func() {
totalRewardsReq = &types.QueryDelegationTotalRewardsRequest{
DelegatorAddress: addrs[0].String(),
}
expectedDelReward := types.NewDelegationDelegatorReward(valAddrs[0],
sdk.DecCoins{sdk.NewInt64DecCoin("stake", 5)})
expTotalRewardsRes = &types.QueryDelegationTotalRewardsResponse{
Rewards: []types.DelegationDelegatorReward{expectedDelReward},
Total: expectedDelReward.Reward,
}
},
true,
},
}
for _, testCase := range testCases {
suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
testCase.malleate()
totalRewardsRes, err := queryClient.DelegationTotalRewards(gocontext.Background(), totalRewardsReq)
if testCase.expPass {
suite.Require().NoError(err)
suite.Require().Equal(totalRewardsRes, expTotalRewardsRes)
} else {
suite.Require().Error(err)
suite.Require().Nil(totalRewardsRes)
}
})
}
// test command validator delegators grpc
var (
delegatorValidatorsReq *types.QueryDelegatorValidatorsRequest
expDelegatorValidatorsRes *types.QueryDelegatorValidatorsResponse
)
testCases = []struct {
msg string
malleate func()
expPass bool
}{
{
"empty request",
func() {
delegatorValidatorsReq = &types.QueryDelegatorValidatorsRequest{}
},
false,
},
{
"request no delegations address",
func() {
delegatorValidatorsReq = &types.QueryDelegatorValidatorsRequest{
DelegatorAddress: addrs[1].String(),
}
expDelegatorValidatorsRes = &types.QueryDelegatorValidatorsResponse{}
},
true,
},
{
"valid request",
func() {
delegatorValidatorsReq = &types.QueryDelegatorValidatorsRequest{
DelegatorAddress: addrs[0].String(),
}
expDelegatorValidatorsRes = &types.QueryDelegatorValidatorsResponse{
Validators: []string{valAddrs[0].String()},
}
},
true,
},
}
for _, testCase := range testCases {
suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
testCase.malleate()
validators, err := queryClient.DelegatorValidators(gocontext.Background(), delegatorValidatorsReq)
if testCase.expPass {
suite.Require().NoError(err)
suite.Require().Equal(expDelegatorValidatorsRes, validators)
} else {
suite.Require().Error(err)
suite.Require().Nil(validators)
}
})
}
}
func (suite *KeeperTestSuite) TestGRPCDelegatorWithdrawAddress() {
app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs
err := app.DistrKeeper.SetWithdrawAddr(ctx, addrs[0], addrs[1])
suite.Require().Nil(err)
var req *types.QueryDelegatorWithdrawAddressRequest
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{
"empty request",
func() {
req = &types.QueryDelegatorWithdrawAddressRequest{}
},
false,
},
{
"valid request",
func() {
req = &types.QueryDelegatorWithdrawAddressRequest{DelegatorAddress: addrs[0].String()}
},
true,
},
}
for _, testCase := range testCases {
suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
testCase.malleate()
withdrawAddress, err := queryClient.DelegatorWithdrawAddress(gocontext.Background(), req)
if testCase.expPass {
suite.Require().NoError(err)
suite.Require().Equal(withdrawAddress.WithdrawAddress, addrs[1].String())
} else {
suite.Require().Error(err)
suite.Require().Nil(withdrawAddress)
}
})
}
}
func (suite *KeeperTestSuite) TestGRPCCommunityPool() {
app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs
var (
req *types.QueryCommunityPoolRequest
expPool *types.QueryCommunityPoolResponse
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{
"valid request empty community pool",
func() {
req = &types.QueryCommunityPoolRequest{}
expPool = &types.QueryCommunityPoolResponse{}
},
true,
},
{
"valid request",
func() {
amount := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addrs[0], amount))
err := app.DistrKeeper.FundCommunityPool(ctx, amount, addrs[0])
suite.Require().Nil(err)
req = &types.QueryCommunityPoolRequest{}
expPool = &types.QueryCommunityPoolResponse{Pool: sdk.NewDecCoinsFromCoins(amount...)}
},
true,
},
}
for _, testCase := range testCases {
suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
testCase.malleate()
pool, err := queryClient.CommunityPool(gocontext.Background(), req)
if testCase.expPass {
suite.Require().NoError(err)
suite.Require().Equal(expPool, pool)
} else {
suite.Require().Error(err)
suite.Require().Nil(pool)
}
})
}
}
func TestDistributionTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}