Skip to content

Commit

Permalink
test: write test for Rewards query endpoint
Browse files Browse the repository at this point in the history
also rename some fields and methods
  • Loading branch information
hallazzang committed Sep 15, 2021
1 parent 6e81264 commit 736d3e8
Show file tree
Hide file tree
Showing 10 changed files with 510 additions and 429 deletions.
2 changes: 1 addition & 1 deletion proto/tendermint/farming/v1beta1/farming.proto
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ message QueuedStaking {
string amount = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
}

message TotalStaking {
message TotalStakings {
option (gogoproto.goproto_getters) = false;

string amount = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
Expand Down
18 changes: 9 additions & 9 deletions proto/tendermint/farming/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ service Query {
option (google.api.http).get = "/cosmos/farming/v1beta1/plans/{plan_id}";
}

rpc Staking(QueryStakingRequest) returns (QueryStakingResponse) {
rpc Stakings(QueryStakingsRequest) returns (QueryStakingsResponse) {
option (google.api.http).get = "/cosmos/farming/v1beta1/stakings/{farmer}";
}

rpc TotalStaking(QueryTotalStakingRequest) returns (QueryTotalStakingResponse) {
rpc TotalStakings(QueryTotalStakingsRequest) returns (QueryTotalStakingsResponse) {
option (google.api.http).get = "/cosmos/farming/v1beta1/total_stakings/{staking_coin_denom}";
}

rpc Reward(QueryRewardRequest) returns (QueryRewardResponse) {
rpc Rewards(QueryRewardsRequest) returns (QueryRewardsResponse) {
option (google.api.http).get = "/cosmos/farming/v1beta1/rewards/{farmer}";
}
}
Expand Down Expand Up @@ -76,32 +76,32 @@ message QueryPlanResponse {
google.protobuf.Any plan = 1 [(cosmos_proto.accepts_interface) = "PlanI"];
}

message QueryStakingRequest {
message QueryStakingsRequest {
string farmer = 1;
string staking_coin_denom = 2;
}

message QueryStakingResponse {
message QueryStakingsResponse {
repeated cosmos.base.v1beta1.Coin staked_coins = 1
[(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false];
repeated cosmos.base.v1beta1.Coin queued_coins = 2
[(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false];
}

message QueryTotalStakingRequest {
message QueryTotalStakingsRequest {
string staking_coin_denom = 1;
}

message QueryTotalStakingResponse {
message QueryTotalStakingsResponse {
string amount = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
}

message QueryRewardRequest {
message QueryRewardsRequest {
string farmer = 1;
string staking_coin_denom = 2;
}

message QueryRewardResponse {
message QueryRewardsResponse {
repeated cosmos.base.v1beta1.Coin rewards = 1
[(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false];
}
14 changes: 7 additions & 7 deletions x/farming/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func (k Querier) Plan(c context.Context, req *types.QueryPlanRequest) (*types.Qu
return &types.QueryPlanResponse{Plan: any}, nil
}

func (k Querier) Staking(c context.Context, req *types.QueryStakingRequest) (*types.QueryStakingResponse, error) {
func (k Querier) Stakings(c context.Context, req *types.QueryStakingsRequest) (*types.QueryStakingsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
Expand All @@ -164,7 +164,7 @@ func (k Querier) Staking(c context.Context, req *types.QueryStakingRequest) (*ty

ctx := sdk.UnwrapSDKContext(c)

resp := &types.QueryStakingResponse{
resp := &types.QueryStakingsResponse{
StakedCoins: sdk.NewCoins(),
QueuedCoins: sdk.NewCoins(),
}
Expand All @@ -191,7 +191,7 @@ func (k Querier) Staking(c context.Context, req *types.QueryStakingRequest) (*ty
return resp, nil
}

func (k Querier) TotalStaking(c context.Context, req *types.QueryTotalStakingRequest) (*types.QueryTotalStakingResponse, error) {
func (k Querier) TotalStakings(c context.Context, req *types.QueryTotalStakingsRequest) (*types.QueryTotalStakingsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
Expand All @@ -202,17 +202,17 @@ func (k Querier) TotalStaking(c context.Context, req *types.QueryTotalStakingReq

ctx := sdk.UnwrapSDKContext(c)

totalStakings, found := k.GetTotalStaking(ctx, req.StakingCoinDenom)
totalStakings, found := k.GetTotalStakings(ctx, req.StakingCoinDenom)
if !found {
totalStakings.Amount = sdk.ZeroInt()
}

return &types.QueryTotalStakingResponse{
return &types.QueryTotalStakingsResponse{
Amount: totalStakings.Amount,
}, nil
}

func (k Querier) Reward(c context.Context, req *types.QueryRewardRequest) (*types.QueryRewardResponse, error) {
func (k Querier) Rewards(c context.Context, req *types.QueryRewardsRequest) (*types.QueryRewardsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
Expand All @@ -230,7 +230,7 @@ func (k Querier) Reward(c context.Context, req *types.QueryRewardRequest) (*type

ctx := sdk.UnwrapSDKContext(c)

resp := &types.QueryRewardResponse{
resp := &types.QueryRewardsResponse{
Rewards: sdk.NewCoins(),
}

Expand Down
123 changes: 102 additions & 21 deletions x/farming/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/tendermint/farming/x/farming"
"github.com/tendermint/farming/x/farming/types"
)

Expand Down Expand Up @@ -217,7 +218,7 @@ func (suite *KeeperTestSuite) TestGRPCPlan() {
}
}

func (suite *KeeperTestSuite) TestGRPCStaking() {
func (suite *KeeperTestSuite) TestGRPCStakings() {
suite.Stake(suite.addrs[0], sdk.NewCoins(sdk.NewInt64Coin(denom1, 1000), sdk.NewInt64Coin(denom2, 1500)))
suite.Stake(suite.addrs[1], sdk.NewCoins(sdk.NewInt64Coin(denom1, 500), sdk.NewInt64Coin(denom2, 2000)))
suite.keeper.ProcessQueuedCoins(suite.ctx)
Expand All @@ -226,9 +227,9 @@ func (suite *KeeperTestSuite) TestGRPCStaking() {

for _, tc := range []struct {
name string
req *types.QueryStakingRequest
req *types.QueryStakingsRequest
expectErr bool
postRun func(*types.QueryStakingResponse)
postRun func(*types.QueryStakingsResponse)
}{
{
"nil request",
Expand All @@ -238,9 +239,9 @@ func (suite *KeeperTestSuite) TestGRPCStaking() {
},
{
"query by farmer addr",
&types.QueryStakingRequest{Farmer: suite.addrs[0].String()},
&types.QueryStakingsRequest{Farmer: suite.addrs[0].String()},
false,
func(resp *types.QueryStakingResponse) {
func(resp *types.QueryStakingsResponse) {
suite.Require().True(coinsEq(
sdk.NewCoins(sdk.NewInt64Coin(denom1, 1000), sdk.NewInt64Coin(denom2, 1500)),
resp.StakedCoins))
Expand All @@ -251,15 +252,15 @@ func (suite *KeeperTestSuite) TestGRPCStaking() {
},
{
"invalid farmer addr",
&types.QueryStakingRequest{Farmer: "invalid"},
&types.QueryStakingsRequest{Farmer: "invalid"},
true,
nil,
},
{
"query with staking coin denom",
&types.QueryStakingRequest{Farmer: suite.addrs[1].String(), StakingCoinDenom: denom2},
&types.QueryStakingsRequest{Farmer: suite.addrs[1].String(), StakingCoinDenom: denom2},
false,
func(resp *types.QueryStakingResponse) {
func(resp *types.QueryStakingsResponse) {
suite.Require().True(coinsEq(
sdk.NewCoins(sdk.NewInt64Coin(denom2, 2000)),
resp.StakedCoins))
Expand All @@ -270,19 +271,19 @@ func (suite *KeeperTestSuite) TestGRPCStaking() {
},
{
"invalid staking coin denom",
&types.QueryStakingRequest{StakingCoinDenom: "!"},
&types.QueryStakingsRequest{StakingCoinDenom: "!"},
true,
nil,
},
{
"query with staking coin denom, without farmer addr",
&types.QueryStakingRequest{StakingCoinDenom: denom1},
&types.QueryStakingsRequest{StakingCoinDenom: denom1},
true,
nil,
},
} {
suite.Run(tc.name, func() {
resp, err := suite.querier.Staking(sdk.WrapSDKContext(suite.ctx), tc.req)
resp, err := suite.querier.Stakings(sdk.WrapSDKContext(suite.ctx), tc.req)
if tc.expectErr {
suite.Require().Error(err)
} else {
Expand All @@ -293,7 +294,7 @@ func (suite *KeeperTestSuite) TestGRPCStaking() {
}
}

func (suite *KeeperTestSuite) TestGRPCTotalStaking() {
func (suite *KeeperTestSuite) TestGRPCTotalStakings() {
suite.Stake(suite.addrs[0], sdk.NewCoins(sdk.NewInt64Coin(denom1, 1000), sdk.NewInt64Coin(denom2, 1500)))
suite.Stake(suite.addrs[1], sdk.NewCoins(sdk.NewInt64Coin(denom1, 500), sdk.NewInt64Coin(denom2, 2000)))
suite.keeper.ProcessQueuedCoins(suite.ctx)
Expand All @@ -302,9 +303,9 @@ func (suite *KeeperTestSuite) TestGRPCTotalStaking() {

for _, tc := range []struct {
name string
req *types.QueryTotalStakingRequest
req *types.QueryTotalStakingsRequest
expectErr bool
postRun func(*types.QueryTotalStakingResponse)
postRun func(*types.QueryTotalStakingsResponse)
}{
{
"nil request",
Expand All @@ -314,34 +315,114 @@ func (suite *KeeperTestSuite) TestGRPCTotalStaking() {
},
{
"empty request",
&types.QueryTotalStakingRequest{},
&types.QueryTotalStakingsRequest{},
true,
nil,
},
{
"query by staking coin denom #1",
&types.QueryTotalStakingRequest{StakingCoinDenom: denom1},
&types.QueryTotalStakingsRequest{StakingCoinDenom: denom1},
false,
func(resp *types.QueryTotalStakingResponse) {
func(resp *types.QueryTotalStakingsResponse) {
suite.Require().True(intEq(sdk.NewInt(1500), resp.Amount))
},
},
{
"query by staking coin denom #1",
&types.QueryTotalStakingRequest{StakingCoinDenom: denom2},
&types.QueryTotalStakingsRequest{StakingCoinDenom: denom2},
false,
func(resp *types.QueryTotalStakingResponse) {
func(resp *types.QueryTotalStakingsResponse) {
suite.Require().True(intEq(sdk.NewInt(3500), resp.Amount))
},
},
{
"invalid staking coin denom",
&types.QueryTotalStakingRequest{StakingCoinDenom: "!"},
&types.QueryTotalStakingsRequest{StakingCoinDenom: "!"},
true,
nil,
},
} {
resp, err := suite.querier.TotalStaking(sdk.WrapSDKContext(suite.ctx), tc.req)
resp, err := suite.querier.TotalStakings(sdk.WrapSDKContext(suite.ctx), tc.req)
if tc.expectErr {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
tc.postRun(resp)
}
}
}

func (suite *KeeperTestSuite) TestGRPCRewards() {
for _, plan := range suite.sampleFixedAmtPlans {
suite.keeper.SetPlan(suite.ctx, plan)
}

suite.Stake(suite.addrs[0], sdk.NewCoins(sdk.NewInt64Coin(denom1, 1000), sdk.NewInt64Coin(denom2, 1500)))
suite.Stake(suite.addrs[1], sdk.NewCoins(sdk.NewInt64Coin(denom1, 1000)))

suite.ctx = suite.ctx.WithBlockTime(mustParseRFC3339("2021-08-06T00:00:00Z"))
farming.EndBlocker(suite.ctx, suite.keeper)
suite.ctx = suite.ctx.WithBlockTime(mustParseRFC3339("2021-08-07T00:00:00Z"))
farming.EndBlocker(suite.ctx, suite.keeper)
suite.ctx = suite.ctx.WithBlockTime(mustParseRFC3339("2021-08-08T00:00:00Z"))
farming.EndBlocker(suite.ctx, suite.keeper)

for _, tc := range []struct {
name string
req *types.QueryRewardsRequest
expectErr bool
postRun func(*types.QueryRewardsResponse)
}{
{
"nil request",
nil,
true,
nil,
},
{
"empty request",
&types.QueryRewardsRequest{},
true,
nil,
},
{
"query by farmer addr",
&types.QueryRewardsRequest{Farmer: suite.addrs[0].String()},
false,
func(resp *types.QueryRewardsResponse) {
// 0.3 * 1000000 * 1/2
// + 0.7 * 1000000 * 1/1
// + 1.0 * 2000000 * 1/2
// ~= 1850000
suite.Require().True(coinsEq(sdk.NewCoins(sdk.NewInt64Coin(denom3, 1849999)), resp.Rewards))
},
},
{
"invalid farmer addr",
&types.QueryRewardsRequest{Farmer: "invalid"},
true,
nil,
},
{
"query with staking coin denom",
&types.QueryRewardsRequest{Farmer: suite.addrs[1].String(), StakingCoinDenom: denom1},
false,
func(resp *types.QueryRewardsResponse) {
// 0.3 * 1000000 * 1/2
// + 1.0 * 2000000 * 1/2
// ~= 1150000
suite.Require().True(coinsEq(sdk.NewCoins(sdk.NewInt64Coin(denom3, 1150000)), resp.Rewards))
},
},
{
"query with staking coin denom, without farmer addr",
&types.QueryRewardsRequest{StakingCoinDenom: denom2},
true,
nil,
},
} {
cacheCtx, _ := suite.ctx.CacheContext() // TODO: can we omit the 'cached' context?
resp, err := suite.querier.Rewards(sdk.WrapSDKContext(cacheCtx), tc.req)
if tc.expectErr {
suite.Require().Error(err)
} else {
Expand Down
6 changes: 3 additions & 3 deletions x/farming/keeper/reward.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,11 @@ func (k Keeper) AllocateRewards(ctx sdk.Context) error {

totalAllocCoins := sdk.NewDecCoins()
for _, weight := range allocInfo.Plan.GetStakingCoinWeights() {
totalStaking, found := k.GetTotalStaking(ctx, weight.Denom)
totalStakings, found := k.GetTotalStakings(ctx, weight.Denom)
if !found {
continue
}
if !totalStaking.Amount.IsPositive() {
if !totalStakings.Amount.IsPositive() {
continue
}

Expand All @@ -242,7 +242,7 @@ func (k Keeper) AllocateRewards(ctx sdk.Context) error {
currentEpoch := k.GetCurrentEpoch(ctx, weight.Denom)
historical := k.GetHistoricalRewards(ctx, weight.Denom, currentEpoch-1)
k.SetHistoricalRewards(ctx, weight.Denom, currentEpoch, types.HistoricalRewards{
CumulativeUnitRewards: historical.CumulativeUnitRewards.Add(allocCoins.QuoDecTruncate(totalStaking.Amount.ToDec())...),
CumulativeUnitRewards: historical.CumulativeUnitRewards.Add(allocCoins.QuoDecTruncate(totalStakings.Amount.ToDec())...),
})
k.SetCurrentEpoch(ctx, weight.Denom, currentEpoch+1)

Expand Down
Loading

0 comments on commit 736d3e8

Please sign in to comment.