Co-authored-by: Akhil Kumar P <36399231+akhilkumarpilli@users.noreply.github.com>
This commit is contained in:
parent
10c19a2592
commit
aead233e24
@ -1,18 +0,0 @@
|
||||
//go:build e2e
|
||||
// +build e2e
|
||||
|
||||
package distribution
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestWithdrawAllSuite(t *testing.T) {
|
||||
suite.Run(t, new(WithdrawAllTestSuite))
|
||||
}
|
||||
|
||||
func TestGRPCQueryTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(GRPCQueryTestSuite))
|
||||
}
|
||||
@ -1,460 +0,0 @@
|
||||
package distribution
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"cosmossdk.io/simapp"
|
||||
"cosmossdk.io/x/distribution/types"
|
||||
|
||||
sdktestutil "github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
|
||||
"github.com/cosmos/cosmos-sdk/types/query"
|
||||
)
|
||||
|
||||
type GRPCQueryTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network network.NetworkI
|
||||
}
|
||||
|
||||
func (s *GRPCQueryTestSuite) SetupSuite() {
|
||||
s.T().Log("setting up e2e test suite")
|
||||
|
||||
cfg := network.DefaultConfig(simapp.NewTestNetworkFixture)
|
||||
cfg.NumValidators = 1
|
||||
s.cfg = cfg
|
||||
|
||||
var err error
|
||||
s.network, err = network.New(s.T(), s.T().TempDir(), cfg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
}
|
||||
|
||||
// TearDownSuite cleans up the current test network after _each_ test.
|
||||
func (s *GRPCQueryTestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e test suite1")
|
||||
s.network.Cleanup()
|
||||
}
|
||||
|
||||
func (s *GRPCQueryTestSuite) TestQueryParamsGRPC() {
|
||||
val := s.network.GetValidators()[0]
|
||||
baseURL := val.GetAPIAddress()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
respType proto.Message
|
||||
expected proto.Message
|
||||
}{
|
||||
{
|
||||
"gRPC request params",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/params", baseURL),
|
||||
&types.QueryParamsResponse{},
|
||||
&types.QueryParamsResponse{
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
resp, err := sdktestutil.GetRequest(tc.url)
|
||||
s.Run(tc.name, func() {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
s.Require().Equal(tc.expected, tc.respType)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *GRPCQueryTestSuite) TestQueryValidatorDistributionInfoGRPC() {
|
||||
val := s.network.GetValidators()[0]
|
||||
baseURL := val.GetAPIAddress()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expErr bool
|
||||
respType proto.Message
|
||||
}{
|
||||
{
|
||||
"gRPC request with wrong validator address",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s", baseURL, "wrongAddress"),
|
||||
true,
|
||||
&types.QueryValidatorDistributionInfoResponse{},
|
||||
},
|
||||
{
|
||||
"gRPC request with valid validator address ",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s", baseURL, val.GetValAddress().String()),
|
||||
false,
|
||||
&types.QueryValidatorDistributionInfoResponse{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
resp, err := sdktestutil.GetRequest(tc.url)
|
||||
s.Run(tc.name, func() {
|
||||
if tc.expErr {
|
||||
s.Require().Error(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *GRPCQueryTestSuite) TestQueryOutstandingRewardsGRPC() {
|
||||
val := s.network.GetValidators()[0]
|
||||
baseURL := val.GetAPIAddress()
|
||||
|
||||
rewards, err := sdk.ParseDecCoins("46.06stake")
|
||||
s.Require().NoError(err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
headers map[string]string
|
||||
expErr bool
|
||||
respType proto.Message
|
||||
expected proto.Message
|
||||
}{
|
||||
{
|
||||
"gRPC request params with wrong validator address",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/outstanding_rewards", baseURL, "wrongAddress"),
|
||||
map[string]string{},
|
||||
true,
|
||||
&types.QueryValidatorOutstandingRewardsResponse{},
|
||||
&types.QueryValidatorOutstandingRewardsResponse{},
|
||||
},
|
||||
{
|
||||
"gRPC request params valid address",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/outstanding_rewards", baseURL, val.GetValAddress().String()),
|
||||
map[string]string{
|
||||
grpctypes.GRPCBlockHeightHeader: "2",
|
||||
},
|
||||
false,
|
||||
&types.QueryValidatorOutstandingRewardsResponse{},
|
||||
&types.QueryValidatorOutstandingRewardsResponse{
|
||||
Rewards: types.ValidatorOutstandingRewards{
|
||||
Rewards: rewards,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
resp, err := sdktestutil.GetRequestWithHeaders(tc.url, tc.headers)
|
||||
s.Run(tc.name, func() {
|
||||
if tc.expErr {
|
||||
s.Require().Error(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
s.Require().Equal(tc.expected.String(), tc.respType.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *GRPCQueryTestSuite) TestQueryValidatorCommissionGRPC() {
|
||||
val := s.network.GetValidators()[0]
|
||||
baseURL := val.GetAPIAddress()
|
||||
|
||||
commission, err := sdk.ParseDecCoins("23.03stake")
|
||||
s.Require().NoError(err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
headers map[string]string
|
||||
expErr bool
|
||||
respType proto.Message
|
||||
expected proto.Message
|
||||
}{
|
||||
{
|
||||
"gRPC request params with wrong validator address",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/commission", baseURL, "wrongAddress"),
|
||||
map[string]string{},
|
||||
true,
|
||||
&types.QueryValidatorCommissionResponse{},
|
||||
&types.QueryValidatorCommissionResponse{},
|
||||
},
|
||||
{
|
||||
"gRPC request params valid address",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/commission", baseURL, val.GetValAddress().String()),
|
||||
map[string]string{
|
||||
grpctypes.GRPCBlockHeightHeader: "2",
|
||||
},
|
||||
false,
|
||||
&types.QueryValidatorCommissionResponse{},
|
||||
&types.QueryValidatorCommissionResponse{
|
||||
Commission: types.ValidatorAccumulatedCommission{
|
||||
Commission: commission,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
resp, err := sdktestutil.GetRequestWithHeaders(tc.url, tc.headers)
|
||||
s.Run(tc.name, func() {
|
||||
if tc.expErr {
|
||||
s.Require().Error(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
s.Require().Equal(tc.expected.String(), tc.respType.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *GRPCQueryTestSuite) TestQuerySlashesGRPC() {
|
||||
val := s.network.GetValidators()[0]
|
||||
baseURL := val.GetAPIAddress()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expErr bool
|
||||
respType proto.Message
|
||||
expected proto.Message
|
||||
}{
|
||||
{
|
||||
"invalid validator address",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/slashes", baseURL, ""),
|
||||
true,
|
||||
&types.QueryValidatorSlashesResponse{},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"invalid start height",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/slashes?starting_height=%s&ending_height=%s", baseURL, val.GetValAddress().String(), "-1", "3"),
|
||||
true,
|
||||
&types.QueryValidatorSlashesResponse{},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"invalid start height",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/slashes?starting_height=%s&ending_height=%s", baseURL, val.GetValAddress().String(), "1", "-3"),
|
||||
true,
|
||||
&types.QueryValidatorSlashesResponse{},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"valid request get slashes",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/slashes?starting_height=%s&ending_height=%s", baseURL, val.GetValAddress().String(), "1", "3"),
|
||||
false,
|
||||
&types.QueryValidatorSlashesResponse{},
|
||||
&types.QueryValidatorSlashesResponse{
|
||||
Pagination: &query.PageResponse{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
resp, err := sdktestutil.GetRequest(tc.url)
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
if tc.expErr {
|
||||
s.Require().Error(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
s.Require().Equal(tc.expected.String(), tc.respType.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *GRPCQueryTestSuite) TestQueryDelegatorRewardsGRPC() {
|
||||
val := s.network.GetValidators()[0]
|
||||
baseURL := val.GetAPIAddress()
|
||||
|
||||
rewards, err := sdk.ParseDecCoins("23.03stake")
|
||||
s.Require().NoError(err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
headers map[string]string
|
||||
expErr bool
|
||||
respType proto.Message
|
||||
expected proto.Message
|
||||
}{
|
||||
{
|
||||
"wrong delegator address",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/rewards", baseURL, "wrongDelegatorAddress"),
|
||||
map[string]string{},
|
||||
true,
|
||||
&types.QueryDelegationTotalRewardsResponse{},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/rewards", baseURL, val.GetAddress().String()),
|
||||
map[string]string{
|
||||
grpctypes.GRPCBlockHeightHeader: "2",
|
||||
},
|
||||
false,
|
||||
&types.QueryDelegationTotalRewardsResponse{},
|
||||
&types.QueryDelegationTotalRewardsResponse{
|
||||
Rewards: []types.DelegationDelegatorReward{
|
||||
types.NewDelegationDelegatorReward(val.GetValAddress().String(), rewards),
|
||||
},
|
||||
Total: rewards,
|
||||
},
|
||||
},
|
||||
{
|
||||
"wrong validator address(specific validator rewards)",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/rewards/%s", baseURL, val.GetAddress().String(), "wrongValAddress"),
|
||||
map[string]string{},
|
||||
true,
|
||||
&types.QueryDelegationTotalRewardsResponse{},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"valid request(specific validator rewards)",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/rewards/%s", baseURL, val.GetAddress().String(), val.GetValAddress().String()),
|
||||
map[string]string{
|
||||
grpctypes.GRPCBlockHeightHeader: "2",
|
||||
},
|
||||
false,
|
||||
&types.QueryDelegationRewardsResponse{},
|
||||
&types.QueryDelegationRewardsResponse{
|
||||
Rewards: rewards,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
resp, err := sdktestutil.GetRequestWithHeaders(tc.url, tc.headers)
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
if tc.expErr {
|
||||
s.Require().Error(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
s.Require().Equal(tc.expected.String(), tc.respType.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *GRPCQueryTestSuite) TestQueryDelegatorValidatorsGRPC() {
|
||||
val := s.network.GetValidators()[0]
|
||||
baseURL := val.GetAPIAddress()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expErr bool
|
||||
respType proto.Message
|
||||
expected proto.Message
|
||||
}{
|
||||
{
|
||||
"empty delegator address",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/validators", baseURL, ""),
|
||||
true,
|
||||
&types.QueryDelegatorValidatorsResponse{},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"wrong delegator address",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/validators", baseURL, "wrongDelegatorAddress"),
|
||||
true,
|
||||
&types.QueryDelegatorValidatorsResponse{},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/validators", baseURL, val.GetAddress().String()),
|
||||
false,
|
||||
&types.QueryDelegatorValidatorsResponse{},
|
||||
&types.QueryDelegatorValidatorsResponse{
|
||||
Validators: []string{val.GetValAddress().String()},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
resp, err := sdktestutil.GetRequest(tc.url)
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
if tc.expErr {
|
||||
s.Require().Error(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
s.Require().Equal(tc.expected.String(), tc.respType.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *GRPCQueryTestSuite) TestQueryWithdrawAddressGRPC() {
|
||||
val := s.network.GetValidators()[0]
|
||||
baseURL := val.GetAPIAddress()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
url string
|
||||
expErr bool
|
||||
respType proto.Message
|
||||
expected proto.Message
|
||||
}{
|
||||
{
|
||||
"empty delegator address",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/withdraw_address", baseURL, ""),
|
||||
true,
|
||||
&types.QueryDelegatorWithdrawAddressResponse{},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"wrong delegator address",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/withdraw_address", baseURL, "wrongDelegatorAddress"),
|
||||
true,
|
||||
&types.QueryDelegatorWithdrawAddressResponse{},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"valid request",
|
||||
fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/withdraw_address", baseURL, val.GetAddress().String()),
|
||||
false,
|
||||
&types.QueryDelegatorWithdrawAddressResponse{},
|
||||
&types.QueryDelegatorWithdrawAddressResponse{
|
||||
WithdrawAddress: val.GetAddress().String(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
resp, err := sdktestutil.GetRequest(tc.url)
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
if tc.expErr {
|
||||
s.Require().Error(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(resp, tc.respType))
|
||||
s.Require().Equal(tc.expected.String(), tc.respType.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,139 +0,0 @@
|
||||
package distribution
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"cosmossdk.io/simapp"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
"cosmossdk.io/x/distribution/client/cli"
|
||||
stakingtypes "cosmossdk.io/x/staking/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
type WithdrawAllTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network network.NetworkI
|
||||
}
|
||||
|
||||
func (s *WithdrawAllTestSuite) SetupSuite() {
|
||||
cfg := network.DefaultConfig(simapp.NewTestNetworkFixture)
|
||||
cfg.NumValidators = 2
|
||||
s.cfg = cfg
|
||||
|
||||
s.T().Log("setting up e2e test suite")
|
||||
network, err := network.New(s.T(), s.T().TempDir(), s.cfg)
|
||||
s.Require().NoError(err)
|
||||
s.network = network
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
}
|
||||
|
||||
// TearDownSuite cleans up the current test network after _each_ test.
|
||||
func (s *WithdrawAllTestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e test suite")
|
||||
s.network.Cleanup()
|
||||
}
|
||||
|
||||
// This test requires multiple validators, if I add this test to `E2ETestSuite` by increasing
|
||||
// `NumValidators` the existing tests are leading to non-determnism so created new suite for this test.
|
||||
func (s *WithdrawAllTestSuite) TestNewWithdrawAllRewardsGenerateOnly() {
|
||||
require := s.Require()
|
||||
val := s.network.GetValidators()[0]
|
||||
val1 := s.network.GetValidators()[1]
|
||||
clientCtx := val.GetClientCtx()
|
||||
|
||||
info, _, err := val.GetClientCtx().Keyring.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
||||
require.NoError(err)
|
||||
|
||||
pubkey, err := info.GetPubKey()
|
||||
require.NoError(err)
|
||||
|
||||
newAddr := sdk.AccAddress(pubkey.Address())
|
||||
|
||||
msgSend := &banktypes.MsgSend{
|
||||
FromAddress: val.GetAddress().String(),
|
||||
ToAddress: newAddr.String(),
|
||||
Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(2000))),
|
||||
}
|
||||
_, err = clitestutil.SubmitTestTx(
|
||||
val.GetClientCtx(),
|
||||
msgSend,
|
||||
val.GetAddress(),
|
||||
clitestutil.TestTxConfig{},
|
||||
)
|
||||
|
||||
require.NoError(err)
|
||||
require.NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// delegate 500 tokens to validator1
|
||||
msg := &stakingtypes.MsgDelegate{
|
||||
DelegatorAddress: newAddr.String(),
|
||||
ValidatorAddress: val.GetValAddress().String(),
|
||||
Amount: sdk.NewCoin("stake", math.NewInt(500)),
|
||||
}
|
||||
|
||||
_, err = clitestutil.SubmitTestTx(val.GetClientCtx(), msg, newAddr, clitestutil.TestTxConfig{})
|
||||
require.NoError(err)
|
||||
require.NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// delegate 500 tokens to validator2
|
||||
msg2 := &stakingtypes.MsgDelegate{
|
||||
DelegatorAddress: newAddr.String(),
|
||||
ValidatorAddress: val1.GetValAddress().String(),
|
||||
Amount: sdk.NewCoin("stake", math.NewInt(500)),
|
||||
}
|
||||
|
||||
_, err = clitestutil.SubmitTestTx(val.GetClientCtx(), msg2, newAddr, clitestutil.TestTxConfig{})
|
||||
require.NoError(err)
|
||||
require.NoError(s.network.WaitForNextBlock())
|
||||
|
||||
err = s.network.RetryForBlocks(func() error {
|
||||
args := []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
|
||||
fmt.Sprintf("--%s=1", cli.FlagMaxMessagesPerTx),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()),
|
||||
}
|
||||
cmd := cli.NewWithdrawAllRewardsCmd()
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// expect 2 transactions in the generated file when --max-msgs in a tx set 1.
|
||||
txLen := len(strings.Split(strings.Trim(out.String(), "\n"), "\n"))
|
||||
if txLen != 2 {
|
||||
return fmt.Errorf("expected 2 transactions in the generated file, got %d", txLen)
|
||||
}
|
||||
return nil
|
||||
}, 3)
|
||||
require.NoError(err)
|
||||
|
||||
args := []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
|
||||
fmt.Sprintf("--%s=2", cli.FlagMaxMessagesPerTx),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()),
|
||||
}
|
||||
cmd := cli.NewWithdrawAllRewardsCmd()
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
require.NoError(err)
|
||||
// expect 1 transaction in the generated file when --max-msgs in a tx set 2, since there are only delegations.
|
||||
s.Require().Equal(1, len(strings.Split(strings.Trim(out.String(), "\n"), "\n")))
|
||||
}
|
||||
@ -607,7 +607,7 @@ func TestAuthzExecRedelegateAuthorization(t *testing.T) {
|
||||
msgRedelegateTypeURL, granterAddr, val1Addr, val2Addr, testDenom, redelegationAmount)
|
||||
execMsg := WriteToTempJSONFile(t, redelegateTx)
|
||||
|
||||
redelegateCmd := []string{"tx", "authz", "exec", execMsg.Name(), "--from=" + granteeAddr, "--gas=auto"}
|
||||
redelegateCmd := []string{"tx", "authz", "exec", execMsg.Name(), "--from=" + granteeAddr, "--gas=500000", "--fees=10stake"}
|
||||
rsp = cli.RunAndWait(redelegateCmd...)
|
||||
RequireTxSuccess(t, rsp)
|
||||
|
||||
|
||||
301
tests/systemtests/distribution_test.go
Normal file
301
tests/systemtests/distribution_test.go
Normal file
@ -0,0 +1,301 @@
|
||||
//go:build system_test
|
||||
|
||||
package systemtests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/tidwall/sjson"
|
||||
)
|
||||
|
||||
const (
|
||||
distrTestDenom = "stake"
|
||||
)
|
||||
|
||||
func TestWithdrawAllRewardsCmd(t *testing.T) {
|
||||
// scenario: test distribution withdraw all rewards command
|
||||
// given a running chain
|
||||
|
||||
sut.ResetChain(t)
|
||||
cli := NewCLIWrapper(t, sut, verbose)
|
||||
|
||||
newAddr := cli.AddKey("newAddr")
|
||||
require.NotEmpty(t, newAddr)
|
||||
|
||||
var initialAmount int64 = 10000000
|
||||
initialBalance := fmt.Sprintf("%d%s", initialAmount, distrTestDenom)
|
||||
sut.ModifyGenesisCLI(t,
|
||||
[]string{"genesis", "add-genesis-account", newAddr, initialBalance},
|
||||
)
|
||||
sut.StartChain(t)
|
||||
|
||||
// query balance
|
||||
newAddrBal := cli.QueryBalance(newAddr, distrTestDenom)
|
||||
require.Equal(t, initialAmount, newAddrBal)
|
||||
|
||||
// query validator operator address
|
||||
rsp := cli.CustomQuery("q", "staking", "validators")
|
||||
validators := gjson.Get(rsp, "validators.#.operator_address").Array()
|
||||
require.GreaterOrEqual(t, len(validators), 2)
|
||||
val1Addr := validators[0].String()
|
||||
val2Addr := validators[1].String()
|
||||
|
||||
var delegationAmount int64 = 100000
|
||||
delegation := fmt.Sprintf("%d%s", delegationAmount, distrTestDenom)
|
||||
|
||||
// delegate tokens to validator1
|
||||
rsp = cli.RunAndWait("tx", "staking", "delegate", val1Addr, delegation, "--from="+newAddr, "--fees=1"+distrTestDenom)
|
||||
RequireTxSuccess(t, rsp)
|
||||
|
||||
// delegate tokens to validator2
|
||||
rsp = cli.RunAndWait("tx", "staking", "delegate", val2Addr, delegation, "--from="+newAddr, "--fees=1"+distrTestDenom)
|
||||
RequireTxSuccess(t, rsp)
|
||||
|
||||
// check updated balance: newAddrBal - delegatedBal - fees
|
||||
expBal := newAddrBal - (delegationAmount * 2) - 2
|
||||
newAddrBal = cli.QueryBalance(newAddr, distrTestDenom)
|
||||
require.Equal(t, expBal, newAddrBal)
|
||||
|
||||
withdrawCmdArgs := []string{"tx", "distribution", "withdraw-all-rewards", "--from=" + newAddr, "--fees=1" + distrTestDenom}
|
||||
|
||||
// test with --max-msgs
|
||||
testCases := []struct {
|
||||
name string
|
||||
maxMsgs int
|
||||
expTxLen int
|
||||
}{
|
||||
{
|
||||
"--max-msgs value is 1",
|
||||
1,
|
||||
2,
|
||||
},
|
||||
{
|
||||
"--max-msgs value is 2",
|
||||
2,
|
||||
1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assertGenOnlyOutput := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool {
|
||||
require.Len(t, gotOutputs, 1)
|
||||
// gets output combining two objects without any space or new line
|
||||
splitOutput := strings.Split(gotOutputs[0].(string), "}{")
|
||||
require.Len(t, splitOutput, tc.expTxLen)
|
||||
return false
|
||||
}
|
||||
cmd := append(withdrawCmdArgs, fmt.Sprintf("--max-msgs=%d", tc.maxMsgs), "--generate-only")
|
||||
_ = cli.WithRunErrorMatcher(assertGenOnlyOutput).Run(cmd...)
|
||||
})
|
||||
}
|
||||
|
||||
// test withdraw-all-rewards transaction
|
||||
rsp = cli.RunAndWait(withdrawCmdArgs...)
|
||||
RequireTxSuccess(t, rsp)
|
||||
}
|
||||
|
||||
func TestDistrValidatorGRPCQueries(t *testing.T) {
|
||||
// scenario: test distribution validator grpc gateway queries
|
||||
// given a running chain
|
||||
|
||||
sut.ResetChain(t)
|
||||
cli := NewCLIWrapper(t, sut, verbose)
|
||||
// get validator address
|
||||
valAddr := cli.GetKeyAddr("node0")
|
||||
require.NotEmpty(t, valAddr)
|
||||
valOperAddr := cli.GetKeyAddrPrefix("node0", "val")
|
||||
require.NotEmpty(t, valOperAddr)
|
||||
|
||||
sut.StartChain(t)
|
||||
|
||||
sut.AwaitNBlocks(t, 3)
|
||||
|
||||
baseurl := sut.APIAddress()
|
||||
expectedAmountOutput := fmt.Sprintf(`{"denom":"%s","amount":"203.105000000000000000"}`, distrTestDenom)
|
||||
|
||||
// test params grpc endpoint
|
||||
paramsURL := baseurl + "/cosmos/distribution/v1beta1/params"
|
||||
|
||||
paramsTestCases := []RestTestCase{
|
||||
{
|
||||
"gRPC request params",
|
||||
paramsURL,
|
||||
http.StatusOK,
|
||||
`{"params":{"community_tax":"0.020000000000000000","base_proposer_reward":"0.000000000000000000","bonus_proposer_reward":"0.000000000000000000","withdraw_addr_enabled":true}}`,
|
||||
},
|
||||
}
|
||||
RunRestQueries(t, paramsTestCases)
|
||||
|
||||
// test validator distribution info grpc endpoint
|
||||
validatorsURL := baseurl + `/cosmos/distribution/v1beta1/validators/%s`
|
||||
validatorsOutput := fmt.Sprintf(`{"operator_address":"%s","self_bond_rewards":[],"commission":[%s]}`, valAddr, expectedAmountOutput)
|
||||
|
||||
validatorsTestCases := []RestTestCase{
|
||||
{
|
||||
"gRPC request validator with valid validator address",
|
||||
fmt.Sprintf(validatorsURL, valOperAddr),
|
||||
http.StatusOK,
|
||||
validatorsOutput,
|
||||
},
|
||||
}
|
||||
TestRestQueryIgnoreNumbers(t, validatorsTestCases)
|
||||
|
||||
// test outstanding rewards grpc endpoint
|
||||
outstandingRewardsURL := baseurl + `/cosmos/distribution/v1beta1/validators/%s/outstanding_rewards`
|
||||
|
||||
rewardsTestCases := []RestTestCase{
|
||||
{
|
||||
"gRPC request outstanding rewards with valid validator address",
|
||||
fmt.Sprintf(outstandingRewardsURL, valOperAddr),
|
||||
http.StatusOK,
|
||||
fmt.Sprintf(`{"rewards":{"rewards":[%s]}}`, expectedAmountOutput),
|
||||
},
|
||||
}
|
||||
TestRestQueryIgnoreNumbers(t, rewardsTestCases)
|
||||
|
||||
// test validator commission grpc endpoint
|
||||
commissionURL := baseurl + `/cosmos/distribution/v1beta1/validators/%s/commission`
|
||||
|
||||
commissionTestCases := []RestTestCase{
|
||||
{
|
||||
"gRPC request commission with valid validator address",
|
||||
fmt.Sprintf(commissionURL, valOperAddr),
|
||||
http.StatusOK,
|
||||
fmt.Sprintf(`{"commission":{"commission":[%s]}}`, expectedAmountOutput),
|
||||
},
|
||||
}
|
||||
TestRestQueryIgnoreNumbers(t, commissionTestCases)
|
||||
|
||||
// test validator slashes grpc endpoint
|
||||
slashURL := baseurl + `/cosmos/distribution/v1beta1/validators/%s/slashes`
|
||||
invalidHeightOutput := `{"code":3, "message":"strconv.ParseUint: parsing \"-3\": invalid syntax", "details":[]}`
|
||||
|
||||
slashTestCases := []RestTestCase{
|
||||
{
|
||||
"invalid start height",
|
||||
fmt.Sprintf(slashURL+`?starting_height=%s&ending_height=%s`, valOperAddr, "-3", "3"),
|
||||
http.StatusBadRequest,
|
||||
invalidHeightOutput,
|
||||
},
|
||||
{
|
||||
"invalid end height",
|
||||
fmt.Sprintf(slashURL+`?starting_height=%s&ending_height=%s`, valOperAddr, "1", "-3"),
|
||||
http.StatusBadRequest,
|
||||
invalidHeightOutput,
|
||||
},
|
||||
{
|
||||
"valid request get slashes",
|
||||
fmt.Sprintf(slashURL+`?starting_height=%s&ending_height=%s`, valOperAddr, "1", "3"),
|
||||
http.StatusOK,
|
||||
`{"slashes":[],"pagination":{"next_key":null,"total":"0"}}`,
|
||||
},
|
||||
}
|
||||
RunRestQueries(t, slashTestCases)
|
||||
}
|
||||
|
||||
func TestDistrDelegatorGRPCQueries(t *testing.T) {
|
||||
// scenario: test distribution validator gsrpc gateway queries
|
||||
// given a running chain
|
||||
|
||||
sut.ResetChain(t)
|
||||
cli := NewCLIWrapper(t, sut, verbose)
|
||||
|
||||
// get validator address
|
||||
valAddr := cli.GetKeyAddr("node0")
|
||||
require.NotEmpty(t, valAddr)
|
||||
valOperAddr := cli.GetKeyAddrPrefix("node0", "val")
|
||||
require.NotEmpty(t, valOperAddr)
|
||||
|
||||
// update commission rate of node0 validator
|
||||
// generate new gentx and copy it to genesis.json before starting network
|
||||
rsp := cli.RunCommandWithArgs("genesis", "gentx", "node0", "100000000"+distrTestDenom, "--chain-id="+cli.chainID, "--commission-rate=0.01", "--home", sut.nodePath(0), "--keyring-backend=test")
|
||||
// extract gentx path from above command output
|
||||
re := regexp.MustCompile(`"(.*?\.json)"`)
|
||||
match := re.FindStringSubmatch(rsp)
|
||||
require.GreaterOrEqual(t, len(match), 1)
|
||||
|
||||
updatedGentx := filepath.Join(WorkDir, match[1])
|
||||
updatedGentxBz, err := os.ReadFile(updatedGentx) // #nosec G304
|
||||
require.NoError(t, err)
|
||||
|
||||
sut.ModifyGenesisJSON(t, func(genesis []byte) []byte {
|
||||
state, err := sjson.SetRawBytes(genesis, "app_state.genutil.gen_txs.0", updatedGentxBz)
|
||||
require.NoError(t, err)
|
||||
return state
|
||||
})
|
||||
|
||||
// create new address which will be used as delegator address
|
||||
delAddr := cli.AddKey("delAddr")
|
||||
require.NotEmpty(t, delAddr)
|
||||
|
||||
var initialAmount int64 = 1000000000
|
||||
initialBalance := fmt.Sprintf("%d%s", initialAmount, distrTestDenom)
|
||||
sut.ModifyGenesisCLI(t,
|
||||
[]string{"genesis", "add-genesis-account", delAddr, initialBalance},
|
||||
)
|
||||
|
||||
sut.StartChain(t)
|
||||
|
||||
// delegate some tokens to valOperAddr
|
||||
rsp = cli.RunAndWait("tx", "staking", "delegate", valOperAddr, "100000000"+distrTestDenom, "--from="+delAddr)
|
||||
RequireTxSuccess(t, rsp)
|
||||
|
||||
sut.AwaitNBlocks(t, 5)
|
||||
|
||||
baseurl := sut.APIAddress()
|
||||
|
||||
// test delegator rewards grpc endpoint
|
||||
delegatorRewardsURL := baseurl + `/cosmos/distribution/v1beta1/delegators/%s/rewards`
|
||||
expectedAmountOutput := `{"denom":"stake","amount":"0.121275000000000000"}`
|
||||
rewardsOutput := fmt.Sprintf(`{"rewards":[{"validator_address":"%s","reward":[%s]}],"total":[%s]}`, valOperAddr, expectedAmountOutput, expectedAmountOutput)
|
||||
|
||||
delegatorRewardsTestCases := []RestTestCase{
|
||||
{
|
||||
"valid rewards request with valid delegator address",
|
||||
fmt.Sprintf(delegatorRewardsURL, delAddr),
|
||||
http.StatusOK,
|
||||
rewardsOutput,
|
||||
},
|
||||
{
|
||||
"valid request(specific validator rewards)",
|
||||
fmt.Sprintf(delegatorRewardsURL+`/%s`, delAddr, valOperAddr),
|
||||
http.StatusOK,
|
||||
fmt.Sprintf(`{"rewards":[%s]}`, expectedAmountOutput),
|
||||
},
|
||||
}
|
||||
TestRestQueryIgnoreNumbers(t, delegatorRewardsTestCases)
|
||||
|
||||
// test delegator validators grpc endpoint
|
||||
delegatorValsURL := baseurl + `/cosmos/distribution/v1beta1/delegators/%s/validators`
|
||||
valsTestCases := []RestTestCase{
|
||||
{
|
||||
"gRPC request delegator validators with valid delegator address",
|
||||
fmt.Sprintf(delegatorValsURL, delAddr),
|
||||
http.StatusOK,
|
||||
fmt.Sprintf(`{"validators":["%s"]}`, valOperAddr),
|
||||
},
|
||||
}
|
||||
RunRestQueries(t, valsTestCases)
|
||||
|
||||
// test withdraw address grpc endpoint
|
||||
withdrawAddrURL := baseurl + `/cosmos/distribution/v1beta1/delegators/%s/withdraw_address`
|
||||
withdrawAddrTestCases := []RestTestCase{
|
||||
{
|
||||
"gRPC request withdraw address with valid delegator address",
|
||||
fmt.Sprintf(withdrawAddrURL, delAddr),
|
||||
http.StatusOK,
|
||||
fmt.Sprintf(`{"withdraw_address":"%s"}`, delAddr),
|
||||
},
|
||||
}
|
||||
RunRestQueries(t, withdrawAddrTestCases)
|
||||
}
|
||||
@ -3,9 +3,12 @@ package systemtests
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
)
|
||||
|
||||
type RestTestCase struct {
|
||||
@ -28,6 +31,34 @@ func RunRestQueries(t *testing.T, testCases []RestTestCase) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestRestQueryIgnoreNumbers runs given rest testcases by making requests and
|
||||
// checking response with expected output ignoring number values
|
||||
// This method is used when number values in response are non-deterministic
|
||||
func TestRestQueryIgnoreNumbers(t *testing.T, testCases []RestTestCase) {
|
||||
t.Helper()
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
resp, err := testutil.GetRequest(tc.url)
|
||||
require.NoError(t, err)
|
||||
|
||||
// regular expression pattern to match any numeric value in the JSON
|
||||
numberRegexPattern := `"\d+(\.\d+)?"`
|
||||
|
||||
// compile the regex
|
||||
r, err := regexp.Compile(numberRegexPattern)
|
||||
require.NoError(t, err)
|
||||
|
||||
// replace all numeric values in the above JSONs with `NUMBER` text
|
||||
expectedJSON := r.ReplaceAllString(tc.expOut, `"NUMBER"`)
|
||||
actualJSON := r.ReplaceAllString(string(resp), `"NUMBER"`)
|
||||
|
||||
// compare two jsons
|
||||
require.JSONEq(t, expectedJSON, actualJSON)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func GetRequest(t *testing.T, url string) []byte {
|
||||
t.Helper()
|
||||
return GetRequestWithHeaders(t, url, nil, http.StatusOK)
|
||||
|
||||
@ -132,12 +132,17 @@ func (s *SystemUnderTest) SetupChain() {
|
||||
|
||||
genesisBz, err = sjson.SetRawBytes(genesisBz, "consensus.params.block.max_gas", []byte(fmt.Sprintf(`"%d"`, 10_000_000)))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed set block max gas: %s", err))
|
||||
panic(fmt.Sprintf("failed to set block max gas: %s", err))
|
||||
}
|
||||
// Short period for gov
|
||||
genesisBz, err = sjson.SetRawBytes(genesisBz, "app_state.gov.params.voting_period", []byte(fmt.Sprintf(`"%s"`, "8s")))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed set voting period: %s", err))
|
||||
panic(fmt.Sprintf("failed to set regular voting period: %s", err))
|
||||
}
|
||||
// update expedited voting period to avoid validation error
|
||||
genesisBz, err = sjson.SetRawBytes(genesisBz, "app_state.gov.params.expedited_voting_period", []byte(fmt.Sprintf(`"%s"`, "7s")))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to set expedited voting period: %s", err))
|
||||
}
|
||||
s.withEachNodeHome(func(i int, home string) {
|
||||
if err := saveGenesis(home, genesisBz); err != nil {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user