Make system tests extendable for other app binaries
Please enter the commit message for your changes. Lines starting
This commit is contained in:
@@ -40,33 +40,52 @@ type WasmdCli struct {
|
||||
assertErrorFn RunErrorAssert
|
||||
awaitNextBlock awaitNextBlock
|
||||
expTXCommitted bool
|
||||
execBinary string
|
||||
}
|
||||
|
||||
// NewWasmdCLI constructor
|
||||
func NewWasmdCLI(t *testing.T, sut *SystemUnderTest, verbose bool) *WasmdCli {
|
||||
return NewWasmdCLIx(t, sut.rpcAddr, sut.chainID, sut.AwaitNextBlock, filepath.Join(workDir, sut.outputDir), "1"+sdk.DefaultBondDenom, verbose)
|
||||
return NewWasmdCLIx(
|
||||
t,
|
||||
sut.execBinary,
|
||||
sut.rpcAddr,
|
||||
sut.chainID,
|
||||
sut.AwaitNextBlock,
|
||||
filepath.Join(workDir, sut.outputDir),
|
||||
"1"+sdk.DefaultBondDenom,
|
||||
verbose,
|
||||
assert.NoError,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
// NewWasmdCLIx extended constructor
|
||||
func NewWasmdCLIx(
|
||||
t *testing.T,
|
||||
execBinary string,
|
||||
nodeAddress string,
|
||||
chainID string,
|
||||
awaiter awaitNextBlock,
|
||||
homeDir string,
|
||||
fees string,
|
||||
debug bool,
|
||||
assertErrorFn RunErrorAssert,
|
||||
expTXCommitted bool,
|
||||
) *WasmdCli {
|
||||
if strings.TrimSpace(execBinary) == "" {
|
||||
panic("executable binary name must not be empty")
|
||||
}
|
||||
return &WasmdCli{
|
||||
t: t,
|
||||
execBinary: execBinary,
|
||||
nodeAddress: nodeAddress,
|
||||
chainID: chainID,
|
||||
homeDir: homeDir,
|
||||
Debug: debug,
|
||||
assertErrorFn: assert.NoError,
|
||||
awaitNextBlock: awaiter,
|
||||
fees: fees,
|
||||
expTXCommitted: true,
|
||||
assertErrorFn: assertErrorFn,
|
||||
expTXCommitted: expTXCommitted,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,31 +98,48 @@ func (c WasmdCli) WithRunErrorsIgnored() WasmdCli {
|
||||
|
||||
// WithRunErrorMatcher assert function to ensure run command error value
|
||||
func (c WasmdCli) WithRunErrorMatcher(f RunErrorAssert) WasmdCli {
|
||||
return WasmdCli{
|
||||
t: c.t,
|
||||
nodeAddress: c.nodeAddress,
|
||||
chainID: c.chainID,
|
||||
homeDir: c.homeDir,
|
||||
Debug: c.Debug,
|
||||
assertErrorFn: f,
|
||||
awaitNextBlock: c.awaitNextBlock,
|
||||
fees: c.fees,
|
||||
expTXCommitted: c.expTXCommitted,
|
||||
}
|
||||
return *NewWasmdCLIx(
|
||||
c.t,
|
||||
c.execBinary,
|
||||
c.nodeAddress,
|
||||
c.chainID,
|
||||
c.awaitNextBlock,
|
||||
c.homeDir,
|
||||
c.fees,
|
||||
c.Debug,
|
||||
f,
|
||||
c.expTXCommitted,
|
||||
)
|
||||
}
|
||||
|
||||
func (c WasmdCli) WithNodeAddress(addr string) WasmdCli {
|
||||
return WasmdCli{
|
||||
t: c.t,
|
||||
nodeAddress: addr,
|
||||
chainID: c.chainID,
|
||||
homeDir: c.homeDir,
|
||||
Debug: c.Debug,
|
||||
assertErrorFn: c.assertErrorFn,
|
||||
awaitNextBlock: c.awaitNextBlock,
|
||||
fees: c.fees,
|
||||
expTXCommitted: c.expTXCommitted,
|
||||
}
|
||||
func (c WasmdCli) WithNodeAddress(nodeAddr string) WasmdCli {
|
||||
return *NewWasmdCLIx(
|
||||
c.t,
|
||||
c.execBinary,
|
||||
nodeAddr,
|
||||
c.chainID,
|
||||
c.awaitNextBlock,
|
||||
c.homeDir,
|
||||
c.fees,
|
||||
c.Debug,
|
||||
c.assertErrorFn,
|
||||
c.expTXCommitted,
|
||||
)
|
||||
}
|
||||
|
||||
func (c WasmdCli) WithAssertTXUncommitted() WasmdCli {
|
||||
return *NewWasmdCLIx(
|
||||
c.t,
|
||||
c.execBinary,
|
||||
c.nodeAddress,
|
||||
c.chainID,
|
||||
c.awaitNextBlock,
|
||||
c.homeDir,
|
||||
c.fees,
|
||||
c.Debug,
|
||||
c.assertErrorFn,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
// CustomCommand main entry for executing wasmd cli commands.
|
||||
@@ -160,9 +196,8 @@ func (c WasmdCli) CustomQuery(args ...string) string {
|
||||
|
||||
// execute shell command
|
||||
func (c WasmdCli) run(args []string) (output string, ok bool) {
|
||||
// todo assert error???
|
||||
if c.Debug {
|
||||
c.t.Logf("+++ running `wasmd %s`", strings.Join(args, " "))
|
||||
c.t.Logf("+++ running `%s %s`", c.execBinary, strings.Join(args, " "))
|
||||
}
|
||||
gotOut, gotErr := func() (out []byte, err error) {
|
||||
defer func() {
|
||||
|
||||
@@ -94,18 +94,7 @@ func TestVestingAccounts(t *testing.T) {
|
||||
assert.Equal(t, myStartTimestamp, accounts[0].Get("start_time").Int())
|
||||
|
||||
// check accounts have some balances
|
||||
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(100000000))), getGenesisBalance([]byte(raw), vest1Addr))
|
||||
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(100000001))), getGenesisBalance([]byte(raw), vest2Addr))
|
||||
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(200000002))), getGenesisBalance([]byte(raw), vest3Addr))
|
||||
}
|
||||
|
||||
func getGenesisBalance(raw []byte, addr string) sdk.Coins {
|
||||
var r []sdk.Coin
|
||||
balances := gjson.GetBytes(raw, fmt.Sprintf(`app_state.bank.balances.#[address==%q]#.coins`, addr)).Array()
|
||||
for _, coins := range balances {
|
||||
for _, coin := range coins.Array() {
|
||||
r = append(r, sdk.NewCoin(coin.Get("denom").String(), sdk.NewInt(coin.Get("amount").Int())))
|
||||
}
|
||||
}
|
||||
return r
|
||||
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(100000000))), GetGenesisBalance([]byte(raw), vest1Addr))
|
||||
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(100000001))), GetGenesisBalance([]byte(raw), vest2Addr))
|
||||
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(200000002))), GetGenesisBalance([]byte(raw), vest3Addr))
|
||||
}
|
||||
|
||||
@@ -41,8 +41,10 @@ func TestRecursiveMsgsExternalTrigger(t *testing.T) {
|
||||
fees = calcMinFeeRequired(t, gas)
|
||||
}
|
||||
for _, n := range sut.AllNodes(t) {
|
||||
clix := cli.WithRunErrorMatcher(spec.expErrMatcher).WithNodeAddress(n.RPCAddr())
|
||||
clix.expTXCommitted = false
|
||||
clix := cli.
|
||||
WithRunErrorMatcher(spec.expErrMatcher).
|
||||
WithNodeAddress(n.RPCAddr()).
|
||||
WithAssertTXUncommitted()
|
||||
clix.WasmExecute(contractAddr, execMsg, defaultSrcAddr, "--gas="+gas, "--broadcast-mode=sync", "--fees="+fees)
|
||||
}
|
||||
sut.AwaitNextBlock(t)
|
||||
|
||||
33
tests/system/genesis_io.go
Normal file
33
tests/system/genesis_io.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/tidwall/sjson"
|
||||
)
|
||||
|
||||
// SetConsensusMaxGas max gas that can be consumed in a block
|
||||
func SetConsensusMaxGas(t *testing.T, max int) GenesisMutator {
|
||||
return func(genesis []byte) []byte {
|
||||
t.Helper()
|
||||
state, err := sjson.SetRawBytes(genesis, "consensus_params.block.max_gas", []byte(fmt.Sprintf(`"%d"`, max)))
|
||||
require.NoError(t, err)
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
// GetGenesisBalance return the balance amount for an address from the given genesis json
|
||||
func GetGenesisBalance(rawGenesis []byte, addr string) sdk.Coins {
|
||||
var r []sdk.Coin
|
||||
balances := gjson.GetBytes(rawGenesis, fmt.Sprintf(`app_state.bank.balances.#[address==%q]#.coins`, addr)).Array()
|
||||
for _, coins := range balances {
|
||||
for _, coin := range coins.Array() {
|
||||
r = append(r, sdk.NewCoin(coin.Get("denom").String(), sdk.NewInt(coin.Get("amount").Int())))
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tidwall/sjson"
|
||||
)
|
||||
|
||||
// SetConsensusMaxGas max gas that can be consumed in a block
|
||||
func SetConsensusMaxGas(t *testing.T, max int) GenesisMutator {
|
||||
return func(genesis []byte) []byte {
|
||||
t.Helper()
|
||||
state, err := sjson.SetRawBytes(genesis, "consensus_params.block.max_gas", []byte(fmt.Sprintf(`"%d"`, max)))
|
||||
require.NoError(t, err)
|
||||
return state
|
||||
}
|
||||
}
|
||||
@@ -23,22 +23,13 @@ var (
|
||||
verbose bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
InitSDKConfig("wasm")
|
||||
}
|
||||
|
||||
func InitSDKConfig(bech32Prefix string) {
|
||||
config := sdk.GetConfig()
|
||||
config.SetBech32PrefixForAccount(bech32Prefix, bech32Prefix+sdk.PrefixPublic)
|
||||
config.SetBech32PrefixForValidator(bech32Prefix+sdk.PrefixValidator+sdk.PrefixOperator, bech32Prefix+sdk.PrefixValidator+sdk.PrefixOperator+sdk.PrefixPublic)
|
||||
config.SetBech32PrefixForConsensusNode(bech32Prefix+sdk.PrefixValidator+sdk.PrefixConsensus, bech32Prefix+sdk.PrefixValidator+sdk.PrefixConsensus+sdk.PrefixPublic)
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
rebuild := flag.Bool("rebuild", false, "rebuild artifacts")
|
||||
waitTime := flag.Duration("wait-time", defaultWaitTime, "time to wait for chain events")
|
||||
nodesCount := flag.Int("nodes-count", 4, "number of nodes in the cluster")
|
||||
blockTime := flag.Duration("block-time", 1000*time.Millisecond, "block creation time")
|
||||
execBinary := flag.String("binary", "wasmd", "executable binary for server/ client side")
|
||||
bech32Prefix := flag.String("bech32", "wasm", "bech32 prefix to be used with addresses")
|
||||
flag.BoolVar(&verbose, "verbose", false, "verbose output")
|
||||
flag.Parse()
|
||||
|
||||
@@ -53,8 +44,13 @@ func TestMain(m *testing.M) {
|
||||
if verbose {
|
||||
println("Work dir: ", workDir)
|
||||
}
|
||||
initSDKConfig(*bech32Prefix)
|
||||
|
||||
defaultWaitTime = *waitTime
|
||||
sut = NewSystemUnderTest(verbose, *nodesCount, *blockTime)
|
||||
if *execBinary == "" {
|
||||
panic("executable binary name must not be empty")
|
||||
}
|
||||
sut = NewSystemUnderTest(*execBinary, verbose, *nodesCount, *blockTime)
|
||||
if *rebuild {
|
||||
sut.BuildNewBinary()
|
||||
}
|
||||
@@ -98,6 +94,13 @@ func requireEnoughFileHandlers(nodesCount int) {
|
||||
return
|
||||
}
|
||||
|
||||
func initSDKConfig(bech32Prefix string) {
|
||||
config := sdk.GetConfig()
|
||||
config.SetBech32PrefixForAccount(bech32Prefix, bech32Prefix+sdk.PrefixPublic)
|
||||
config.SetBech32PrefixForValidator(bech32Prefix+sdk.PrefixValidator+sdk.PrefixOperator, bech32Prefix+sdk.PrefixValidator+sdk.PrefixOperator+sdk.PrefixPublic)
|
||||
config.SetBech32PrefixForConsensusNode(bech32Prefix+sdk.PrefixValidator+sdk.PrefixConsensus, bech32Prefix+sdk.PrefixValidator+sdk.PrefixConsensus+sdk.PrefixPublic)
|
||||
}
|
||||
|
||||
const (
|
||||
successFlag = `
|
||||
___ _ _ ___ ___ ___ ___ ___
|
||||
|
||||
@@ -33,6 +33,7 @@ var workDir string
|
||||
|
||||
// SystemUnderTest blockchain provisioning
|
||||
type SystemUnderTest struct {
|
||||
execBinary string
|
||||
blockListener *EventListener
|
||||
currentHeight int64
|
||||
chainID string
|
||||
@@ -51,9 +52,13 @@ type SystemUnderTest struct {
|
||||
dirty bool // requires full reset when marked dirty
|
||||
}
|
||||
|
||||
func NewSystemUnderTest(verbose bool, nodesCount int, blockTime time.Duration) *SystemUnderTest {
|
||||
func NewSystemUnderTest(execBinary string, verbose bool, nodesCount int, blockTime time.Duration) *SystemUnderTest {
|
||||
if execBinary == "" {
|
||||
panic("executable binary name must not be empty")
|
||||
}
|
||||
return &SystemUnderTest{
|
||||
chainID: "testing",
|
||||
execBinary: execBinary,
|
||||
outputDir: "./testnet",
|
||||
blockTime: blockTime,
|
||||
rpcAddr: "tcp://localhost:26657",
|
||||
@@ -84,9 +89,9 @@ func (s *SystemUnderTest) SetupChain() {
|
||||
"--starting-ip-address", "", // empty to use host systems
|
||||
"--single-host",
|
||||
}
|
||||
println("+++ wasmd " + strings.Join(args, " "))
|
||||
fmt.Printf("+++ %s %s", s.execBinary, strings.Join(args, " "))
|
||||
cmd := exec.Command( //nolint:gosec
|
||||
locateExecutable("wasmd"),
|
||||
locateExecutable(s.execBinary),
|
||||
args...,
|
||||
)
|
||||
cmd.Dir = workDir
|
||||
@@ -193,7 +198,7 @@ func appendToBuf(r io.Reader, b *ring.Ring, stop <-chan struct{}) {
|
||||
}
|
||||
text := scanner.Text()
|
||||
// filter out noise
|
||||
if strings.Contains(text, "module=rpc-server protocol=websocket") {
|
||||
if isLogNoise(text) {
|
||||
continue
|
||||
}
|
||||
b.Value = text
|
||||
@@ -201,6 +206,17 @@ func appendToBuf(r io.Reader, b *ring.Ring, stop <-chan struct{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func isLogNoise(text string) bool {
|
||||
for _, v := range []string{
|
||||
"\x1b[36mmodule=\x1b[0mrpc-server", // "module=rpc-server",
|
||||
} {
|
||||
if strings.Contains(text, v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// AwaitNodeUp ensures the node is running
|
||||
func (s *SystemUnderTest) AwaitNodeUp(t *testing.T, rpcAddr string) {
|
||||
t.Helper()
|
||||
@@ -249,7 +265,7 @@ func (s *SystemUnderTest) StopChain() {
|
||||
}
|
||||
s.cleanupFn = nil
|
||||
// send SIGTERM
|
||||
cmd := exec.Command(locateExecutable("pkill"), "-15", "wasmd") //nolint:gosec
|
||||
cmd := exec.Command(locateExecutable("pkill"), "-15", s.execBinary) //nolint:gosec
|
||||
cmd.Dir = workDir
|
||||
if _, err := cmd.CombinedOutput(); err != nil {
|
||||
s.Logf("failed to stop chain: %s\n", err)
|
||||
@@ -260,14 +276,14 @@ func (s *SystemUnderTest) StopChain() {
|
||||
select {
|
||||
case <-timeout:
|
||||
s.Log("killing nodes now")
|
||||
cmd = exec.Command(locateExecutable("pkill"), "-9", "wasmd") //nolint:gosec
|
||||
cmd = exec.Command(locateExecutable("pkill"), "-9", s.execBinary) //nolint:gosec
|
||||
cmd.Dir = workDir
|
||||
if _, err := cmd.CombinedOutput(); err != nil {
|
||||
s.Logf("failed to kill process: %s\n", err)
|
||||
}
|
||||
shutdown = true
|
||||
default:
|
||||
if err := exec.Command(locateExecutable("pgrep"), "wasmd").Run(); err != nil { //nolint:gosec
|
||||
if err := exec.Command(locateExecutable("pgrep"), s.execBinary).Run(); err != nil { //nolint:gosec
|
||||
shutdown = true
|
||||
}
|
||||
}
|
||||
@@ -290,7 +306,7 @@ func (s SystemUnderTest) PrintBuffer() {
|
||||
})
|
||||
}
|
||||
|
||||
// BuildNewBinary builds and installs new wasmd binary
|
||||
// BuildNewBinary builds and installs new executable binary
|
||||
func (s SystemUnderTest) BuildNewBinary() {
|
||||
s.Log("Install binaries\n")
|
||||
makePath := locateExecutable("make")
|
||||
@@ -431,7 +447,7 @@ func saveGenesis(home string, content []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForEachNodeExecAndWait runs the given wasmd commands for all cluster nodes synchronously
|
||||
// ForEachNodeExecAndWait runs the given app executable commands for all cluster nodes synchronously
|
||||
// The commands output is returned for each node.
|
||||
func (s *SystemUnderTest) ForEachNodeExecAndWait(t *testing.T, cmds ...[]string) [][]string {
|
||||
result := make([][]string, s.nodesCount)
|
||||
@@ -439,9 +455,9 @@ func (s *SystemUnderTest) ForEachNodeExecAndWait(t *testing.T, cmds ...[]string)
|
||||
result[i] = make([]string, len(cmds))
|
||||
for j, xargs := range cmds {
|
||||
xargs = append(xargs, "--home", home)
|
||||
s.Logf("Execute `wasmd %s`\n", strings.Join(xargs, " "))
|
||||
s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(xargs, " "))
|
||||
cmd := exec.Command( //nolint:gosec
|
||||
locateExecutable("wasmd"),
|
||||
locateExecutable(s.execBinary),
|
||||
xargs...,
|
||||
)
|
||||
cmd.Dir = workDir
|
||||
@@ -454,14 +470,14 @@ func (s *SystemUnderTest) ForEachNodeExecAndWait(t *testing.T, cmds ...[]string)
|
||||
return result
|
||||
}
|
||||
|
||||
// forEachNodesExecAsync runs the given wasmd command for all cluster nodes and returns without waiting
|
||||
// forEachNodesExecAsync runs the given app cli command for all cluster nodes and returns without waiting
|
||||
func (s *SystemUnderTest) forEachNodesExecAsync(t *testing.T, xargs ...string) []func() error {
|
||||
r := make([]func() error, s.nodesCount)
|
||||
s.withEachNodeHome(func(i int, home string) {
|
||||
args := append(xargs, "--home", home) //nolint:gocritic
|
||||
s.Logf("Execute `wasmd %s`\n", strings.Join(args, " "))
|
||||
s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(args, " "))
|
||||
cmd := exec.Command( //nolint:gosec
|
||||
locateExecutable("wasmd"),
|
||||
locateExecutable(s.execBinary),
|
||||
args...,
|
||||
)
|
||||
cmd.Dir = workDir
|
||||
@@ -480,7 +496,7 @@ func (s SystemUnderTest) withEachNodeHome(cb func(i int, home string)) {
|
||||
|
||||
// nodePath returns the path of the node within the work dir. not absolute
|
||||
func (s SystemUnderTest) nodePath(i int) string {
|
||||
return fmt.Sprintf("%s/node%d/wasmd", s.outputDir, i)
|
||||
return fmt.Sprintf("%s/node%d/%s", s.outputDir, i, s.execBinary)
|
||||
}
|
||||
|
||||
func (s SystemUnderTest) Log(msg string) {
|
||||
@@ -538,9 +554,9 @@ func (s *SystemUnderTest) AddFullnode(t *testing.T, beforeStart ...func(nodeNumb
|
||||
// prepare new node
|
||||
moniker := fmt.Sprintf("node%d", nodeNumber)
|
||||
args := []string{"init", moniker, "--home", nodePath, "--overwrite"}
|
||||
s.Logf("Execute `wasmd %s`\n", strings.Join(args, " "))
|
||||
s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(args, " "))
|
||||
cmd := exec.Command( //nolint:gosec
|
||||
locateExecutable("wasmd"),
|
||||
locateExecutable(s.execBinary),
|
||||
args...,
|
||||
)
|
||||
cmd.Dir = workDir
|
||||
@@ -575,9 +591,9 @@ func (s *SystemUnderTest) AddFullnode(t *testing.T, beforeStart ...func(nodeNumb
|
||||
"--log_level=info",
|
||||
"--home", nodePath,
|
||||
}
|
||||
s.Logf("Execute `wasmd %s`\n", strings.Join(args, " "))
|
||||
s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(args, " "))
|
||||
cmd = exec.Command( //nolint:gosec
|
||||
locateExecutable("wasmd"),
|
||||
locateExecutable(s.execBinary),
|
||||
args...,
|
||||
)
|
||||
cmd.Dir = workDir
|
||||
@@ -608,6 +624,9 @@ func (n Node) RPCAddr() string {
|
||||
|
||||
// locateExecutable looks up the binary on the OS path.
|
||||
func locateExecutable(file string) string {
|
||||
if strings.TrimSpace(file) == "" {
|
||||
panic("executable binary name must not be empty")
|
||||
}
|
||||
path, err := exec.LookPath(file)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("unexpected error %s", err.Error()))
|
||||
|
||||
Reference in New Issue
Block a user