Skip to content

Commit

Permalink
Start query tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alpe committed Nov 2, 2021
1 parent 294e1fa commit 8feb46e
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 17 deletions.
14 changes: 5 additions & 9 deletions app/wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ func SetupWasmHandlers(cdc codec.Marshaler,
result twasmkeeper.TgradeWasmHandlerKeeper,
poeKeeper poewasm.ViewKeeper,
) []wasmkeeper.Option {
queryPluginOpt := wasmkeeper.WithQueryPlugins(&wasmkeeper.QueryPlugins{
Staking: poewasm.StakingQuerier(poeKeeper),
})

extMessageHandlerOpt := wasmkeeper.WithMessageHandlerDecorator(func(nested wasmkeeper.Messenger) wasmkeeper.Messenger {
return wasmkeeper.NewMessageHandlerChain(
// disable staking messages
Expand All @@ -35,16 +39,8 @@ func SetupWasmHandlers(cdc codec.Marshaler,
twasmkeeper.NewTgradeHandler(cdc, result, bankKeeper, govRouter),
)
})
extQueryHandlerOpt := wasmkeeper.WithQueryHandlerDecorator(func(nested wasmkeeper.WasmVMQueryHandler) wasmkeeper.WasmVMQueryHandler {
return wasmkeeper.WasmVMQueryHandlerFn(func(ctx sdk.Context, caller sdk.AccAddress, request wasmvmtypes.QueryRequest) ([]byte, error) {
if request.Staking != nil {
return poewasm.StakingQuerier(poeKeeper)(ctx, request.Staking)
}
return nested.HandleQuery(ctx, caller, request)
})
})
return []wasm.Option{
queryPluginOpt,
extMessageHandlerOpt,
extQueryHandlerOpt,
}
}
2 changes: 1 addition & 1 deletion x/poe/keeper/poetesting/mock_contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (m ValsetContractMock) QueryConfig(ctx types.Context) (*contract.ValsetConf
return m.QueryConfigFn(ctx)
}

//var _ keeper.StakeContract = StakeContractMock{}
// var _ keeper.StakeContract = StakeContractMock{}

type StakeContractMock struct {
QueryStakingUnbondingPeriodFn func(ctx types.Context) (time.Duration, error)
Expand Down
15 changes: 8 additions & 7 deletions x/poe/wasm/query_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func StakingQuerier(poeKeeper ViewKeeper) func(ctx sdk.Context, request *wasmvmt
}
return json.Marshal(res)
}
zero := sdk.ZeroDec().String()
if request.AllValidators != nil {
validators, err := poeKeeper.ValsetContract(ctx).ListValidators(ctx)
if err != nil {
Expand All @@ -35,9 +36,9 @@ func StakingQuerier(poeKeeper ViewKeeper) func(ctx sdk.Context, request *wasmvmt
for i, v := range validators {
wasmVals[i] = wasmvmtypes.Validator{
Address: v.OperatorAddress,
Commission: v.Commission.Rate.String(),
MaxCommission: v.Commission.MaxRate.String(),
MaxChangeRate: v.Commission.MaxChangeRate.String(),
Commission: zero,
MaxCommission: zero,
MaxChangeRate: zero,
}
}
res := wasmvmtypes.AllValidatorsResponse{
Expand All @@ -58,9 +59,9 @@ func StakingQuerier(poeKeeper ViewKeeper) func(ctx sdk.Context, request *wasmvmt
if v != nil {
res.Validator = &wasmvmtypes.Validator{
Address: v.OperatorAddress,
Commission: v.Commission.Rate.String(),
MaxCommission: v.Commission.MaxRate.String(),
MaxChangeRate: v.Commission.MaxChangeRate.String(),
Commission: zero,
MaxCommission: zero,
MaxChangeRate: zero,
}
}
return json.Marshal(res)
Expand Down Expand Up @@ -89,7 +90,7 @@ func StakingQuerier(poeKeeper ViewKeeper) func(ctx sdk.Context, request *wasmvmt
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, request.Delegation.Delegator)
}
validator, err := sdk.ValAddressFromBech32(request.Delegation.Validator)
validator, err := sdk.AccAddressFromBech32(request.Delegation.Validator)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, request.Delegation.Validator)
}
Expand Down
222 changes: 222 additions & 0 deletions x/poe/wasm/query_plugin_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
package wasm

import (
"testing"

wasmvmtypes "github.com/CosmWasm/wasmvm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/confio/tgrade/x/poe/keeper"
"github.com/confio/tgrade/x/poe/keeper/poetesting"
poetypes "github.com/confio/tgrade/x/poe/types"
)

func TestStakingQuerier(t *testing.T) {
specs := map[string]struct {
src wasmvmtypes.StakingQuery
mock ViewKeeper
expJson string
expErr bool
}{
"bonded denum": {
src: wasmvmtypes.StakingQuery{BondedDenom: &struct{}{}},
mock: ViewKeeperMock{GetBondDenomFn: func(ctx sdk.Context) string {
return "alx"
}},
expJson: `{"denom": "alx"}`,
},
"all validators - single": {
src: wasmvmtypes.StakingQuery{AllValidators: &wasmvmtypes.AllValidatorsQuery{}},
mock: ViewKeeperMock{ValsetContractFn: func(ctx sdk.Context) keeper.ValsetContract {
return poetesting.ValsetContractMock{
ListValidatorsFn: func(ctx sdk.Context) ([]stakingtypes.Validator, error) {
resp := []stakingtypes.Validator{
poetypes.ValidatorFixture(func(m *stakingtypes.Validator) {
m.OperatorAddress = "myOperatorAddress"
}),
}
return resp, nil
},
}
}},
expJson: `{"validators":[{"address":"myOperatorAddress","commission":"0.000000000000000000","max_commission":"0.000000000000000000","max_change_rate":"0.000000000000000000"}]}`,
},
"all validators - multiple": {
src: wasmvmtypes.StakingQuery{AllValidators: &wasmvmtypes.AllValidatorsQuery{}},
mock: ViewKeeperMock{ValsetContractFn: func(ctx sdk.Context) keeper.ValsetContract {
return poetesting.ValsetContractMock{
ListValidatorsFn: func(ctx sdk.Context) ([]stakingtypes.Validator, error) {
resp := []stakingtypes.Validator{
poetypes.ValidatorFixture(func(m *stakingtypes.Validator) {
m.OperatorAddress = "myOperatorAddress"
}),
poetypes.ValidatorFixture(func(m *stakingtypes.Validator) {
m.OperatorAddress = "myOtherOperatorAddress"
}),
}
return resp, nil
},
}
}},
expJson: `{"validators":[
{"address":"myOperatorAddress","commission":"0.000000000000000000","max_commission":"0.000000000000000000","max_change_rate":"0.000000000000000000"},
{"address":"myOtherOperatorAddress","commission":"0.000000000000000000","max_commission":"0.000000000000000000","max_change_rate":"0.000000000000000000"}
]}`,
},
"query validator": {
src: wasmvmtypes.StakingQuery{Validator: &wasmvmtypes.ValidatorQuery{Address: "cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3"}},
mock: ViewKeeperMock{ValsetContractFn: func(ctx sdk.Context) keeper.ValsetContract {
return poetesting.ValsetContractMock{
QueryValidatorFn: func(ctx sdk.Context, opAddr sdk.AccAddress) (*stakingtypes.Validator, error) {
val := poetypes.ValidatorFixture(func(m *stakingtypes.Validator) {
m.OperatorAddress = "cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3"
})
return &val, nil
},
}
}},
expJson: `{"validator":{"address":"cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3","commission":"0.000000000000000000","max_commission":"0.000000000000000000","max_change_rate":"0.000000000000000000"}}`,
},
"query validator - unknown address": {
src: wasmvmtypes.StakingQuery{Validator: &wasmvmtypes.ValidatorQuery{Address: "cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3"}},
mock: ViewKeeperMock{ValsetContractFn: func(ctx sdk.Context) keeper.ValsetContract {
return poetesting.ValsetContractMock{
QueryValidatorFn: func(ctx sdk.Context, opAddr sdk.AccAddress) (*stakingtypes.Validator, error) {
return nil, nil
},
}
}},
expJson: `{"validator": null}`,
},
"query validator - invalid address": {
src: wasmvmtypes.StakingQuery{Validator: &wasmvmtypes.ValidatorQuery{Address: "not a valid address"}},
expErr: true,
},
"all delegations": {
src: wasmvmtypes.StakingQuery{AllDelegations: &wasmvmtypes.AllDelegationsQuery{Delegator: "cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3"}},
mock: ViewKeeperMock{StakeContractFn: func(ctx sdk.Context) keeper.StakeContract {
return poetesting.StakeContractMock{
QueryStakedAmountFn: func(ctx sdk.Context, opAddr sdk.AccAddress) (*sdk.Int, error) {
myValue := sdk.OneInt()
return &myValue, nil
},
}
},
GetBondDenomFn: func(ctx sdk.Context) string {
return "alx"
}},
expJson: `{"delegations":[{"delegator":"cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3","validator":"cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3","amount":{"denom":"alx","amount":"1"}}]}`,
},
"all delegations - unknown address": {
src: wasmvmtypes.StakingQuery{AllDelegations: &wasmvmtypes.AllDelegationsQuery{Delegator: "cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3"}},
mock: ViewKeeperMock{StakeContractFn: func(ctx sdk.Context) keeper.StakeContract {
return poetesting.StakeContractMock{
QueryStakedAmountFn: func(ctx sdk.Context, opAddr sdk.AccAddress) (*sdk.Int, error) {
return nil, nil
},
}
}},
expJson: `{"delegations":[]}`,
},
"all delegations - invalid address": {
src: wasmvmtypes.StakingQuery{AllDelegations: &wasmvmtypes.AllDelegationsQuery{Delegator: "not a valid address"}},
expErr: true,
},
"query delegation": {
src: wasmvmtypes.StakingQuery{Delegation: &wasmvmtypes.DelegationQuery{Delegator: "cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3", Validator: "cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3"}},
mock: ViewKeeperMock{
StakeContractFn: func(ctx sdk.Context) keeper.StakeContract {
return poetesting.StakeContractMock{
QueryStakedAmountFn: func(ctx sdk.Context, opAddr sdk.AccAddress) (*sdk.Int, error) {
myValue := sdk.OneInt()
return &myValue, nil
},
}
},
GetBondDenomFn: func(ctx sdk.Context) string {
return "alx"
},
DistributionContractFn: func(ctx sdk.Context) keeper.DistributionContract {
return poetesting.DistributionContractMock{ValidatorOutstandingRewardFn: func(ctx sdk.Context, addr sdk.AccAddress) (sdk.Coin, error) {
return sdk.NewCoin("alx", sdk.NewInt(2)), nil
}}
},
},
expJson: `{
"delegation": {
"delegator": "cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3",
"validator": "cosmos1yq8zt83jznmp94jkj65yvfz9n52akmxt52ehm3",
"amount": {
"denom": "alx",
"amount": "1"
},
"accumulated_rewards": [
{
"denom": "alx",
"amount": "2"
}
],
"can_redelegate": {
"denom": "alx",
"amount": "1"
}
}
}
`,
// todo:
// - check address do not match
// - unknown address
// - invalid address
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
q := StakingQuerier(spec.mock)
gotRsp, gotErr := q(sdk.Context{}, &spec.src)
if spec.expErr {
require.Error(t, gotErr)
return
}
require.NoError(t, gotErr)
assert.JSONEq(t, spec.expJson, string(gotRsp), string(gotRsp))
})
}
}

type ViewKeeperMock struct {
GetBondDenomFn func(ctx sdk.Context) string
DistributionContractFn func(ctx sdk.Context) keeper.DistributionContract
ValsetContractFn func(ctx sdk.Context) keeper.ValsetContract
StakeContractFn func(ctx sdk.Context) keeper.StakeContract
}

func (m ViewKeeperMock) GetBondDenom(ctx sdk.Context) string {
if m.GetBondDenomFn == nil {
panic("not expected to be called")
}
return m.GetBondDenomFn(ctx)
}

func (m ViewKeeperMock) DistributionContract(ctx sdk.Context) keeper.DistributionContract {
if m.DistributionContractFn == nil {
panic("not expected to be called")
}
return m.DistributionContractFn(ctx)
}

func (m ViewKeeperMock) ValsetContract(ctx sdk.Context) keeper.ValsetContract {
if m.ValsetContractFn == nil {
panic("not expected to be called")
}
return m.ValsetContractFn(ctx)
}

func (m ViewKeeperMock) StakeContract(ctx sdk.Context) keeper.StakeContract {
if m.StakeContractFn == nil {
panic("not expected to be called")
}
return m.StakeContractFn(ctx)
}

0 comments on commit 8feb46e

Please sign in to comment.