testing

package
v0.0.0-...-3c4d084 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 12, 2023 License: Apache-2.0 Imports: 32 Imported by: 0

README

Testing

Test framework for system tests. Starts and interacts with a (multi node) blockchain in Go. Supports

  • CLI
  • Servers
  • Events
  • RPC

Uses:

  • testify
  • gjson
  • sjson Server and client side are executed on the host machine

Developer

Test strategy

System tests cover the full stack via cli and a running (multi node) network. They are more expensive (in terms of time/ cpu) to run compared to unit or integration tests. Therefore, we focus on the critical path and do not cover every condition.

Execute a single test
go test -tags system_test -count=1 -v ./testing --run TestSmokeTest  -verbose
  • Force a binary rebuild before running the test
go test -tags system_test -count=1 -v ./testing --run TestSmokeTest  -verbose -rebuild

Test cli parameters

  • -verbose verbose output
  • -rebuild - rebuild artifacts
  • -wait-time duration - time to wait for chain events (default 30s)
  • -nodes-count int - number of nodes in the cluster (default 4)

Port ranges

With n nodes:

  • 26657 - 26657+n - RPC
  • 1317 - 1317+n - API
  • 9090 - 9090+n - GRPC
  • 16656 - 16656+n - P2P

For example Node 3 listens on 26660 for RPC calls

Resources

Disclaimer

This was inspired by the amazing work of the e-money team on their system tests. Thank you!

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RequireTxFailure

func RequireTxFailure(t *testing.T, got string, containsMsgs ...string)

RequireTxFailure require the received response to contain any failure code and the passed msgsgs

func RequireTxSuccess

func RequireTxSuccess(t *testing.T, got string)

RequireTxSuccess require the received response to contain the success code

Types

type CleanupFn

type CleanupFn func()

type EventConsumer

type EventConsumer func(e ctypes.ResultEvent) (more bool)

func CaptureAllEventsConsumer

func CaptureAllEventsConsumer(t *testing.T, optMaxWaitTime ...time.Duration) (c EventConsumer, done func() []ctypes.ResultEvent)

CaptureAllEventsConsumer is an `EventConsumer` that captures all events until `done()` is called to stop or timeout happens. The consumer works async in the background and returns all the captured events when `done()` is called. This can be used to verify that certain events have happened. Example usage:

	c, done := CaptureAllEventsConsumer(t)
	query := `tm.event='Tx'`
	cleanupFn := l.Subscribe(query, c)
	t.Cleanup(cleanupFn)

 // do something in your test that create events

	assert.Len(t, done(), 1) // then verify your assumption

func CaptureSingleEventConsumer

func CaptureSingleEventConsumer() (EventConsumer, *ctypes.ResultEvent)

CaptureSingleEventConsumer consumes one event. No timeout

func TimeoutConsumer

func TimeoutConsumer(t *testing.T, maxWaitTime time.Duration, next EventConsumer) EventConsumer

TimeoutConsumer is an event consumer decorator with a max wait time. Panics when wait time exceeded without a result returned

type EventListener

type EventListener struct {
	// contains filtered or unexported fields
}

EventListener watches for events on the chain

func NewEventListener

func NewEventListener(t *testing.T, rpcAddr string) *EventListener

NewEventListener event listener

func (*EventListener) AwaitQuery

func (l *EventListener) AwaitQuery(query string, optMaxWaitTime ...time.Duration) *ctypes.ResultEvent

AwaitQuery blocks and waits for a single result or timeout. This can be used with `broadcast-mode=async`. For query syntax See https://docs.cosmos.network/master/core/events.html#subscribing-to-events

func (*EventListener) Subscribe

func (l *EventListener) Subscribe(query string, cb EventConsumer) func()

Subscribe to receive events for a topic. Does not block. For query syntax See https://docs.cosmos.network/master/core/events.html#subscribing-to-events

type FuryaCli

type FuryaCli struct {
	Debug bool
	// contains filtered or unexported fields
}

FuryaCli wraps the command line interface

func NewFuryaCli

func NewFuryaCli(t *testing.T, sut *SystemUnderTest, verbose bool) *FuryaCli

func NewFuryaCliX

func NewFuryaCliX(t *testing.T, nodeAddress string, chainID string, homeDir string, debug bool) *FuryaCli

func (FuryaCli) AddKey

func (c FuryaCli) AddKey(name string) string

AddKey add key to default keyring. Returns address

func (FuryaCli) CustomCommand

func (c FuryaCli) CustomCommand(args ...string) string

func (FuryaCli) CustomQuery

func (c FuryaCli) CustomQuery(args ...string) string

func (FuryaCli) Execute

func (c FuryaCli) Execute(contractAddr, msg, from string, args ...string) string

Execute send MsgExecute to a contract

func (FuryaCli) FundAddress

func (c FuryaCli) FundAddress(destAddr, amount string) string

FundAddress sends the token amount to the destination address

func (FuryaCli) GetDefaultKeyAddr

func (c FuryaCli) GetDefaultKeyAddr() string

GetDefaultKeyAddr returns the address of the default test key

func (FuryaCli) GetKeyAddr

func (c FuryaCli) GetKeyAddr(name string) string

GetKeyAddr returns address

func (FuryaCli) GetPoEContractAddress

func (c FuryaCli) GetPoEContractAddress(v string) string

GetPoEContractAddress query the PoE contract address

func (FuryaCli) GetTendermintValidatorSet

func (c FuryaCli) GetTendermintValidatorSet() rpc.ResultValidatorsOutput

func (FuryaCli) InstantiateWasm

func (c FuryaCli) InstantiateWasm(codeID int, initMsg string, args ...string) string

InstantiateWasm create a new contract instance. returns contract address

func (FuryaCli) IsInTendermintValset

func (c FuryaCli) IsInTendermintValset(valPubKey cryptotypes.PubKey) (rpc.ResultValidatorsOutput, bool)

IsInTendermintValset returns true when the giben pub key is in the current active tendermint validator set

func (FuryaCli) Keys

func (c FuryaCli) Keys(args ...string) string

func (FuryaCli) QueryBalance

func (c FuryaCli) QueryBalance(addr, denom string) int64

QueryBalance returns balance amount for given denom. 0 when not found

func (FuryaCli) QueryBalances

func (c FuryaCli) QueryBalances(addr string) string

QueryBalances queries all balances for an account. Returns json response Example:`{"balances":[{"denom":"node0token","amount":"1000000000"},{"denom":"ufury","amount":"400000003"}],"pagination":{}}`

func (FuryaCli) QuerySmart

func (c FuryaCli) QuerySmart(contractAddr, msg string, args ...string) string

QuerySmart run smart contract query

func (FuryaCli) QueryTotalSupply

func (c FuryaCli) QueryTotalSupply(denom string) int64

QueryTotalSupply returns total amount of tokens for a given denom. 0 when not found

func (FuryaCli) QueryValidator

func (c FuryaCli) QueryValidator(addr string) string

QueryValidator queries the validator for the given operator address. Returns json response

func (FuryaCli) QueryValidatorRewards

func (c FuryaCli) QueryValidatorRewards(addr string) sdk.DecCoin

QueryValidatorRewards queries the validator rewards for the given operator address

func (FuryaCli) StoreWasm

func (c FuryaCli) StoreWasm(file string, args ...string) int

StoreWasm uploads a wasm contract to the chain. Returns code id

func (FuryaCli) WithNodeAddress

func (c FuryaCli) WithNodeAddress(addr string) FuryaCli

func (FuryaCli) WithRunErrorMatcher

func (c FuryaCli) WithRunErrorMatcher(f RunErrorAssert) FuryaCli

WithRunErrorMatcher assert function to ensure run command error value

type GenesisMutator

type GenesisMutator func([]byte) []byte

func SetAllEngagementPoints

func SetAllEngagementPoints(t *testing.T, points int) GenesisMutator

SetAllEngagementPoints set the given value for all members of the engagement group (default = validators)

func SetBlockRewards

func SetBlockRewards(t *testing.T, amount sdk.Coin) GenesisMutator

SetBlockRewards set the valset contract config unbonding period

func SetConsensusMaxGas

func SetConsensusMaxGas(t *testing.T, max int) GenesisMutator

SetConsensusMaxGas max gas that can be consumed in a block

func SetEpochLength

func SetEpochLength(t *testing.T, epoch time.Duration) GenesisMutator

SetEpochLength set the valset contract config to given epoch length

func SetGlobalMinFee

func SetGlobalMinFee(t *testing.T, fees ...sdk.DecCoin) GenesisMutator

SetGlobalMinFee set the passed coins to the global minimum fee

func SetPoEParamsMutator

func SetPoEParamsMutator(t *testing.T, params poetypes.Params) GenesisMutator

SetPoEParamsMutator set params in genesis

func SetUnbondingPeriod

func SetUnbondingPeriod(t *testing.T, unbonding time.Duration) GenesisMutator

SetUnbondingPeriod set the stake contract config unbonding period

type Node

type Node struct {
	ID      string
	IP      string
	RPCPort int
	P2PPort int
}

func (Node) PeerAddr

func (n Node) PeerAddr() string

func (Node) RPCAddr

func (n Node) RPCAddr() string

type RPCClient

type RPCClient struct {
	// contains filtered or unexported fields
}

RPCClient is a test helper to interact with a node via the RPC endpoint.

func NewRPCCLient

func NewRPCCLient(t *testing.T, addr string) RPCClient

func (RPCClient) Validators

func (r RPCClient) Validators() []*tmtypes.Validator

type RunErrorAssert

type RunErrorAssert func(t require.TestingT, err error, msgAndArgs ...interface{})

RunErrorAssert is custom type that is satisfies by testify matchers as well

var (
	// ErrOutOfGasMatcher requires error with out of gas message
	ErrOutOfGasMatcher RunErrorAssert = func(t require.TestingT, err error, args ...interface{}) {
		const oogMsg = "out of gas"
		expErrWithMsg(t, err, args, oogMsg)
	}
	// ErrTimeoutMatcher requires time out message
	ErrTimeoutMatcher RunErrorAssert = func(t require.TestingT, err error, args ...interface{}) {
		const expMsg = "timed out waiting for tx to be included in a block"
		expErrWithMsg(t, err, args, expMsg)
	}
	// ErrPostFailedMatcher requires post failed
	ErrPostFailedMatcher RunErrorAssert = func(t require.TestingT, err error, args ...interface{}) {
		const expMsg = "post failed"
		expErrWithMsg(t, err, args, expMsg)
	}
	// ErrInvalidQuery requires smart query request failed
	ErrInvalidQuery RunErrorAssert = func(t require.TestingT, err error, args ...interface{}) {
		const expMsg = "query wasm contract failed"
		expErrWithMsg(t, err, args, expMsg)
	}
)

type SystemUnderTest

type SystemUnderTest struct {
	ChainStarted bool
	// contains filtered or unexported fields
}

SystemUnderTest blockchain provisioning

func NewSystemUnderTest

func NewSystemUnderTest(verbose bool, nodesCount int, blockTime time.Duration) *SystemUnderTest

func (*SystemUnderTest) AddFullnode

func (s *SystemUnderTest) AddFullnode(t *testing.T, beforeStart ...func(nodeNumber int, nodePath string)) Node

AddFullnode starts a new fullnode that connects to the existing chain but is not a validator.

func (SystemUnderTest) AllNodes

func (s SystemUnderTest) AllNodes(t *testing.T) []Node

func (SystemUnderTest) AllPeers

func (s SystemUnderTest) AllPeers(t *testing.T) []string

func (*SystemUnderTest) AwaitNextBlock

func (s *SystemUnderTest) AwaitNextBlock(t *testing.T, timeout ...time.Duration) int64

AwaitNextBlock is a first class function that any caller can use to ensure a new block was minted. Returns the new height

func (*SystemUnderTest) AwaitNodeUp

func (s *SystemUnderTest) AwaitNodeUp(t *testing.T, rpcAddr string)

AwaitNodeUp ensures the node is running

func (SystemUnderTest) BuildNewBinary

func (s SystemUnderTest) BuildNewBinary()

BuildNewBinary builds and installs new furya binary

func (*SystemUnderTest) ForEachNodeExecAndWait

func (s *SystemUnderTest) ForEachNodeExecAndWait(t *testing.T, cmds ...[]string) [][]string

ForEachNodeExecAndWait runs the given furya commands for all cluster nodes synchronously The commands output is returned for each node.

func (SystemUnderTest) IsDirty

func (s SystemUnderTest) IsDirty() bool

IsDirty true when non default genesis or other state modification were applied that might create incompatibility for tests

func (SystemUnderTest) Log

func (s SystemUnderTest) Log(msg string)

func (SystemUnderTest) Logf

func (s SystemUnderTest) Logf(msg string, args ...interface{})

func (*SystemUnderTest) MarkDirty

func (s *SystemUnderTest) MarkDirty()

MarkDirty whole chain will be reset when marked dirty

func (*SystemUnderTest) ModifyGenesisCLI

func (s *SystemUnderTest) ModifyGenesisCLI(t *testing.T, cmds ...[]string)

ModifyGenesisCLI executes the CLI commands to modify the genesis

func (*SystemUnderTest) ModifyGenesisJSON

func (s *SystemUnderTest) ModifyGenesisJSON(t *testing.T, mutators ...GenesisMutator)

ModifyGenesisJSON resets the chain and executes the callbacks to update the json representation The mutator callbacks after each other receive the genesis as raw bytes and return the updated genesis for the next. example:

return func(genesis []byte) []byte {
	val, _ := json.Marshal(sdk.NewDecCoins(fees...))
	state, _ := sjson.SetRawBytes(genesis, "app_state.globalfee.params.minimum_gas_prices", val)
	return state
}

func (*SystemUnderTest) NewEventListener

func (s *SystemUnderTest) NewEventListener(t *testing.T) *EventListener

NewEventListener constructor for Eventlistener with system rpc address

func (SystemUnderTest) PrintBuffer

func (s SystemUnderTest) PrintBuffer()

PrintBuffer prints the chain logs to the console

func (SystemUnderTest) RPCClient

func (s SystemUnderTest) RPCClient(t *testing.T) RPCClient

func (*SystemUnderTest) ReadGenesisJSON

func (s *SystemUnderTest) ReadGenesisJSON(t *testing.T) string

ReadGenesisJSON returns current genesis.json content as raw string

func (*SystemUnderTest) ResetChain

func (s *SystemUnderTest) ResetChain(t *testing.T)

ResetChain stops and clears all nodes state via 'unsafe-reset-all'

func (*SystemUnderTest) ResetDirtyChain

func (s *SystemUnderTest) ResetDirtyChain(t *testing.T)

ResetDirtyChain reset chain when non default setup or state (dirty)

func (*SystemUnderTest) SetupChain

func (s *SystemUnderTest) SetupChain()

func (*SystemUnderTest) StartChain

func (s *SystemUnderTest) StartChain(t *testing.T, xargs ...string)

func (*SystemUnderTest) StopChain

func (s *SystemUnderTest) StopChain()

StopChain stops the system under test and executes all registered cleanup callbacks

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL