Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add staking cli test #33

Merged
merged 14 commits into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions cli_test/helpers/fixtures.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package helpers

import (
codecstd "github.com/cosmos/cosmos-sdk/codec/std"
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
"io/ioutil"
"os"
"path/filepath"
Expand All @@ -26,9 +28,19 @@ type Fixtures struct {
SimdHome string
SimcliHome string
P2PAddr string
Cdc *codec.Codec
T *testing.T
}

var (
cdc = codecstd.MakeCodec(simapp.ModuleBasics)
appCodec = codecstd.NewAppCodec(cdc)
)

func init() {
authclient.Codec = appCodec
}

// NewFixtures creates a new instance of Fixtures with many vars set
func NewFixtures(t *testing.T) *Fixtures {
tmpDir, err := ioutil.TempDir("", "sdk_integration_"+t.Name()+"_")
Expand All @@ -42,7 +54,7 @@ func NewFixtures(t *testing.T) *Fixtures {

buildDir := os.Getenv("BUILDDIR")
if buildDir == "" {
buildDir, err = filepath.Abs("../../build/")
buildDir, err = filepath.Abs("../../../../build/")
require.NoError(t, err)
}

Expand All @@ -56,6 +68,7 @@ func NewFixtures(t *testing.T) *Fixtures {
SimcliHome: filepath.Join(tmpDir, ".simcli"),
RPCAddr: servAddr,
P2PAddr: p2pAddr,
Cdc: cdc,
Port: port,
}
}
Expand All @@ -67,11 +80,10 @@ func (f Fixtures) GenesisFile() string {

// GenesisFile returns the application's genesis state
func (f Fixtures) GenesisState() simapp.GenesisState {
cdc := codec.New()
genDoc, err := tmtypes.GenesisDocFromFile(f.GenesisFile())
require.NoError(f.T, err)

var appState simapp.GenesisState
require.NoError(f.T, cdc.UnmarshalJSON(genDoc.AppState, &appState))
require.NoError(f.T, f.Cdc.UnmarshalJSON(genDoc.AppState, &appState))
return appState
}
65 changes: 58 additions & 7 deletions cli_test/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package helpers
import (
"encoding/json"
"fmt"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/staking"
"os"
"path/filepath"
"strings"

"github.com/cosmos/cosmos-sdk/x/staking"

"github.com/stretchr/testify/require"

clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
Expand Down Expand Up @@ -216,6 +217,24 @@ func (f *Fixtures) TxStakingCreateValidator(from, consPubKey string, amount sdk.
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), clientkeys.DefaultKeyPass)
}

func (f *Fixtures) TxStakingEditValidator(from string, flags ...string) (bool, string, string) {
cmd := fmt.Sprintf("%s tx staking edit-validator %v --keyring-backend=test "+
"--from=%s", f.SimcliBinary, f.Flags(), from)
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), clientkeys.DefaultKeyPass)
}

func (f *Fixtures) TxStakingDelegate(validatorOperatorAddress, from string, amount sdk.Coin, flags ...string) (bool, string, string) {
cmd := fmt.Sprintf("%s tx staking delegate %s %v %v --keyring-backend=test "+
"--from=%s", f.SimcliBinary, validatorOperatorAddress, amount, f.Flags(), from)
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), clientkeys.DefaultKeyPass)
}

func (f *Fixtures) TxStakingReDelegate(srcOperatorAddress, dstOperatorAddress, from string, amount sdk.Coin, flags ...string) (bool, string, string) {
cmd := fmt.Sprintf("%s tx staking redelegate %s %s %v %v --keyring-backend=test "+
"--from=%s", f.SimcliBinary, srcOperatorAddress, dstOperatorAddress, amount, f.Flags(), from)
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), clientkeys.DefaultKeyPass)
}

// TxStakingUnbond is gaiacli tx staking unbond
func (f *Fixtures) TxStakingUnbond(from, shares string, validator sdk.ValAddress, flags ...string) bool {
cmd := fmt.Sprintf("%s tx staking unbond --keyring-backend=test %s %v --from=%s %v",
Expand All @@ -229,7 +248,7 @@ func (f *Fixtures) QueryStakingValidator(valAddr sdk.ValAddress, flags ...string
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
var validator staking.Validator

err := cdc.UnmarshalJSON([]byte(out), &validator)
err := f.Cdc.UnmarshalJSON([]byte(out), &validator)
require.NoError(f.T, err, "out %v\n, err %v", out, err)
return validator
}
Expand All @@ -240,7 +259,7 @@ func (f *Fixtures) QueryStakingUnbondingDelegationsFrom(valAddr sdk.ValAddress,
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
var ubds []staking.UnbondingDelegation

err := cdc.UnmarshalJSON([]byte(out), &ubds)
err := f.Cdc.UnmarshalJSON([]byte(out), &ubds)
require.NoError(f.T, err, "out %v\n, err %v", out, err)
return ubds
}
Expand All @@ -251,7 +270,7 @@ func (f *Fixtures) QueryStakingDelegationsTo(valAddr sdk.ValAddress, flags ...st
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
var delegations []staking.Delegation

err := cdc.UnmarshalJSON([]byte(out), &delegations)
err := f.Cdc.UnmarshalJSON([]byte(out), &delegations)
require.NoError(f.T, err, "out %v\n, err %v", out, err)
return delegations
}
Expand All @@ -262,7 +281,7 @@ func (f *Fixtures) QueryStakingPool(flags ...string) staking.Pool {
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
var pool staking.Pool

err := cdc.UnmarshalJSON([]byte(out), &pool)
err := f.Cdc.UnmarshalJSON([]byte(out), &pool)
require.NoError(f.T, err, "out %v\n, err %v", out, err)
return pool
}
Expand All @@ -273,7 +292,39 @@ func (f *Fixtures) QueryStakingParameters(flags ...string) staking.Params {
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
var params staking.Params

err := cdc.UnmarshalJSON([]byte(out), &params)
err := f.Cdc.UnmarshalJSON([]byte(out), &params)
require.NoError(f.T, err, "out %v\n, err %v", out, err)
return params
}

//___________________________________________________________________________________
// gaiacli query account

// QueryAccount is gaiacli query account
func (f *Fixtures) QueryAccount(address sdk.AccAddress, flags ...string) auth.BaseAccount {
cmd := fmt.Sprintf("%s query account %s %v", f.SimcliBinary, address, f.Flags())
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
var initRes map[string]json.RawMessage
err := json.Unmarshal([]byte(out), &initRes)
require.NoError(f.T, err, "out %v, err %v", out, err)
value := initRes["value"]
var acc auth.BaseAccount
cdc := codec.New()
codec.RegisterCrypto(cdc)
err = cdc.UnmarshalJSON(value, &acc)
require.NoError(f.T, err, "value %v, err %v", string(value), err)
return acc
}

// QueryBalances executes the bank query balances command for a given address and
// flag set.
func (f *Fixtures) QueryBalances(address sdk.AccAddress, flags ...string) sdk.Coins {
cmd := fmt.Sprintf("%s query bank balances %s %v", f.SimcliBinary, address, f.Flags())
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")

var balances sdk.Coins

require.NoError(f.T, f.Cdc.UnmarshalJSON([]byte(out), &balances), "out %v\n", out)

return balances
}
25 changes: 24 additions & 1 deletion cli_test/helpers/utils.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
package helpers

import "strings"
import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/stretchr/testify/require"
"strings"
"testing"
)

func addFlags(cmd string, flags []string) string {
for _, f := range flags {
cmd += " " + f
}
return strings.TrimSpace(cmd)
}

//nolint:deadcode,unused
func UnmarshalStdTx(t *testing.T, c *codec.Codec, s string) (stdTx auth.StdTx) {
require.Nil(t, c.UnmarshalJSON([]byte(s), &stdTx))
return
}

func FindDelegateAccount(validatorDelegations []staking.Delegation, delegatorAddress string) staking.Delegation {
for i := 0; i < len(validatorDelegations); i++ {
if validatorDelegations[i].DelegatorAddress.String() == delegatorAddress {
return validatorDelegations[i]
}
}

return staking.Delegation{}
}
16 changes: 0 additions & 16 deletions cli_test/tests/codec.go

This file was deleted.

File renamed without changes.
78 changes: 78 additions & 0 deletions x/bank/client/cli/send_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package cli_test

import (
"github.com/cosmos/cosmos-sdk/cli_test/helpers"
"github.com/cosmos/cosmos-sdk/tests"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"testing"
)

func TestCLISend(t *testing.T) {
t.Parallel()
f := helpers.InitFixtures(t)

// start gaiad server
proc := f.SDStart()
defer proc.Stop(false)

// Save key addresses for later uspackage testse
fooAddr := f.KeyAddress(helpers.KeyFoo)
barAddr := f.KeyAddress(helpers.KeyBar)

startTokens := sdk.TokensFromConsensusPower(50)
require.Equal(t, startTokens, f.QueryBalances(fooAddr).AmountOf(helpers.Denom))

sendTokens := sdk.TokensFromConsensusPower(10)

// It does not allow to send in offline mode
success, _, stdErr := f.TxSend(helpers.KeyFoo, barAddr, sdk.NewCoin(helpers.Denom, sendTokens), "-y", "--offline")
require.Contains(t, stdErr, "no RPC client is defined in offline mode")
require.False(f.T, success)
tests.WaitForNextNBlocksTM(1, f.Port)

// Send some tokens from one account to the other
f.TxSend(helpers.KeyFoo, barAddr, sdk.NewCoin(helpers.Denom, sendTokens), "-y")
tests.WaitForNextNBlocksTM(1, f.Port)

// Ensure account balances match expected
require.Equal(t, sendTokens, f.QueryBalances(barAddr).AmountOf(helpers.Denom))
require.Equal(t, startTokens.Sub(sendTokens), f.QueryBalances(fooAddr).AmountOf(helpers.Denom))

// Test --dry-run
success, _, _ = f.TxSend(helpers.KeyFoo, barAddr, sdk.NewCoin(helpers.Denom, sendTokens), "--dry-run")
require.True(t, success)

// Test --generate-only
success, stdout, stderr := f.TxSend(
fooAddr.String(), barAddr, sdk.NewCoin(helpers.Denom, sendTokens), "--generate-only=true",
)
require.Empty(t, stderr)
require.True(t, success)
msg := helpers.UnmarshalStdTx(f.T, f.Cdc, stdout)
t.Log(msg)
require.NotZero(t, msg.Fee.Gas)
require.Len(t, msg.Msgs, 1)
require.Len(t, msg.GetSignatures(), 0)

// Check state didn't change
require.Equal(t, startTokens.Sub(sendTokens), f.QueryBalances(fooAddr).AmountOf(helpers.Denom))

// test autosequencing
f.TxSend(helpers.KeyFoo, barAddr, sdk.NewCoin(helpers.Denom, sendTokens), "-y")
tests.WaitForNextNBlocksTM(1, f.Port)

// Ensure account balances match expected
require.Equal(t, sendTokens.MulRaw(2), f.QueryBalances(barAddr).AmountOf(helpers.Denom))
require.Equal(t, startTokens.Sub(sendTokens.MulRaw(2)), f.QueryBalances(fooAddr).AmountOf(helpers.Denom))

// test memo
f.TxSend(helpers.KeyFoo, barAddr, sdk.NewCoin(helpers.Denom, sendTokens), "--memo='testmemo'", "-y")
tests.WaitForNextNBlocksTM(1, f.Port)

// Ensure account balances match expected
require.Equal(t, sendTokens.MulRaw(3), f.QueryBalances(barAddr).AmountOf(helpers.Denom))
require.Equal(t, startTokens.Sub(sendTokens.MulRaw(3)), f.QueryBalances(fooAddr).AmountOf(helpers.Denom))

f.Cleanup()
}
84 changes: 84 additions & 0 deletions x/staking/client/cli/staking_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package cli_test

import (
"github.com/cosmos/cosmos-sdk/cli_test/helpers"
"github.com/cosmos/cosmos-sdk/tests"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519"
"testing"
)

//-----------------------------------------------------------------------------------
//staking tx

func TestCLICreateValidator(t *testing.T) {
t.Parallel()
f := helpers.InitFixtures(t)

// start gaiad server
proc := f.SDStart()
defer proc.Stop(false)

barAddr := f.KeyAddress(helpers.KeyBar)
barVal := sdk.ValAddress(barAddr)

consPubKey := sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, ed25519.GenPrivKey().PubKey())

sendTokens := sdk.TokensFromConsensusPower(10)
f.TxSend(helpers.KeyFoo, barAddr, sdk.NewCoin(helpers.Denom, sendTokens), "-y")
tests.WaitForNextNBlocksTM(1, f.Port)

require.Equal(t, sendTokens, f.QueryBalances(barAddr).AmountOf(helpers.Denom))

// Generate a create validator transaction and ensure correctness
success, stdout, stderr := f.TxStakingCreateValidator(barAddr.String(), consPubKey, sdk.NewInt64Coin(helpers.Denom, 2), "--generate-only")
require.True(f.T, success)
require.Empty(f.T, stderr)

msg := helpers.UnmarshalStdTx(f.T, f.Cdc, stdout)
require.NotZero(t, msg.Fee.Gas)
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 0, len(msg.GetSignatures()))

// Test --dry-run
newValTokens := sdk.TokensFromConsensusPower(2)
success, _, _ = f.TxStakingCreateValidator(barAddr.String(), consPubKey, sdk.NewCoin(helpers.Denom, newValTokens), "--dry-run")
require.True(t, success)

// Create the validator
f.TxStakingCreateValidator(helpers.KeyBar, consPubKey, sdk.NewCoin(helpers.Denom, newValTokens), "-y")
tests.WaitForNextNBlocksTM(1, f.Port)

// Ensure funds were deducted properly
require.Equal(t, sendTokens.Sub(newValTokens), f.QueryBalances(barAddr).AmountOf(helpers.Denom))

// Ensure that validator state is as expected
validator := f.QueryStakingValidator(barVal)
require.Equal(t, validator.OperatorAddress, barVal)
require.True(sdk.IntEq(t, newValTokens, validator.Tokens))

// Query delegations to the validator
validatorDelegations := f.QueryStakingDelegationsTo(barVal)
require.Len(t, validatorDelegations, 1)
require.NotZero(t, validatorDelegations[0].Shares)

// unbond a single share
unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(1))
success = f.TxStakingUnbond(helpers.KeyBar, unbondAmt.String(), barVal, "-y")
require.True(t, success)
tests.WaitForNextNBlocksTM(1, f.Port)

// Ensure bonded staking is correct
remainingTokens := newValTokens.Sub(unbondAmt.Amount)
validator = f.QueryStakingValidator(barVal)
require.Equal(t, remainingTokens, validator.Tokens)

// Get unbonding delegations from the validator
validatorUbds := f.QueryStakingUnbondingDelegationsFrom(barVal)
require.Len(t, validatorUbds, 1)
require.Len(t, validatorUbds[0].Entries, 1)
require.Equal(t, remainingTokens.String(), validatorUbds[0].Entries[0].Balance.String())

f.Cleanup()
}