Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: e2e test reliability #2276

Merged
merged 60 commits into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
10d1b58
delete eth dockerfiles
toteki Oct 8, 2023
3a015ad
move gaia funcs to gaia.go
toteki Oct 9, 2023
a9c2e13
move metoken util out of setup folder; move oracle tests to oracle file
toteki Oct 9, 2023
8089346
function comments
toteki Oct 9, 2023
010081e
todo comments
toteki Oct 9, 2023
b1ecb91
comments
toteki Oct 9, 2023
0f387d4
comments and combine some functions
toteki Oct 9, 2023
fb68b83
price-feeder.go
toteki Oct 9, 2023
ad36a20
import order
toteki Oct 9, 2023
4acd3d0
ibc.go
toteki Oct 9, 2023
ce2565b
add test account
toteki Oct 9, 2023
524a024
revert and try creating accounts later
toteki Oct 9, 2023
ac88978
refactor coins without string
toteki Oct 9, 2023
0efd173
try with commented out
toteki Oct 9, 2023
bdc0d24
init balance as coins, not string
toteki Oct 9, 2023
1825421
Merge branch 'adam/e2e2' into adam/e2speed2
toteki Oct 9, 2023
1c36c38
fix merge
toteki Oct 9, 2023
8f66c2d
move vars around
toteki Oct 9, 2023
3859ff5
comment
toteki Oct 9, 2023
d4ce9f2
Merge branch 'adam/e2e2' into adam/e2speed2
toteki Oct 9, 2023
dfaa82e
fix merge
toteki Oct 9, 2023
5369dac
Merge branch 'main' into adam/e2speed2
toteki Oct 10, 2023
200a8f9
lower wait time
toteki Oct 10, 2023
ab14fb6
dedicated client for test accounts
toteki Oct 10, 2023
33649c3
add client to each validator
toteki Oct 10, 2023
19f9ce3
client name
toteki Oct 10, 2023
7cbb799
overhaul tests to use single-mnemonic clients
toteki Oct 10, 2023
11f4087
fix
toteki Oct 10, 2023
0160c7d
fix
toteki Oct 10, 2023
9c0debc
logs
toteki Oct 10, 2023
858874a
prevent division by zero
toteki Oct 10, 2023
e14274c
prevent division by zero
toteki Oct 10, 2023
83ae6f8
rename fix
toteki Oct 10, 2023
3ac8acc
account sequence: use expcted value on retry
toteki Oct 10, 2023
0cfd9b2
fix delegation
toteki Oct 10, 2023
6993c27
switch account on meToken test
toteki Oct 11, 2023
becda69
Merge branch 'main' into adam/e2speed2
toteki Oct 11, 2023
6e3dcf1
log every ibc tx
toteki Oct 11, 2023
986772f
modify logs
toteki Oct 11, 2023
da936cd
logs++
toteki Oct 11, 2023
c86f476
revert one addr change in ibc
toteki Oct 11, 2023
0c8f42a
++
toteki Oct 11, 2023
682238b
++
toteki Oct 11, 2023
e6676e9
why was this working before? x2 fixed
toteki Oct 12, 2023
9e870b5
diagnose
toteki Oct 12, 2023
2f0b540
is that the last of them?
toteki Oct 12, 2023
2d28d04
empty commit
toteki Oct 12, 2023
2906101
Merge branch 'main' into adam/e2speed2
toteki Oct 12, 2023
0787cae
oracle tests
toteki Oct 12, 2023
84f273c
Revert "build(deps): Bump github.com/spf13/viper from 1.16.0 to 1.17.…
toteki Oct 12, 2023
5b2f375
Merge branch 'adam/revert' into adam/e2speed2
toteki Oct 12, 2023
0ee88ac
tidy
toteki Oct 12, 2023
e4bb52c
Merge branch 'adam/revert' into adam/e2speed2
toteki Oct 12, 2023
50c0666
exceed quota more reliably
toteki Oct 12, 2023
fe8a3ad
exceed quota more reliably
toteki Oct 12, 2023
3f3d6b7
rewrite ibc test to use reliable amounts (not > or < quota based on r…
toteki Oct 12, 2023
321ddd5
fix
toteki Oct 12, 2023
d2e6033
add log
toteki Oct 12, 2023
ada33de
++
toteki Oct 12, 2023
56d8982
skip ibc e2e
toteki Oct 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ test-e2e-cov: $(TEST_E2E_DEPS)

test-e2e-clean:
docker stop umee0 umee1 umee2 umee-gaia-relayer gaiaval0 umee-price-feeder || true
docker rm umee0 umee1 umee2 umee-gaia-relayer gaiaval0 umee-price-feeder
docker rm umee0 umee1 umee2 umee-gaia-relayer gaiaval0 umee-price-feeder || true
docker network prune -f

test-qa:
@go test ./tests/qa/... -timeout 30m -v -tags='test_qa'
Expand Down
24 changes: 0 additions & 24 deletions tests/e2e/docker/eth.Dockerfile

This file was deleted.

9 changes: 0 additions & 9 deletions tests/e2e/docker/ganache.Dockerfile

This file was deleted.

20 changes: 20 additions & 0 deletions tests/e2e/e2e_metoken_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,23 @@ func (s *E2ETest) executeRedeemWithFailure(umeeAddr string, meToken sdk.Coin, as
500*time.Millisecond,
)
}

func (s *E2ETest) TxMetokenSwap(umeeAddr string, asset sdk.Coin, meTokenDenom string) error {
req := &metoken.MsgSwap{
User: umeeAddr,
Asset: asset,
MetokenDenom: meTokenDenom,
}

return s.BroadcastTxWithRetry(req)
}

func (s *E2ETest) TxMetokenRedeem(umeeAddr string, meToken sdk.Coin, assetDenom string) error {
req := &metoken.MsgRedeem{
User: umeeAddr,
Metoken: meToken,
AssetDenom: assetDenom,
}

return s.BroadcastTxWithRetry(req)
}
49 changes: 49 additions & 0 deletions tests/e2e/e2e_oracle_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package e2e

import (
"time"

"github.com/umee-network/umee/v6/tests/grpc"
)

// TestMedians queries for the oracle params, collects historical
// prices based on those params, checks that the stored medians and
// medians deviations are correct, updates the oracle params with
// a gov prop, then checks the medians and median deviations again.
func (s *E2ETest) TestMedians() {
err := grpc.MedianCheck(s.Umee)
s.Require().NoError(err)
}

func (s *E2ETest) TestUpdateOracleParams() {
params, err := s.Umee.QueryOracleParams()
s.Require().NoError(err)

s.Require().Equal(uint64(5), params.HistoricStampPeriod)
s.Require().Equal(uint64(4), params.MaximumPriceStamps)
s.Require().Equal(uint64(20), params.MedianStampPeriod)

// simple retry loop to submit and pass a proposal
for i := 0; i < 3; i++ {
err = grpc.SubmitAndPassProposal(
s.Umee,
grpc.OracleParamChanges(10, 2, 20),
)
if err == nil {
break
}

time.Sleep(1 * time.Second)
}

s.Require().NoError(err, "submit and pass proposal")

params, err = s.Umee.QueryOracleParams()
s.Require().NoError(err)

s.Require().Equal(uint64(10), params.HistoricStampPeriod)
s.Require().Equal(uint64(2), params.MaximumPriceStamps)
s.Require().Equal(uint64(20), params.MedianStampPeriod)

s.Require().NoError(err)
}
49 changes: 6 additions & 43 deletions tests/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@ import (
"time"

"github.com/stretchr/testify/suite"

sdk "github.com/cosmos/cosmos-sdk/types"

setup "github.com/umee-network/umee/v6/tests/e2e/setup"
"github.com/umee-network/umee/v6/tests/grpc"
)

type E2ETest struct {
setup.E2ETestSuite
}

// TestE2ETestSuite is the entry point for e2e testing. It runs after the docker build commands
// listed in Makefile as prerequisites to test-e2e. It first calls E2ETestSuite.SetupSuite() and
// then runs all public methods on the suite whose names match regex "^Test". These tests appear
// to run in series (and in alphabetical order), so the only other transactions being submitted
// while they run are the price feeder votes by the validators running in docker containers.
func TestE2ETestSuite(t *testing.T) {
suite.Run(t, new(E2ETest))
}
Expand Down Expand Up @@ -48,45 +53,3 @@ func (s *E2ETest) mustFailTx(msg sdk.Msg, errSubstring string) {
errSubstring,
)
}

// TestMedians queries for the oracle params, collects historical
// prices based on those params, checks that the stored medians and
// medians deviations are correct, updates the oracle params with
// a gov prop, then checks the medians and median deviations again.
func (s *E2ETest) TestMedians() {
err := grpc.MedianCheck(s.Umee)
s.Require().NoError(err)
}

func (s *E2ETest) TestUpdateOracleParams() {
params, err := s.Umee.QueryOracleParams()
s.Require().NoError(err)

s.Require().Equal(uint64(5), params.HistoricStampPeriod)
s.Require().Equal(uint64(4), params.MaximumPriceStamps)
s.Require().Equal(uint64(20), params.MedianStampPeriod)

// simple retry loop to submit and pass a proposal
for i := 0; i < 3; i++ {
err = grpc.SubmitAndPassProposal(
s.Umee,
grpc.OracleParamChanges(10, 2, 20),
)
if err == nil {
break
}

time.Sleep(1 * time.Second)
}

s.Require().NoError(err, "submit and pass proposal")

params, err = s.Umee.QueryOracleParams()
s.Require().NoError(err)

s.Require().Equal(uint64(10), params.HistoricStampPeriod)
s.Require().Equal(uint64(2), params.MaximumPriceStamps)
s.Require().Equal(uint64(20), params.MedianStampPeriod)

s.Require().NoError(err)
}
63 changes: 63 additions & 0 deletions tests/e2e/setup/accounts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package setup

import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"

appparams "github.com/umee-network/umee/v6/app/params"
"github.com/umee-network/umee/v6/util/coin"
"github.com/umee-network/umee/v6/x/metoken/mocks"
)

type testAccount struct {
mnemonic string
keyInfo keyring.Record
addr sdk.AccAddress
}

var (
// Initial coins to give to validator 0 (which it uses to fund test accounts)
val0Coins = sdk.NewCoins(
coin.New(appparams.BondDenom, 1_000000_000000),
coin.New(PhotonDenom, 1_000000_000000),
coin.New(mocks.USDTBaseDenom, 1_000000_000000),
)
// Initial coins to give to all other validators
val1Coins = sdk.NewCoins(
coin.New(appparams.BondDenom, 1_000000_000000),
)

// Number of test accounts to initialize in chain.TestAccounts
numTestAccounts = 1

// Initial coins to give to each test account. Ensure that this * numTestAccounts < val0Coins
testAccountCoins = sdk.NewCoins(
coin.New(appparams.BondDenom, 100000_000000),
coin.New(PhotonDenom, 100000_000000),
coin.New(mocks.USDTBaseDenom, 100000_000000),
)

// TODO: stake less on the validators, and instead delegate from a test account
stakeAmountCoin = coin.New(appparams.BondDenom, 1000)
stakeAmountCoin2 = coin.New(appparams.BondDenom, 5000)
toteki marked this conversation as resolved.
Show resolved Hide resolved
)

// create a test account, which is an address with a mnemonic stored only in memory, to be used with the network.
// these are created randomly each time and added to the suite, so they should be accessed by c.TestAccounts[i >= 0]
// and queries by the desired account's address
func (c *chain) createTestAccount(cdc codec.Codec) error {
mnemonic, info, err := createMemoryKey(cdc)
if err != nil {
return err
}
ta := testAccount{}
ta.keyInfo = *info
ta.mnemonic = mnemonic
ta.addr, err = info.GetAddress() // TODO: verify this address starts with "umee1"
if err != nil {
return err
}
c.TestAccounts = append(c.TestAccounts, &ta)
return nil
}
54 changes: 18 additions & 36 deletions tests/e2e/setup/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ type chain struct {
dataDir string
ID string
Validators []*validator
TestAccounts []*testAccount
GaiaValidators []*gaiaValidator
}

// newChain creates a chain with a random chain ID and makes a temporary directory to hold its data
func newChain() (*chain, error) {
tmpDir, err := os.MkdirTemp("", "umee-e2e-testnet-")
if err != nil {
Expand All @@ -56,64 +58,44 @@ func newChain() (*chain, error) {
}, nil
}

// configDir is located at <chain.dataDir>/<chain.ID>
func (c *chain) configDir() string {
return fmt.Sprintf("%s/%s", c.dataDir, c.ID)
}

// createAndInitValidators adds a number of validators to the chain and initializes their
// keys, config.toml and genesis.json in separate config directories created for each validator.
// Their monikers are all set to "umee" but their indexes are different.
func (c *chain) createAndInitValidators(cdc codec.Codec, count int) error {
for i := 0; i < count; i++ {
node := c.createValidator(i)
node := validator{
chain: c,
index: i,
moniker: "umee",
}

// generate genesis files
// create config directory and initializes config.toml and genesis.json
if err := node.init(cdc); err != nil {
return err
}

c.Validators = append(c.Validators, node)

// create keys
// generate a random key and save to keyring-backend-test in the validator's config directory
if err := node.createKey(cdc, "val"); err != nil {
return err
}
// loads or generates a node key in the validator's config directory
// TODO (comment): which are we doing? loading or generating?
if err := node.createNodeKey(); err != nil {
return err
}
// loads or generates a consensus key in the validator's config directory
// TODO (comment): which are we doing? loading or generating?
if err := node.createConsensusKey(); err != nil {
return err
}
}

return nil
}

func (c *chain) createAndInitGaiaValidator(cdc codec.Codec) error {
// create gaia validator
gaiaVal := c.createGaiaValidator(0)

// create keys
mnemonic, info, err := createMemoryKey(cdc)
if err != nil {
return err
c.Validators = append(c.Validators, &node)
}

gaiaVal.keyInfo = *info
gaiaVal.mnemonic = mnemonic

c.GaiaValidators = append(c.GaiaValidators, gaiaVal)

return nil
}

func (c *chain) createValidator(index int) *validator {
return &validator{
chain: c,
index: index,
moniker: "umee",
}
}

func (c *chain) createGaiaValidator(index int) *gaiaValidator {
return &gaiaValidator{
index: index,
}
}
Loading