diff --git a/Makefile b/Makefile index 910d3416..1534604f 100644 --- a/Makefile +++ b/Makefile @@ -322,4 +322,8 @@ start-remote-sims: -—job-definition kava-sim-master \ -—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 diff --git a/tests/e2e/.env b/tests/e2e/.env index fe3e6cea..d68ae06e 100644 --- a/tests/e2e/.env +++ b/tests/e2e/.env @@ -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='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=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 diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index a6d7fa71..2021d006 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -40,8 +40,7 @@ func TestIntegrationTestSuite(t *testing.T) { // example test that queries kava via SDK and EVM func (suite *IntegrationTestSuite) TestChainID() { - // TODO: make chain agnostic, don't hardcode expected chain ids (in testutil) - expectedEvmNetworkId, err := emtypes.ParseChainID(testutil.ChainId) + expectedEvmNetworkId, err := emtypes.ParseChainID(suite.Kava.ChainId) suite.NoError(err) // EVM query @@ -52,7 +51,7 @@ func (suite *IntegrationTestSuite) TestChainID() { // SDK query nodeInfo, err := suite.Kava.Tm.GetNodeInfo(context.Background(), &tmservice.GetNodeInfoRequest{}) 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 diff --git a/tests/e2e/readme.md b/tests/e2e/readme.md new file mode 100644 index 00000000..fe5084bc --- /dev/null +++ b/tests/e2e/readme.md @@ -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`. diff --git a/tests/e2e/runner/chain.go b/tests/e2e/runner/chain.go index 1e3aad8a..7dcfd66f 100644 --- a/tests/e2e/runner/chain.go +++ b/tests/e2e/runner/chain.go @@ -21,6 +21,7 @@ type ChainDetails struct { RestPort string EvmPort string + ChainId string StakingDenom string } @@ -68,6 +69,7 @@ var ( GrpcPort: "9090", EvmPort: "8545", + ChainId: "kavalocalnet_8888-1", StakingDenom: "ukava", } ibcChain = ChainDetails{ @@ -76,6 +78,7 @@ var ( GrpcPort: "9092", EvmPort: "8547", + ChainId: "kavalocalnet_8889-2", StakingDenom: "uatom", } ) diff --git a/tests/e2e/testutil/account.go b/tests/e2e/testutil/account.go index 281f195b..8493fc96 100644 --- a/tests/e2e/testutil/account.go +++ b/tests/e2e/testutil/account.go @@ -191,7 +191,7 @@ func (chain *Chain) NewFundedAccount(name string, funds sdk.Coins) *SigningAccou acc := chain.AddNewSigningAccount( name, hd.CreateHDPath(app.Bip44CoinType, 0, 0), - ChainId, + chain.ChainId, mnemonic, ) @@ -208,7 +208,7 @@ func (chain *Chain) NewFundedAccount(name string, funds sdk.Coins) *SigningAccou banktypes.NewMsgSend(whale.SdkAddress, acc.SdkAddress, funds), }, 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), }, ) diff --git a/tests/e2e/testutil/chain.go b/tests/e2e/testutil/chain.go index 850828ba..b0add223 100644 --- a/tests/e2e/testutil/chain.go +++ b/tests/e2e/testutil/chain.go @@ -26,7 +26,8 @@ type Chain struct { accounts map[string]*SigningAccount t *testing.T - details *runner.ChainDetails + StakingDenom string + ChainId string EvmClient *ethclient.Client 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 // 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) { - chain := &Chain{t: t} + chain := &Chain{ + t: t, + StakingDenom: details.StakingDenom, + ChainId: details.ChainId, + } chain.encodingConfig = app.MakeEncodingConfig() - chain.details = details grpcUrl := fmt.Sprintf("http://localhost:%s", details.GrpcPort) grpcConn, err := util.NewGrpcConnection(grpcUrl) @@ -66,7 +70,7 @@ func NewChain(t *testing.T, details *runner.ChainDetails, fundedAccountMnemonic whale := chain.AddNewSigningAccount( FundedAccountName, hd.CreateHDPath(Bip44CoinType, 0, 0), - ChainId, + chain.ChainId, fundedAccountMnemonic, ) diff --git a/tests/e2e/testutil/suite.go b/tests/e2e/testutil/suite.go index 41c6605a..e29f75b8 100644 --- a/tests/e2e/testutil/suite.go +++ b/tests/e2e/testutil/suite.go @@ -10,9 +10,7 @@ import ( ) const ( - ChainId = "kavalocalnet_8888-1" FundedAccountName = "whale" - StakingDenom = "ukava" // use coin type 60 so we are compatible with accounts from `kava add keys --eth ` // these accounts use the ethsecp256k1 signing algorithm that allows the signing client // to manage both sdk & evm txs.