mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-29 09:45:18 +00:00
247 lines
8.3 KiB
Go
247 lines
8.3 KiB
Go
package testutil
|
|
|
|
import (
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
sdkmath "cosmossdk.io/math"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
"github.com/0glabs/0g-chain/chaincfg"
|
|
|
|
"github.com/0glabs/0g-chain/tests/e2e/runner"
|
|
"github.com/0glabs/0g-chain/tests/util"
|
|
)
|
|
|
|
const (
|
|
FundedAccountName = "whale"
|
|
// use coin type 60 so we are compatible with accounts from `0gchaind add keys --eth <name>`
|
|
// these accounts use the ethsecp256k1 signing algorithm that allows the signing client
|
|
// to manage both sdk & evm txs.
|
|
Bip44CoinType = 60
|
|
|
|
IbcPort = "transfer"
|
|
IbcChannel = "channel-0"
|
|
)
|
|
|
|
// DeployedErc20 is a type that wraps the details of the pre-deployed erc20 used by the e2e test suite.
|
|
// The Address comes from SuiteConfig.ZgChainErc20Address
|
|
// The CosmosDenom is fetched from the EnabledConversionPairs param of x/evmutil.
|
|
// The tests expect the following:
|
|
// - the funded account has a nonzero balance of the erc20
|
|
// - the erc20 is enabled for conversion to sdk.Coin
|
|
// - the corresponding sdk.Coin is enabled as a cdp collateral type
|
|
// These requirements are checked in InitZgChainEvmData().
|
|
type DeployedErc20 struct {
|
|
Address common.Address
|
|
CosmosDenom string
|
|
|
|
CdpCollateralType string
|
|
}
|
|
|
|
// E2eTestSuite is a testify test suite for running end-to-end integration tests on ZgChain.
|
|
type E2eTestSuite struct {
|
|
suite.Suite
|
|
|
|
config SuiteConfig
|
|
runner runner.NodeRunner
|
|
|
|
ZgChain *Chain
|
|
Ibc *Chain
|
|
|
|
UpgradeHeight int64
|
|
DeployedErc20 DeployedErc20
|
|
|
|
cost costSummary
|
|
enableRefunds bool
|
|
}
|
|
|
|
// costSummary wraps info about what funds get irrecoverably spent by the test suite run
|
|
type costSummary struct {
|
|
sdkAddress string
|
|
evmAddress string
|
|
|
|
erc20BalanceBefore *big.Int
|
|
erc20BalanceAfter *big.Int
|
|
|
|
sdkBalanceBefore sdk.Coins
|
|
sdkBalanceAfter sdk.Coins
|
|
}
|
|
|
|
// String implements fmt.Stringer
|
|
func (s costSummary) String() string {
|
|
before := sdk.NewCoins(s.sdkBalanceBefore...).Add(sdk.NewCoin("erc20", sdkmath.NewIntFromBigInt(s.erc20BalanceBefore)))
|
|
after := sdk.NewCoins(s.sdkBalanceAfter...).Add(sdk.NewCoin("erc20", sdkmath.NewIntFromBigInt(s.erc20BalanceAfter)))
|
|
cost, _ := before.SafeSub(after...)
|
|
return fmt.Sprintf("Cost Summary for %s (%s):\nbefore:\n%s\nafter:\n%s\ncost:\n%s\n",
|
|
s.sdkAddress, s.evmAddress, util.PrettyPrintCoins(before), util.PrettyPrintCoins(after), util.PrettyPrintCoins(cost),
|
|
)
|
|
}
|
|
|
|
// SetupSuite is run before all tests. It initializes chain connections and sets up the
|
|
// account used for funding accounts in the tests.
|
|
func (suite *E2eTestSuite) SetupSuite() {
|
|
var err error
|
|
fmt.Println("setting up test suite.")
|
|
chaincfg.SetSDKConfig()
|
|
|
|
suiteConfig := ParseSuiteConfig()
|
|
suite.config = suiteConfig
|
|
suite.DeployedErc20 = DeployedErc20{
|
|
Address: common.HexToAddress(suiteConfig.ZgChainErc20Address),
|
|
// Denom & CdpCollateralType are fetched in InitZgChainEvmData()
|
|
}
|
|
|
|
// setup the correct NodeRunner for the given config
|
|
if suiteConfig.Kvtool != nil {
|
|
suite.runner = suite.SetupKvtoolNodeRunner()
|
|
} else if suiteConfig.LiveNetwork != nil {
|
|
suite.runner = suite.SetupLiveNetworkNodeRunner()
|
|
} else {
|
|
panic("expected either kvtool or live network configs to be defined")
|
|
}
|
|
|
|
chains := suite.runner.StartChains()
|
|
zgchain := chains.MustGetChain("0gchain")
|
|
suite.ZgChain, err = NewChain(suite.T(), zgchain, suiteConfig.FundedAccountMnemonic)
|
|
if err != nil {
|
|
suite.runner.Shutdown()
|
|
suite.T().Fatalf("failed to create 0g-chain querier: %s", err)
|
|
}
|
|
|
|
if suiteConfig.IncludeIbcTests {
|
|
ibcchain := chains.MustGetChain("ibc")
|
|
suite.Ibc, err = NewChain(suite.T(), ibcchain, suiteConfig.FundedAccountMnemonic)
|
|
if err != nil {
|
|
suite.runner.Shutdown()
|
|
suite.T().Fatalf("failed to create ibc chain querier: %s", err)
|
|
}
|
|
}
|
|
|
|
suite.InitZgChainEvmData()
|
|
|
|
whale := suite.ZgChain.GetAccount(FundedAccountName)
|
|
suite.cost = costSummary{
|
|
sdkAddress: whale.SdkAddress.String(),
|
|
evmAddress: whale.EvmAddress.Hex(),
|
|
sdkBalanceBefore: suite.ZgChain.QuerySdkForBalances(whale.SdkAddress),
|
|
erc20BalanceBefore: suite.ZgChain.GetErc20Balance(suite.DeployedErc20.Address, whale.EvmAddress),
|
|
}
|
|
}
|
|
|
|
// TearDownSuite is run after all tests have run.
|
|
// In the event of a panic during the tests, it is run after testify recovers.
|
|
func (suite *E2eTestSuite) TearDownSuite() {
|
|
fmt.Println("tearing down test suite.")
|
|
|
|
whale := suite.ZgChain.GetAccount(FundedAccountName)
|
|
|
|
if suite.enableRefunds {
|
|
suite.cost.sdkBalanceAfter = suite.ZgChain.QuerySdkForBalances(whale.SdkAddress)
|
|
suite.cost.erc20BalanceAfter = suite.ZgChain.GetErc20Balance(suite.DeployedErc20.Address, whale.EvmAddress)
|
|
fmt.Println("==BEFORE REFUNDS==")
|
|
fmt.Println(suite.cost)
|
|
|
|
fmt.Println("attempting to return all unused funds")
|
|
suite.ZgChain.ReturnAllFunds()
|
|
|
|
fmt.Println("==AFTER REFUNDS==")
|
|
}
|
|
|
|
// calculate & output cost summary for funded account
|
|
suite.cost.sdkBalanceAfter = suite.ZgChain.QuerySdkForBalances(whale.SdkAddress)
|
|
suite.cost.erc20BalanceAfter = suite.ZgChain.GetErc20Balance(suite.DeployedErc20.Address, whale.EvmAddress)
|
|
fmt.Println(suite.cost)
|
|
|
|
// close all account request channels
|
|
suite.ZgChain.Shutdown()
|
|
if suite.Ibc != nil {
|
|
suite.Ibc.Shutdown()
|
|
}
|
|
// gracefully shutdown docker container(s)
|
|
suite.runner.Shutdown()
|
|
}
|
|
|
|
// SetupKvtoolNodeRunner is a helper method for building a KvtoolRunnerConfig from the suite config.
|
|
func (suite *E2eTestSuite) SetupKvtoolNodeRunner() *runner.KvtoolRunner {
|
|
// upgrade tests are only supported on kvtool networks
|
|
suite.UpgradeHeight = suite.config.Kvtool.ZgChainUpgradeHeight
|
|
suite.enableRefunds = false
|
|
|
|
runnerConfig := runner.KvtoolRunnerConfig{
|
|
ZgChainConfigTemplate: suite.config.Kvtool.ZgChainConfigTemplate,
|
|
|
|
IncludeIBC: suite.config.IncludeIbcTests,
|
|
ImageTag: "local",
|
|
|
|
EnableAutomatedUpgrade: suite.config.Kvtool.IncludeAutomatedUpgrade,
|
|
ZgChainUpgradeName: suite.config.Kvtool.ZgChainUpgradeName,
|
|
ZgChainUpgradeHeight: suite.config.Kvtool.ZgChainUpgradeHeight,
|
|
ZgChainUpgradeBaseImageTag: suite.config.Kvtool.ZgChainUpgradeBaseImageTag,
|
|
|
|
SkipShutdown: suite.config.SkipShutdown,
|
|
}
|
|
|
|
return runner.NewKvtoolRunner(runnerConfig)
|
|
}
|
|
|
|
// SetupLiveNetworkNodeRunner is a helper method for building a LiveNodeRunner from the suite config.
|
|
func (suite *E2eTestSuite) SetupLiveNetworkNodeRunner() *runner.LiveNodeRunner {
|
|
// live network setup doesn't presently support ibc
|
|
if suite.config.IncludeIbcTests {
|
|
panic("ibc tests not supported for live network configuration")
|
|
}
|
|
|
|
// Manually set upgrade height for live networks
|
|
suite.UpgradeHeight = suite.config.LiveNetwork.UpgradeHeight
|
|
suite.enableRefunds = true
|
|
|
|
runnerConfig := runner.LiveNodeRunnerConfig{
|
|
ZgChainRpcUrl: suite.config.LiveNetwork.ZgChainRpcUrl,
|
|
ZgChainGrpcUrl: suite.config.LiveNetwork.ZgChainGrpcUrl,
|
|
ZgChainEvmRpcUrl: suite.config.LiveNetwork.ZgChainEvmRpcUrl,
|
|
UpgradeHeight: suite.config.LiveNetwork.UpgradeHeight,
|
|
}
|
|
|
|
return runner.NewLiveNodeRunner(runnerConfig)
|
|
}
|
|
|
|
// SkipIfIbcDisabled should be called at the start of tests that require IBC.
|
|
// It gracefully skips the current test if IBC tests are disabled.
|
|
func (suite *E2eTestSuite) SkipIfIbcDisabled() {
|
|
if !suite.config.IncludeIbcTests {
|
|
suite.T().SkipNow()
|
|
}
|
|
}
|
|
|
|
// SkipIfUpgradeDisabled should be called at the start of tests that require automated upgrades.
|
|
// It gracefully skips the current test if upgrades are dissabled.
|
|
// Note: automated upgrade tests are currently only enabled for Kvtool suite runs.
|
|
func (suite *E2eTestSuite) SkipIfUpgradeDisabled() {
|
|
if suite.config.Kvtool != nil && !suite.config.Kvtool.IncludeAutomatedUpgrade {
|
|
fmt.Println("skipping upgrade test, kvtool automated upgrade is disabled")
|
|
suite.T().SkipNow()
|
|
}
|
|
|
|
// If there isn't a manual upgrade height set in the config, skip the test
|
|
if suite.config.LiveNetwork != nil && suite.config.LiveNetwork.UpgradeHeight == 0 {
|
|
fmt.Println("skipping upgrade test, live network upgrade height is not set")
|
|
suite.T().SkipNow()
|
|
}
|
|
}
|
|
|
|
// SkipIfKvtoolDisabled should be called at the start of tests that require kvtool.
|
|
func (suite *E2eTestSuite) SkipIfKvtoolDisabled() {
|
|
if suite.config.Kvtool == nil {
|
|
suite.T().SkipNow()
|
|
}
|
|
}
|
|
|
|
// BigIntsEqual is a helper method for comparing the equality of two big ints
|
|
func (suite *E2eTestSuite) BigIntsEqual(expected *big.Int, actual *big.Int, msg string) {
|
|
suite.Truef(expected.Cmp(actual) == 0, "%s (expected: %s, actual: %s)", msg, expected.String(), actual.String())
|
|
}
|