mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 00:05:18 +00:00
add gaia cli tests
This commit is contained in:
parent
83110d028e
commit
3cb63349b2
51
cli_test/README.md
Normal file
51
cli_test/README.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Gaia CLI Integration tests
|
||||||
|
|
||||||
|
The gaia cli integration tests live in this folder. You can run the full suite by running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ go test -v -p 4 ./cmd/gaia/cli_test/...
|
||||||
|
# OR!
|
||||||
|
$ make test_cli
|
||||||
|
```
|
||||||
|
> NOTE: While the full suite runs in parallel, some of the tests can take up to a minute to complete
|
||||||
|
|
||||||
|
### Test Structure
|
||||||
|
|
||||||
|
This integration suite [uses a thin wrapper](https://godoc.org/github.com/cosmos/cosmos-sdk/tests) over the [`os/exec`](https://golang.org/pkg/os/exec/) package. This allows the integration test to run against built binaries (both `gaiad` and `gaiacli` are used) while being written in golang. This allows tests to take advantage of the various golang code we have for operations like marshal/unmarshal, crypto, etc...
|
||||||
|
|
||||||
|
> NOTE: The tests will use whatever `gaiad` or `gaiacli` binaries are available in your `$PATH`. You can check which binary will be run by the suite by running `which gaiad` or `which gaiacli`. If you have your `$GOPATH` properly setup they should be in `$GOPATH/bin/gaia*`. This will ensure that your test uses the latest binary you have built
|
||||||
|
|
||||||
|
Tests generally follow this structure:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func TestMyNewCommand(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
f := InitFixtures(t)
|
||||||
|
|
||||||
|
// start gaiad server
|
||||||
|
proc := f.GDStart()
|
||||||
|
defer proc.Stop(false)
|
||||||
|
|
||||||
|
// Your test code goes here...
|
||||||
|
|
||||||
|
f.Cleanup()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This boilerplate above:
|
||||||
|
- Ensures the tests run in parallel. Because the tests are calling out to `os/exec` for many operations these tests can take a long time to run.
|
||||||
|
- Creates `.gaiad` and `.gaiacli` folders in a new temp folder.
|
||||||
|
- Uses `gaiacli` to create 2 accounts for use in testing: `foo` and `bar`
|
||||||
|
- Creates a genesis file with coins (`1000footoken,1000feetoken,150stake`) controlled by the `foo` key
|
||||||
|
- Generates an initial bonding transaction (`gentx`) to make the `foo` key a validator at genesis
|
||||||
|
- Starts `gaiad` and stops it once the test exits
|
||||||
|
- Cleans up test state on a successful run
|
||||||
|
|
||||||
|
### Notes when adding/running tests
|
||||||
|
|
||||||
|
- Because the tests run against a built binary, you should make sure you build every time the code changes and you want to test again, otherwise you will be testing against an older version. If you are adding new tests this can easily lead to confusing test results.
|
||||||
|
- The [`test_helpers.go`](./test_helpers.go) file is organized according to the format of `gaiacli` and `gaiad` commands. There are comments with section headers describing the different areas. Helper functions to call CLI functionality are generally named after the command (e.g. `gaiacli query staking validator` would be `QueryStakingValidator`). Try to keep functions grouped by their position in the command tree.
|
||||||
|
- Test state that is needed by `tx` and `query` commands (`home`, `chain_id`, etc...) is stored on the `Fixtures` object. This makes constructing your new tests almost trivial.
|
||||||
|
- Sometimes if you exit a test early there can be still running `gaiad` and `gaiacli` processes that will interrupt subsequent runs. Still running `gaiacli` processes will block access to the keybase while still running `gaiad` processes will block ports and prevent new tests from spinning up. You can ensure new tests spin up clean by running `pkill -9 gaiad && pkill -9 gaiacli` before each test run.
|
||||||
|
- Most `query` and `tx` commands take a variadic `flags` argument. This pattern allows for the creation of a general function which is easily modified by adding flags. See the `TxSend` function and its use for a good example.
|
||||||
|
- `Tx*` functions follow a general pattern and return `(success bool, stdout string, stderr string)`. This allows for easy testing of multiple different flag configurations. See `TestGaiaCLICreateValidator` or `TestGaiaCLISubmitProposal` for a good example of the pattern.
|
1093
cli_test/cli_test.go
Normal file
1093
cli_test/cli_test.go
Normal file
File diff suppressed because it is too large
Load Diff
3
cli_test/doc.go
Normal file
3
cli_test/doc.go
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package clitest
|
||||||
|
|
||||||
|
// package clitest runs integration tests which make use of CLI commands.
|
685
cli_test/test_helpers.go
Normal file
685
cli_test/test_helpers.go
Normal file
@ -0,0 +1,685 @@
|
|||||||
|
package clitest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
cmn "github.com/tendermint/tendermint/libs/common"
|
||||||
|
|
||||||
|
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||||
|
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||||
|
appInit "github.com/cosmos/cosmos-sdk/cmd/gaia/init"
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||||
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
|
"github.com/cosmos/cosmos-sdk/tests"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
denom = "stake"
|
||||||
|
keyFoo = "foo"
|
||||||
|
keyBar = "bar"
|
||||||
|
fooDenom = "footoken"
|
||||||
|
feeDenom = "feetoken"
|
||||||
|
fee2Denom = "fee2token"
|
||||||
|
keyBaz = "baz"
|
||||||
|
keyVesting = "vesting"
|
||||||
|
keyFooBarBaz = "foobarbaz"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
startCoins = sdk.Coins{
|
||||||
|
sdk.NewCoin(feeDenom, sdk.TokensFromTendermintPower(1000000)),
|
||||||
|
sdk.NewCoin(fee2Denom, sdk.TokensFromTendermintPower(1000000)),
|
||||||
|
sdk.NewCoin(fooDenom, sdk.TokensFromTendermintPower(1000)),
|
||||||
|
sdk.NewCoin(denom, sdk.TokensFromTendermintPower(150)),
|
||||||
|
}
|
||||||
|
|
||||||
|
vestingCoins = sdk.Coins{
|
||||||
|
sdk.NewCoin(feeDenom, sdk.TokensFromTendermintPower(500000)),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// Fixtures
|
||||||
|
|
||||||
|
// Fixtures is used to setup the testing environment
|
||||||
|
type Fixtures struct {
|
||||||
|
ChainID string
|
||||||
|
RPCAddr string
|
||||||
|
Port string
|
||||||
|
GDHome string
|
||||||
|
GCLIHome string
|
||||||
|
P2PAddr string
|
||||||
|
T *testing.T
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFixtures creates a new instance of Fixtures with many vars set
|
||||||
|
func NewFixtures(t *testing.T) *Fixtures {
|
||||||
|
tmpDir, err := ioutil.TempDir("", "gaia_integration_"+t.Name()+"_")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
servAddr, port, err := server.FreeTCPAddr()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
p2pAddr, _, err := server.FreeTCPAddr()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return &Fixtures{
|
||||||
|
T: t,
|
||||||
|
GDHome: filepath.Join(tmpDir, ".gaiad"),
|
||||||
|
GCLIHome: filepath.Join(tmpDir, ".gaiacli"),
|
||||||
|
RPCAddr: servAddr,
|
||||||
|
P2PAddr: p2pAddr,
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenesisFile returns the path of the genesis file
|
||||||
|
func (f Fixtures) GenesisFile() string {
|
||||||
|
return filepath.Join(f.GDHome, "config", "genesis.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenesisFile returns the application's genesis state
|
||||||
|
func (f Fixtures) GenesisState() app.GenesisState {
|
||||||
|
cdc := codec.New()
|
||||||
|
genDoc, err := appInit.LoadGenesisDoc(cdc, f.GenesisFile())
|
||||||
|
require.NoError(f.T, err)
|
||||||
|
|
||||||
|
var appState app.GenesisState
|
||||||
|
require.NoError(f.T, cdc.UnmarshalJSON(genDoc.AppState, &appState))
|
||||||
|
return appState
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
|
||||||
|
// 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: GDInit sets the ChainID
|
||||||
|
f.GDInit(keyFoo)
|
||||||
|
|
||||||
|
f.CLIConfig("chain-id", f.ChainID)
|
||||||
|
f.CLIConfig("broadcast-mode", "block")
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.GDHome, f.GCLIHome)
|
||||||
|
for _, d := range clean {
|
||||||
|
err := os.RemoveAll(d)
|
||||||
|
require.NoError(f.T, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flags returns the flags necessary for making most CLI calls
|
||||||
|
func (f *Fixtures) Flags() string {
|
||||||
|
return fmt.Sprintf("--home=%s --node=%s", f.GCLIHome, f.RPCAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// gaiad
|
||||||
|
|
||||||
|
// UnsafeResetAll is gaiad unsafe-reset-all
|
||||||
|
func (f *Fixtures) UnsafeResetAll(flags ...string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiad --home=%s unsafe-reset-all", f.GDHome)
|
||||||
|
executeWrite(f.T, addFlags(cmd, flags))
|
||||||
|
err := os.RemoveAll(filepath.Join(f.GDHome, "config", "gentx"))
|
||||||
|
require.NoError(f.T, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GDInit is gaiad init
|
||||||
|
// NOTE: GDInit sets the ChainID for the Fixtures instance
|
||||||
|
func (f *Fixtures) GDInit(moniker string, flags ...string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiad init -o --home=%s %s", f.GDHome, moniker)
|
||||||
|
_, stderr := tests.ExecuteT(f.T, addFlags(cmd, flags), app.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 gaiad add-genesis-account
|
||||||
|
func (f *Fixtures) AddGenesisAccount(address sdk.AccAddress, coins sdk.Coins, flags ...string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiad add-genesis-account %s %s --home=%s", address, coins, f.GDHome)
|
||||||
|
executeWriteCheckErr(f.T, addFlags(cmd, flags))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenTx is gaiad gentx
|
||||||
|
func (f *Fixtures) GenTx(name string, flags ...string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiad gentx --name=%s --home=%s --home-client=%s", name, f.GDHome, f.GCLIHome)
|
||||||
|
executeWriteCheckErr(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CollectGenTxs is gaiad collect-gentxs
|
||||||
|
func (f *Fixtures) CollectGenTxs(flags ...string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiad collect-gentxs --home=%s", f.GDHome)
|
||||||
|
executeWriteCheckErr(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GDStart runs gaiad start with the appropriate flags and returns a process
|
||||||
|
func (f *Fixtures) GDStart(flags ...string) *tests.Process {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiad start --home=%s --rpc.laddr=%v --p2p.laddr=%v", f.GDHome, f.RPCAddr, f.P2PAddr)
|
||||||
|
proc := tests.GoExecuteTWithStdout(f.T, addFlags(cmd, flags))
|
||||||
|
tests.WaitForTMStart(f.Port)
|
||||||
|
tests.WaitForNextNBlocksTM(1, f.Port)
|
||||||
|
return proc
|
||||||
|
}
|
||||||
|
|
||||||
|
// GDTendermint returns the results of gaiad tendermint [query]
|
||||||
|
func (f *Fixtures) GDTendermint(query string) string {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiad tendermint %s --home=%s", query, f.GDHome)
|
||||||
|
success, stdout, stderr := executeWriteRetStdStreams(f.T, cmd)
|
||||||
|
require.Empty(f.T, stderr)
|
||||||
|
require.True(f.T, success)
|
||||||
|
return strings.TrimSpace(stdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateGenesis runs gaiad validate-genesis
|
||||||
|
func (f *Fixtures) ValidateGenesis() {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiad validate-genesis --home=%s", f.GDHome)
|
||||||
|
executeWriteCheckErr(f.T, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// gaiacli keys
|
||||||
|
|
||||||
|
// KeysDelete is gaiacli keys delete
|
||||||
|
func (f *Fixtures) KeysDelete(name string, flags ...string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli keys delete --home=%s %s", f.GCLIHome, name)
|
||||||
|
executeWrite(f.T, addFlags(cmd, append(append(flags, "-y"), "-f")))
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeysAdd is gaiacli keys add
|
||||||
|
func (f *Fixtures) KeysAdd(name string, flags ...string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli keys add --home=%s %s", f.GCLIHome, name)
|
||||||
|
executeWriteCheckErr(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeysAddRecover prepares gaiacli keys add --recover
|
||||||
|
func (f *Fixtures) KeysAddRecover(name, mnemonic string, flags ...string) (exitSuccess bool, stdout, stderr string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli keys add --home=%s --recover %s", f.GCLIHome, name)
|
||||||
|
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), app.DefaultKeyPass, mnemonic)
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeysAddRecoverHDPath prepares gaiacli keys add --recover --account --index
|
||||||
|
func (f *Fixtures) KeysAddRecoverHDPath(name, mnemonic string, account uint32, index uint32, flags ...string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli keys add --home=%s --recover %s --account %d --index %d", f.GCLIHome, name, account, index)
|
||||||
|
executeWriteCheckErr(f.T, addFlags(cmd, flags), app.DefaultKeyPass, mnemonic)
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeysShow is gaiacli keys show
|
||||||
|
func (f *Fixtures) KeysShow(name string, flags ...string) keys.KeyOutput {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli keys show --home=%s %s", f.GCLIHome, name)
|
||||||
|
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
var ko keys.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
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// gaiacli config
|
||||||
|
|
||||||
|
// CLIConfig is gaiacli config
|
||||||
|
func (f *Fixtures) CLIConfig(key, value string, flags ...string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli config --home=%s %s %s", f.GCLIHome, key, value)
|
||||||
|
executeWriteCheckErr(f.T, addFlags(cmd, flags))
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// gaiacli tx send/sign/broadcast
|
||||||
|
|
||||||
|
// TxSend is gaiacli tx send
|
||||||
|
func (f *Fixtures) TxSend(from string, to sdk.AccAddress, amount sdk.Coin, flags ...string) (bool, string, string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli tx send %s %s %v --from=%s", to, amount, f.Flags(), from)
|
||||||
|
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fixtures) txSendWithConfirm(
|
||||||
|
from string, to sdk.AccAddress, amount sdk.Coin, confirm string, flags ...string,
|
||||||
|
) (bool, string, string) {
|
||||||
|
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli tx send %s %s %v --from=%s", to, amount, f.Flags(), from)
|
||||||
|
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), confirm, app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxSign is gaiacli tx sign
|
||||||
|
func (f *Fixtures) TxSign(signer, fileName string, flags ...string) (bool, string, string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli tx sign %v --from=%s %v", f.Flags(), signer, fileName)
|
||||||
|
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxBroadcast is gaiacli tx broadcast
|
||||||
|
func (f *Fixtures) TxBroadcast(fileName string, flags ...string) (bool, string, string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli tx broadcast %v %v", f.Flags(), fileName)
|
||||||
|
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxEncode is gaiacli tx encode
|
||||||
|
func (f *Fixtures) TxEncode(fileName string, flags ...string) (bool, string, string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli tx encode %v %v", f.Flags(), fileName)
|
||||||
|
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxMultisign is gaiacli tx multisign
|
||||||
|
func (f *Fixtures) TxMultisign(fileName, name string, signaturesFiles []string,
|
||||||
|
flags ...string) (bool, string, string) {
|
||||||
|
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli tx multisign %v %s %s %s", f.Flags(),
|
||||||
|
fileName, name, strings.Join(signaturesFiles, " "),
|
||||||
|
)
|
||||||
|
return executeWriteRetStdStreams(f.T, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// gaiacli tx staking
|
||||||
|
|
||||||
|
// TxStakingCreateValidator is gaiacli tx staking create-validator
|
||||||
|
func (f *Fixtures) TxStakingCreateValidator(from, consPubKey string, amount sdk.Coin, flags ...string) (bool, string, string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli tx staking create-validator %v --from=%s --pubkey=%s", f.Flags(), from, consPubKey)
|
||||||
|
cmd += fmt.Sprintf(" --amount=%v --moniker=%v --commission-rate=%v", amount, from, "0.05")
|
||||||
|
cmd += fmt.Sprintf(" --commission-max-rate=%v --commission-max-change-rate=%v", "0.20", "0.10")
|
||||||
|
cmd += fmt.Sprintf(" --min-self-delegation=%v", "1")
|
||||||
|
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxStakingUnbond is gaiacli tx staking unbond
|
||||||
|
func (f *Fixtures) TxStakingUnbond(from, shares string, validator sdk.ValAddress, flags ...string) bool {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli tx staking unbond %s %v --from=%s %v", validator, shares, from, f.Flags())
|
||||||
|
return executeWrite(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// gaiacli tx gov
|
||||||
|
|
||||||
|
// TxGovSubmitProposal is gaiacli tx gov submit-proposal
|
||||||
|
func (f *Fixtures) TxGovSubmitProposal(from, typ, title, description string, deposit sdk.Coin, flags ...string) (bool, string, string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli tx gov submit-proposal %v --from=%s --type=%s", f.Flags(), from, typ)
|
||||||
|
cmd += fmt.Sprintf(" --title=%s --description=%s --deposit=%s", title, description, deposit)
|
||||||
|
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxGovDeposit is gaiacli tx gov deposit
|
||||||
|
func (f *Fixtures) TxGovDeposit(proposalID int, from string, amount sdk.Coin, flags ...string) (bool, string, string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli tx gov deposit %d %s --from=%s %v", proposalID, amount, from, f.Flags())
|
||||||
|
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxGovVote is gaiacli tx gov vote
|
||||||
|
func (f *Fixtures) TxGovVote(proposalID int, option gov.VoteOption, from string, flags ...string) (bool, string, string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli tx gov vote %d %s --from=%s %v", proposalID, option, from, f.Flags())
|
||||||
|
return executeWriteRetStdStreams(f.T, addFlags(cmd, flags), app.DefaultKeyPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// gaiacli query account
|
||||||
|
|
||||||
|
// QueryAccount is gaiacli query account
|
||||||
|
func (f *Fixtures) QueryAccount(address sdk.AccAddress, flags ...string) auth.BaseAccount {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query account %s %v", 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
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// gaiacli query txs
|
||||||
|
|
||||||
|
// QueryTxs is gaiacli query txs
|
||||||
|
func (f *Fixtures) QueryTxs(page, limit int, tags ...string) []sdk.TxResponse {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query txs --page=%d --limit=%d --tags='%s' %v", page, limit, queryTags(tags), f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, cmd, "")
|
||||||
|
var txs []sdk.TxResponse
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &txs)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return txs
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryTxsInvalid query txs with wrong parameters and compare expected error
|
||||||
|
func (f *Fixtures) QueryTxsInvalid(expectedErr error, page, limit int, tags ...string) {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query txs --page=%d --limit=%d --tags='%s' %v", page, limit, queryTags(tags), f.Flags())
|
||||||
|
_, err := tests.ExecuteT(f.T, cmd, "")
|
||||||
|
require.EqualError(f.T, expectedErr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// gaiacli query staking
|
||||||
|
|
||||||
|
// QueryStakingValidator is gaiacli query staking validator
|
||||||
|
func (f *Fixtures) QueryStakingValidator(valAddr sdk.ValAddress, flags ...string) staking.Validator {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query staking validator %s %v", valAddr, f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
var validator staking.Validator
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &validator)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return validator
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryStakingUnbondingDelegationsFrom is gaiacli query staking unbonding-delegations-from
|
||||||
|
func (f *Fixtures) QueryStakingUnbondingDelegationsFrom(valAddr sdk.ValAddress, flags ...string) []staking.UnbondingDelegation {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query staking unbonding-delegations-from %s %v", valAddr, f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
var ubds []staking.UnbondingDelegation
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &ubds)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return ubds
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryStakingDelegationsTo is gaiacli query staking delegations-to
|
||||||
|
func (f *Fixtures) QueryStakingDelegationsTo(valAddr sdk.ValAddress, flags ...string) []staking.Delegation {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query staking delegations-to %s %v", valAddr, f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
var delegations []staking.Delegation
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &delegations)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return delegations
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryStakingPool is gaiacli query staking pool
|
||||||
|
func (f *Fixtures) QueryStakingPool(flags ...string) staking.Pool {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query staking pool %v", f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
var pool staking.Pool
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &pool)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return pool
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryStakingParameters is gaiacli query staking parameters
|
||||||
|
func (f *Fixtures) QueryStakingParameters(flags ...string) staking.Params {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query staking params %v", f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
var params staking.Params
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), ¶ms)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// gaiacli query gov
|
||||||
|
|
||||||
|
// QueryGovParamDeposit is gaiacli query gov param deposit
|
||||||
|
func (f *Fixtures) QueryGovParamDeposit() gov.DepositParams {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query gov param deposit %s", f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, cmd, "")
|
||||||
|
var depositParam gov.DepositParams
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &depositParam)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return depositParam
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGovParamVoting is gaiacli query gov param voting
|
||||||
|
func (f *Fixtures) QueryGovParamVoting() gov.VotingParams {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query gov param voting %s", f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, cmd, "")
|
||||||
|
var votingParam gov.VotingParams
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &votingParam)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return votingParam
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGovParamTallying is gaiacli query gov param tallying
|
||||||
|
func (f *Fixtures) QueryGovParamTallying() gov.TallyParams {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query gov param tallying %s", f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, cmd, "")
|
||||||
|
var tallyingParam gov.TallyParams
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &tallyingParam)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return tallyingParam
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGovProposals is gaiacli query gov proposals
|
||||||
|
func (f *Fixtures) QueryGovProposals(flags ...string) gov.Proposals {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query gov proposals %v", f.Flags())
|
||||||
|
stdout, stderr := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
if strings.Contains(stderr, "No matching proposals found") {
|
||||||
|
return gov.Proposals{}
|
||||||
|
}
|
||||||
|
require.Empty(f.T, stderr)
|
||||||
|
var out gov.Proposals
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(stdout), &out)
|
||||||
|
require.NoError(f.T, err)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGovProposal is gaiacli query gov proposal
|
||||||
|
func (f *Fixtures) QueryGovProposal(proposalID int, flags ...string) gov.Proposal {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query gov proposal %d %v", proposalID, f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
var proposal gov.Proposal
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &proposal)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return proposal
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGovVote is gaiacli query gov vote
|
||||||
|
func (f *Fixtures) QueryGovVote(proposalID int, voter sdk.AccAddress, flags ...string) gov.Vote {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query gov vote %d %s %v", proposalID, voter, f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
var vote gov.Vote
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &vote)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return vote
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGovVotes is gaiacli query gov votes
|
||||||
|
func (f *Fixtures) QueryGovVotes(proposalID int, flags ...string) []gov.Vote {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query gov votes %d %v", proposalID, f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
var votes []gov.Vote
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &votes)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return votes
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGovDeposit is gaiacli query gov deposit
|
||||||
|
func (f *Fixtures) QueryGovDeposit(proposalID int, depositor sdk.AccAddress, flags ...string) gov.Deposit {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query gov deposit %d %s %v", proposalID, depositor, f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
var deposit gov.Deposit
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &deposit)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return deposit
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryGovDeposits is gaiacli query gov deposits
|
||||||
|
func (f *Fixtures) QueryGovDeposits(propsalID int, flags ...string) []gov.Deposit {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query gov deposits %d %v", propsalID, f.Flags())
|
||||||
|
out, _ := tests.ExecuteT(f.T, addFlags(cmd, flags), "")
|
||||||
|
var deposits []gov.Deposit
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
err := cdc.UnmarshalJSON([]byte(out), &deposits)
|
||||||
|
require.NoError(f.T, err, "out %v\n, err %v", out, err)
|
||||||
|
return deposits
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// query slashing
|
||||||
|
|
||||||
|
// QuerySigningInfo returns the signing info for a validator
|
||||||
|
func (f *Fixtures) QuerySigningInfo(val string) slashing.ValidatorSigningInfo {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query slashing signing-info %s %s", val, f.Flags())
|
||||||
|
res, errStr := tests.ExecuteT(f.T, cmd, "")
|
||||||
|
require.Empty(f.T, errStr)
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
var sinfo slashing.ValidatorSigningInfo
|
||||||
|
err := cdc.UnmarshalJSON([]byte(res), &sinfo)
|
||||||
|
require.NoError(f.T, err)
|
||||||
|
return sinfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// QuerySlashingParams is gaiacli query slashing params
|
||||||
|
func (f *Fixtures) QuerySlashingParams() slashing.Params {
|
||||||
|
cmd := fmt.Sprintf("../../../build/gaiacli query slashing params %s", f.Flags())
|
||||||
|
res, errStr := tests.ExecuteT(f.T, cmd, "")
|
||||||
|
require.Empty(f.T, errStr)
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
var params slashing.Params
|
||||||
|
err := cdc.UnmarshalJSON([]byte(res), ¶ms)
|
||||||
|
require.NoError(f.T, err)
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// executors
|
||||||
|
|
||||||
|
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:", cmn.Green(string(stdout)))
|
||||||
|
}
|
||||||
|
if len(stderr) > 0 {
|
||||||
|
t.Log("Stderr:", cmn.Red(string(stderr)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for process to exit
|
||||||
|
proc.Wait()
|
||||||
|
|
||||||
|
// Return succes, stdout, stderr
|
||||||
|
return proc.ExitState.Success(), string(stdout), string(stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
// utils
|
||||||
|
|
||||||
|
func addFlags(cmd string, flags []string) string {
|
||||||
|
for _, f := range flags {
|
||||||
|
cmd += " " + f
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryTags(tags []string) (out string) {
|
||||||
|
for _, tag := range tags {
|
||||||
|
out += tag + "&"
|
||||||
|
}
|
||||||
|
return strings.TrimSuffix(out, "&")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the given string to a new temporary file
|
||||||
|
func WriteToNewTempFile(t *testing.T, s string) *os.File {
|
||||||
|
fp, err := ioutil.TempFile(os.TempDir(), "cosmos_cli_test_")
|
||||||
|
require.Nil(t, err)
|
||||||
|
_, err = fp.WriteString(s)
|
||||||
|
require.Nil(t, err)
|
||||||
|
return fp
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalStdTx(t *testing.T, stdTx auth.StdTx) []byte {
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
bz, err := cdc.MarshalBinaryBare(stdTx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return bz
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalStdTx(t *testing.T, s string) (stdTx auth.StdTx) {
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
require.Nil(t, cdc.UnmarshalJSON([]byte(s), &stdTx))
|
||||||
|
return
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user