document e2e test suite (#1489)

* add ChainId & StakingDenom to Chain

* document E2E_SKIP_SHUTDOWN env variable

* add update-kvtool make command

* document e2e test suite

* misc updates for clarity
This commit is contained in:
Robert Pirtle 2023-03-17 11:30:23 -07:00 committed by GitHub
parent 400e101cba
commit dbd7d632fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 87 additions and 11 deletions

View File

@ -322,4 +322,8 @@ start-remote-sims:
-—job-definition kava-sim-master \ -—job-definition kava-sim-master \
-—container-override environment=[{SIM_NAME=master-$(VERSION)}] -—container-override environment=[{SIM_NAME=master-$(VERSION)}]
update-kvtool:
git submodule update
cd tests/e2e/kvtool && make install
.PHONY: all build-linux install clean build test test-cli test-all test-rest test-basic start-remote-sims .PHONY: all build-linux install clean build test test-cli test-all test-rest test-basic start-remote-sims

View File

@ -1,4 +1,9 @@
# E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC is for a funded account used to intialize all new testing accounts. # E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC is for a funded account used to intialize all new testing accounts.
E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC='tent fitness boat among census primary pipe nose dream glance cave turtle electric fabric jacket shaft easy myself genuine this sibling pulse word unfold' E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC='tent fitness boat among census primary pipe nose dream glance cave turtle electric fabric jacket shaft easy myself genuine this sibling pulse word unfold'
# E2E_INCLUDE_IBC_TESTS when true will start a 2nd chain & open an IBC channel. It will enable all IBC tests. # E2E_INCLUDE_IBC_TESTS when true will start a 2nd chain & open an IBC channel. It will enable all IBC tests.
E2E_INCLUDE_IBC_TESTS=true E2E_INCLUDE_IBC_TESTS=true
# E2E_SKIP_SHUTDOWN when true will keep the networks running after tests complete (pass or fail)
# This is useful for debugging chain state when writing tests.
E2E_SKIP_SHUTDOWN=false

View File

@ -40,8 +40,7 @@ func TestIntegrationTestSuite(t *testing.T) {
// example test that queries kava via SDK and EVM // example test that queries kava via SDK and EVM
func (suite *IntegrationTestSuite) TestChainID() { func (suite *IntegrationTestSuite) TestChainID() {
// TODO: make chain agnostic, don't hardcode expected chain ids (in testutil) expectedEvmNetworkId, err := emtypes.ParseChainID(suite.Kava.ChainId)
expectedEvmNetworkId, err := emtypes.ParseChainID(testutil.ChainId)
suite.NoError(err) suite.NoError(err)
// EVM query // EVM query
@ -52,7 +51,7 @@ func (suite *IntegrationTestSuite) TestChainID() {
// SDK query // SDK query
nodeInfo, err := suite.Kava.Tm.GetNodeInfo(context.Background(), &tmservice.GetNodeInfoRequest{}) nodeInfo, err := suite.Kava.Tm.GetNodeInfo(context.Background(), &tmservice.GetNodeInfoRequest{})
suite.NoError(err) suite.NoError(err)
suite.Equal(testutil.ChainId, nodeInfo.DefaultNodeInfo.Network) suite.Equal(suite.Kava.ChainId, nodeInfo.DefaultNodeInfo.Network)
} }
// example test that funds a new account & queries its balance // example test that funds a new account & queries its balance

63
tests/e2e/readme.md Normal file
View File

@ -0,0 +1,63 @@
# end-2-end tests for kava
These tests use [`kvtool`](https://github.com/kava-labs/kvtool) to spin up a kava node configuration
and then runs tests against the running network. It is a git sub-repository in this directory. If not
present, you must initialize the subrepo: `git submodule update --init`.
Steps to run
1. Build a Kava docker image tagged `kava/kava:local`: `make build-docker`
2. Ensure latest `kvtool` is installed: `make update-kvtool`
3. Run the test suite: `make test-e2e`
**Note:** The suite will use your locally installed `kvtool` if present. If not present, it will be
installed. If the `kvtool` repo is updated, you must manually update your existing local binary: `make update-kvtool`
## Configuration
The test suite uses env variables that can be set in [`.env`](.env). See that file for a complete list
of options. The variables are parsed and imported into a `SuiteConfig` in [`testutil/config.go`](testutil/config.go).
The variables in `.env` will not override variables that are already present in the environment.
ie. Running `E2E_INCLUDE_IBC_TESTS=false make test-e2e` will disable the ibc tests regardless of how
the variable is set in `.env`.
## `Chain`s
A `testutil.Chain` is the abstraction around details, query clients, & signing accounts for interacting with a
network. After networks are running, a `Chain` is initialized & attached to the main test suite `testutil.E2eTestSuite`.
The primary Kava network is accessible via `suite.Kava`.
Details about the chains can be found [here](runner/chain.go#L62-84).
## `SigningAccount`s
Each `Chain` wraps a map of signing clients for that network. The `SigningAccount` contains clients
for both the Kava EVM and Cosmos-Sdk co-chains.
The methods `SignAndBroadcastKavaTx` and `SignAndBroadcastEvmTx` are used to submit transactions to
the sdk and evm chains, respectively.
### Creating a new account
```go
// create an account on the Kava network, initially funded with 10 KAVA
acc := suite.Kava.NewFundedAccount("account-name", sdk.NewCoins(sdk.NewCoin("ukava", 10e6)))
// you can also access accounts by the name with which they were registered to the suite
acc := suite.Kava.GetAccount("account-name")
```
Funds for new accounts are distributed from the account with the mnemonic from the `E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC`
env variable. The account will be generated with HD coin type 60 & the `ethsecp256k1` private key signing algorithm.
The initial funding account is registered with the name `"whale"`.
## IBC tests
When IBC tests are enabled, an additional network is spun up with a different chain id & an IBC channel is
opened between it and the primary Kava network.
The IBC network runs kava with a different chain id and staking denom (see [runner/chain.go](runner/chain.go)).
The IBC chain queriers & accounts are accessible via `suite.Ibc`.
IBC tests can be disabled by setting `E2E_INCLUDE_IBC_TESTS` to `false`.

View File

@ -21,6 +21,7 @@ type ChainDetails struct {
RestPort string RestPort string
EvmPort string EvmPort string
ChainId string
StakingDenom string StakingDenom string
} }
@ -68,6 +69,7 @@ var (
GrpcPort: "9090", GrpcPort: "9090",
EvmPort: "8545", EvmPort: "8545",
ChainId: "kavalocalnet_8888-1",
StakingDenom: "ukava", StakingDenom: "ukava",
} }
ibcChain = ChainDetails{ ibcChain = ChainDetails{
@ -76,6 +78,7 @@ var (
GrpcPort: "9092", GrpcPort: "9092",
EvmPort: "8547", EvmPort: "8547",
ChainId: "kavalocalnet_8889-2",
StakingDenom: "uatom", StakingDenom: "uatom",
} }
) )

View File

@ -191,7 +191,7 @@ func (chain *Chain) NewFundedAccount(name string, funds sdk.Coins) *SigningAccou
acc := chain.AddNewSigningAccount( acc := chain.AddNewSigningAccount(
name, name,
hd.CreateHDPath(app.Bip44CoinType, 0, 0), hd.CreateHDPath(app.Bip44CoinType, 0, 0),
ChainId, chain.ChainId,
mnemonic, mnemonic,
) )
@ -208,7 +208,7 @@ func (chain *Chain) NewFundedAccount(name string, funds sdk.Coins) *SigningAccou
banktypes.NewMsgSend(whale.SdkAddress, acc.SdkAddress, funds), banktypes.NewMsgSend(whale.SdkAddress, acc.SdkAddress, funds),
}, },
GasLimit: 2e5, GasLimit: 2e5,
FeeAmount: sdk.NewCoins(sdk.NewCoin(chain.details.StakingDenom, sdk.NewInt(75000))), FeeAmount: sdk.NewCoins(sdk.NewCoin(chain.StakingDenom, sdk.NewInt(75000))),
Data: fmt.Sprintf("initial funding of account %s", name), Data: fmt.Sprintf("initial funding of account %s", name),
}, },
) )

View File

@ -26,7 +26,8 @@ type Chain struct {
accounts map[string]*SigningAccount accounts map[string]*SigningAccount
t *testing.T t *testing.T
details *runner.ChainDetails StakingDenom string
ChainId string
EvmClient *ethclient.Client EvmClient *ethclient.Client
Auth authtypes.QueryClient Auth authtypes.QueryClient
@ -39,9 +40,12 @@ type Chain struct {
// A signing client for the fundedAccountMnemonic is initialized. This account is referred to in the // A signing client for the fundedAccountMnemonic is initialized. This account is referred to in the
// code as "whale" and it is used to supply funds to all new accounts. // code as "whale" and it is used to supply funds to all new accounts.
func NewChain(t *testing.T, details *runner.ChainDetails, fundedAccountMnemonic string) (*Chain, error) { func NewChain(t *testing.T, details *runner.ChainDetails, fundedAccountMnemonic string) (*Chain, error) {
chain := &Chain{t: t} chain := &Chain{
t: t,
StakingDenom: details.StakingDenom,
ChainId: details.ChainId,
}
chain.encodingConfig = app.MakeEncodingConfig() chain.encodingConfig = app.MakeEncodingConfig()
chain.details = details
grpcUrl := fmt.Sprintf("http://localhost:%s", details.GrpcPort) grpcUrl := fmt.Sprintf("http://localhost:%s", details.GrpcPort)
grpcConn, err := util.NewGrpcConnection(grpcUrl) grpcConn, err := util.NewGrpcConnection(grpcUrl)
@ -66,7 +70,7 @@ func NewChain(t *testing.T, details *runner.ChainDetails, fundedAccountMnemonic
whale := chain.AddNewSigningAccount( whale := chain.AddNewSigningAccount(
FundedAccountName, FundedAccountName,
hd.CreateHDPath(Bip44CoinType, 0, 0), hd.CreateHDPath(Bip44CoinType, 0, 0),
ChainId, chain.ChainId,
fundedAccountMnemonic, fundedAccountMnemonic,
) )

View File

@ -10,9 +10,7 @@ import (
) )
const ( const (
ChainId = "kavalocalnet_8888-1"
FundedAccountName = "whale" FundedAccountName = "whale"
StakingDenom = "ukava"
// use coin type 60 so we are compatible with accounts from `kava add keys --eth <name>` // use coin type 60 so we are compatible with accounts from `kava add keys --eth <name>`
// these accounts use the ethsecp256k1 signing algorithm that allows the signing client // these accounts use the ethsecp256k1 signing algorithm that allows the signing client
// to manage both sdk & evm txs. // to manage both sdk & evm txs.