Merge PR #6033: Add setup for cli_test

This commit is contained in:
SaReN
2020-04-29 11:52:30 -04:00
committed by GitHub
parent 5a9d3cfc70
commit 3b71198b25
15 changed files with 778 additions and 8 deletions
+13
View File
@@ -0,0 +1,13 @@
package helpers
const (
Denom = "stake"
KeyFoo = "foo"
KeyBar = "bar"
FooDenom = "footoken"
FeeDenom = "feetoken"
Fee2Denom = "fee2token"
KeyBaz = "baz"
KeyVesting = "vesting"
KeyFooBarBaz = "foobarbaz"
)
+49
View File
@@ -0,0 +1,49 @@
package helpers
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/tests"
)
func ExecuteWriteCheckErr(t *testing.T, cmdStr string, writes ...string) {
require.True(t, ExecuteWrite(t, cmdStr, writes...))
}
func ExecuteWrite(t *testing.T, cmdStr string, writes ...string) (exitSuccess bool) {
exitSuccess, _, _ = ExecuteWriteRetStdStreams(t, cmdStr, writes...)
return
}
func ExecuteWriteRetStdStreams(t *testing.T, cmdStr string, writes ...string) (bool, string, string) {
proc := tests.GoExecuteT(t, cmdStr)
// Enables use of interactive commands
for _, write := range writes {
_, err := proc.StdinPipe.Write([]byte(write + "\n"))
require.NoError(t, err)
}
// Read both stdout and stderr from the process
stdout, stderr, err := proc.ReadAll()
if err != nil {
fmt.Println("Err on proc.ReadAll()", err, cmdStr)
}
// Log output.
if len(stdout) > 0 {
t.Log("Stdout:", string(stdout))
}
if len(stderr) > 0 {
t.Log("Stderr:", string(stderr))
}
// Wait for process to exit
proc.Wait()
// Return succes, stdout, stderr
return proc.ExitState.Success(), string(stdout), string(stderr)
}
+78
View File
@@ -0,0 +1,78 @@
package helpers
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/cosmos/cosmos-sdk/std"
"github.com/stretchr/testify/require"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/simapp"
)
var cdc = std.MakeCodec(simapp.ModuleBasics)
// Fixtures is used to setup the testing environment
type Fixtures struct {
BuildDir string
RootDir string
SimdBinary string
SimcliBinary string
ChainID string
RPCAddr string
Port string
SimdHome string
SimcliHome string
P2PAddr string
Cdc *codec.Codec
T *testing.T
}
// 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()+"_")
require.NoError(t, err)
servAddr, port, err := server.FreeTCPAddr()
require.NoError(t, err)
p2pAddr, _, err := server.FreeTCPAddr()
require.NoError(t, err)
buildDir := os.Getenv("BUILDDIR")
require.NotNil(t, buildDir)
return &Fixtures{
T: t,
BuildDir: buildDir,
RootDir: tmpDir,
SimdBinary: filepath.Join(buildDir, "simd"),
SimcliBinary: filepath.Join(buildDir, "simcli"),
SimdHome: filepath.Join(tmpDir, ".simd"),
SimcliHome: filepath.Join(tmpDir, ".simcli"),
RPCAddr: servAddr,
P2PAddr: p2pAddr,
Cdc: cdc,
Port: port,
}
}
// GenesisFile returns the path of the genesis file
func (f Fixtures) GenesisFile() string {
return filepath.Join(f.SimdHome, "config", "genesis.json")
}
// GenesisFile returns the application's genesis state
func (f Fixtures) GenesisState() simapp.GenesisState {
genDoc, err := tmtypes.GenesisDocFromFile(f.GenesisFile())
require.NoError(f.T, err)
var appState simapp.GenesisState
require.NoError(f.T, f.Cdc.UnmarshalJSON(genDoc.AppState, &appState))
return appState
}
+195
View File
@@ -0,0 +1,195 @@
package helpers
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/require"
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/tests"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
)
var (
totalCoins = sdk.NewCoins(
sdk.NewCoin(Fee2Denom, sdk.TokensFromConsensusPower(2000000)),
sdk.NewCoin(FeeDenom, sdk.TokensFromConsensusPower(2000000)),
sdk.NewCoin(FooDenom, sdk.TokensFromConsensusPower(2000)),
sdk.NewCoin(Denom, sdk.TokensFromConsensusPower(300).Add(sdk.NewInt(12))), // add coins from inflation
)
startCoins = sdk.NewCoins(
sdk.NewCoin(Fee2Denom, sdk.TokensFromConsensusPower(1000000)),
sdk.NewCoin(FeeDenom, sdk.TokensFromConsensusPower(1000000)),
sdk.NewCoin(FooDenom, sdk.TokensFromConsensusPower(1000)),
sdk.NewCoin(Denom, sdk.TokensFromConsensusPower(150)),
)
vestingCoins = sdk.NewCoins(
sdk.NewCoin(FeeDenom, sdk.TokensFromConsensusPower(500000)),
)
)
//___________________________________________________________________________________
// simd
// UnsafeResetAll is simd unsafe-reset-all
func (f *Fixtures) UnsafeResetAll(flags ...string) {
cmd := fmt.Sprintf("%s --home=%s unsafe-reset-all", f.SimdBinary, f.SimdHome)
ExecuteWrite(f.T, AddFlags(cmd, flags))
err := os.RemoveAll(filepath.Join(f.SimdHome, "config", "gentx"))
require.NoError(f.T, err)
}
// SDInit is simd init
// NOTE: SDInit sets the ChainID for the Fixtures instance
func (f *Fixtures) SDInit(moniker string, flags ...string) {
cmd := fmt.Sprintf("%s init -o --home=%s %s", f.SimdBinary, f.SimdHome, moniker)
_, stderr := tests.ExecuteT(f.T, AddFlags(cmd, flags), clientkeys.DefaultKeyPass)
var chainID string
var initRes map[string]json.RawMessage
err := json.Unmarshal([]byte(stderr), &initRes)
require.NoError(f.T, err)
err = json.Unmarshal(initRes["chain_id"], &chainID)
require.NoError(f.T, err)
f.ChainID = chainID
}
// AddGenesisAccount is simd add-genesis-account
func (f *Fixtures) AddGenesisAccount(address sdk.AccAddress, coins sdk.Coins, flags ...string) {
cmd := fmt.Sprintf("%s add-genesis-account %s %s --home=%s --keyring-backend=test", f.SimdBinary, address, coins, f.SimdHome)
ExecuteWriteCheckErr(f.T, AddFlags(cmd, flags))
}
// GenTx is simd gentx
func (f *Fixtures) GenTx(name string, flags ...string) {
cmd := fmt.Sprintf("%s gentx --name=%s --home=%s --home-client=%s --keyring-backend=test", f.SimdBinary, name, f.SimdHome, f.SimcliHome)
ExecuteWriteCheckErr(f.T, AddFlags(cmd, flags))
}
// CollectGenTxs is simd collect-gentxs
func (f *Fixtures) CollectGenTxs(flags ...string) {
cmd := fmt.Sprintf("%s collect-gentxs --home=%s", f.SimdBinary, f.SimdHome)
ExecuteWriteCheckErr(f.T, AddFlags(cmd, flags))
}
// SDStart runs simd start with the appropriate flags and returns a process
func (f *Fixtures) SDStart(flags ...string) *tests.Process {
cmd := fmt.Sprintf("%s start --home=%s --rpc.laddr=%v --p2p.laddr=%v", f.SimdBinary, f.SimdHome, f.RPCAddr, f.P2PAddr)
proc := tests.GoExecuteTWithStdout(f.T, AddFlags(cmd, flags))
tests.WaitForTMStart(f.Port)
tests.WaitForNextNBlocksTM(1, f.Port)
return proc
}
// SDTendermint returns the results of simd tendermint [query]
func (f *Fixtures) SDTendermint(query string) string {
cmd := fmt.Sprintf("%s tendermint %s --home=%s", f.SimdBinary, query, f.SimdHome)
success, stdout, stderr := ExecuteWriteRetStdStreams(f.T, cmd)
require.Empty(f.T, stderr)
require.True(f.T, success)
return strings.TrimSpace(stdout)
}
// ValidateGenesis runs simd validate-genesis
func (f *Fixtures) ValidateGenesis() {
cmd := fmt.Sprintf("%s validate-genesis --home=%s", f.SimdBinary, f.SimdHome)
ExecuteWriteCheckErr(f.T, cmd)
}
//___________________________________________________________________________________
// simcli keys
// KeysDelete is simcli keys delete
func (f *Fixtures) KeysDelete(name string, flags ...string) {
cmd := fmt.Sprintf("%s keys delete --keyring-backend=test --home=%s %s", f.SimcliBinary,
f.SimcliHome, name)
ExecuteWrite(f.T, AddFlags(cmd, append(append(flags, "-y"), "-f")))
}
// KeysAdd is simcli keys add
func (f *Fixtures) KeysAdd(name string, flags ...string) {
cmd := fmt.Sprintf("%s keys add --keyring-backend=test --home=%s %s", f.SimcliBinary,
f.SimcliHome, name)
ExecuteWriteCheckErr(f.T, AddFlags(cmd, flags))
}
// KeysAddRecover prepares simcli keys add --recover
func (f *Fixtures) KeysAddRecover(name, mnemonic string, flags ...string) (exitSuccess bool, stdout, stderr string) {
cmd := fmt.Sprintf("%s keys add --keyring-backend=test --home=%s --recover %s",
f.SimcliBinary, f.SimcliHome, name)
return ExecuteWriteRetStdStreams(f.T, AddFlags(cmd, flags), mnemonic)
}
// KeysAddRecoverHDPath prepares simcli keys add --recover --account --index
func (f *Fixtures) KeysAddRecoverHDPath(name, mnemonic string, account uint32, index uint32, flags ...string) {
cmd := fmt.Sprintf("%s keys add --keyring-backend=test --home=%s --recover %s --account %d"+
" --index %d", f.SimcliBinary, f.SimcliHome, name, account, index)
ExecuteWriteCheckErr(f.T, AddFlags(cmd, flags), mnemonic)
}
// KeysShow is simcli keys show
func (f *Fixtures) KeysShow(name string, flags ...string) keyring.KeyOutput {
cmd := fmt.Sprintf("%s keys show --keyring-backend=test --home=%s %s", f.SimcliBinary,
f.SimcliHome, name)
out, _ := tests.ExecuteT(f.T, AddFlags(cmd, flags), "")
var ko keyring.KeyOutput
err := clientkeys.UnmarshalJSON([]byte(out), &ko)
require.NoError(f.T, err)
return ko
}
// KeyAddress returns the SDK account address from the key
func (f *Fixtures) KeyAddress(name string) sdk.AccAddress {
ko := f.KeysShow(name)
accAddr, err := sdk.AccAddressFromBech32(ko.Address)
require.NoError(f.T, err)
return accAddr
}
//___________________________________________________________________________________
// simcli config
// CLIConfig is simcli config
func (f *Fixtures) CLIConfig(key, value string, flags ...string) {
cmd := fmt.Sprintf("%s config --home=%s %s %s", f.SimcliBinary, f.SimcliHome, key, value)
ExecuteWriteCheckErr(f.T, AddFlags(cmd, flags))
}
// TxBroadcast is gaiacli tx broadcast
func (f *Fixtures) TxBroadcast(fileName string, flags ...string) (bool, string, string) {
cmd := fmt.Sprintf("%s tx broadcast %v %v", f.SimcliBinary, f.Flags(), fileName)
return ExecuteWriteRetStdStreams(f.T, AddFlags(cmd, flags), clientkeys.DefaultKeyPass)
}
// TxEncode is gaiacli tx encode
func (f *Fixtures) TxEncode(fileName string, flags ...string) (bool, string, string) {
cmd := fmt.Sprintf("%s tx encode %v %v", f.SimcliBinary, f.Flags(), fileName)
return ExecuteWriteRetStdStreams(f.T, AddFlags(cmd, flags), clientkeys.DefaultKeyPass)
}
//utils
func AddFlags(cmd string, flags []string) string {
for _, f := range flags {
cmd += " " + f
}
return strings.TrimSpace(cmd)
}
func UnmarshalStdTx(t *testing.T, c *codec.Codec, s string) (stdTx auth.StdTx) {
require.Nil(t, c.UnmarshalJSON([]byte(s), &stdTx))
return
}
+70
View File
@@ -0,0 +1,70 @@
package helpers
import (
"fmt"
"os"
"testing"
"time"
"github.com/stretchr/testify/require"
)
// InitFixtures is called at the beginning of a test and initializes a chain
// with 1 validator.
func InitFixtures(t *testing.T) (f *Fixtures) {
f = NewFixtures(t)
// reset test state
f.UnsafeResetAll()
f.CLIConfig("keyring-backend", "test")
// ensure keystore has foo and bar keys
f.KeysDelete(KeyFoo)
f.KeysDelete(KeyBar)
f.KeysDelete(KeyBar)
f.KeysDelete(KeyFooBarBaz)
f.KeysAdd(KeyFoo)
f.KeysAdd(KeyBar)
f.KeysAdd(KeyBaz)
f.KeysAdd(KeyVesting)
f.KeysAdd(KeyFooBarBaz, "--multisig-threshold=2", fmt.Sprintf(
"--multisig=%s,%s,%s", KeyFoo, KeyBar, KeyBaz))
// ensure that CLI output is in JSON format
f.CLIConfig("output", "json")
// NOTE: SDInit sets the ChainID
f.SDInit(KeyFoo)
f.CLIConfig("chain-id", f.ChainID)
f.CLIConfig("broadcast-mode", "block")
f.CLIConfig("trust-node", "true")
// start an account with tokens
f.AddGenesisAccount(f.KeyAddress(KeyFoo), startCoins)
f.AddGenesisAccount(
f.KeyAddress(KeyVesting), startCoins,
fmt.Sprintf("--vesting-amount=%s", vestingCoins),
fmt.Sprintf("--vesting-start-time=%d", time.Now().UTC().UnixNano()),
fmt.Sprintf("--vesting-end-time=%d", time.Now().Add(60*time.Second).UTC().UnixNano()),
)
f.GenTx(KeyFoo)
f.CollectGenTxs()
return f
}
// Cleanup is meant to be run at the end of a test to clean up an remaining test state
func (f *Fixtures) Cleanup(dirs ...string) {
clean := append(dirs, f.RootDir)
for _, d := range clean {
require.NoError(f.T, os.RemoveAll(d))
}
}
// Flags returns the flags necessary for making most CLI calls
func (f *Fixtures) Flags() string {
return fmt.Sprintf("--home=%s --node=%s", f.SimcliHome, f.RPCAddr)
}
+3
View File
@@ -0,0 +1,3 @@
package tests
// package tests runs integration tests which make use of CLI commands.
+39
View File
@@ -0,0 +1,39 @@
// +build cli_test
package tests
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/tests/cli/helpers"
)
func TestCLIKeysAddMultisig(t *testing.T) {
t.Parallel()
f := helpers.InitFixtures(t)
// key names order does not matter
f.KeysAdd("msig1", "--multisig-threshold=2",
fmt.Sprintf("--multisig=%s,%s", helpers.KeyBar, helpers.KeyBaz))
ke1Address1 := f.KeysShow("msig1").Address
f.KeysDelete("msig1")
f.KeysAdd("msig2", "--multisig-threshold=2",
fmt.Sprintf("--multisig=%s,%s", helpers.KeyBaz, helpers.KeyBar))
require.Equal(t, ke1Address1, f.KeysShow("msig2").Address)
f.KeysDelete("msig2")
f.KeysAdd("msig3", "--multisig-threshold=2",
fmt.Sprintf("--multisig=%s,%s", helpers.KeyBar, helpers.KeyBaz),
"--nosort")
f.KeysAdd("msig4", "--multisig-threshold=2",
fmt.Sprintf("--multisig=%s,%s", helpers.KeyBaz, helpers.KeyBar),
"--nosort")
require.NotEqual(t, f.KeysShow("msig3").Address, f.KeysShow("msig4").Address)
// Cleanup testing directories
f.Cleanup()
}