package testutil import ( "fmt" "os" "strconv" "github.com/subosito/gotenv" ) func init() { // read the .env file, if present gotenv.Load() } // SuiteConfig wraps configuration details for running the end-to-end test suite. type SuiteConfig struct { // A funded account used to fnd all other accounts. FundedAccountMnemonic string // A config for using kvtool local networks for the test run Kvtool *KvtoolConfig // A config for connecting to a running network LiveNetwork *LiveNetworkConfig // Whether or not to start an IBC chain. Use `suite.SkipIfIbcDisabled()` in IBC tests in IBC tests. IncludeIbcTests bool // The contract address of a deployed ERC-20 token ZgchainERC20Address string // When true, the chains will remain running after tests complete (pass or fail) SkipShutdown bool } // KvtoolConfig wraps configuration options for running the end-to-end test suite against // a locally running chain. This config must be defined if E2E_RUN_KVTOOL_NETWORKS is true. type KvtoolConfig struct { // The 0gchain.configTemplate flag to be passed to kvtool, usually "master". // This allows one to change the base genesis used to start the chain. ZgChainConfigTemplate string // Whether or not to run a chain upgrade & run post-upgrade tests. Use `suite.SkipIfUpgradeDisabled()` in post-upgrade tests. IncludeAutomatedUpgrade bool // Name of the upgrade, if upgrade is enabled. ZgChainUpgradeName string // Height upgrade will be applied to the test chain, if upgrade is enabled. ZgChainUpgradeHeight int64 // Tag of 0gchain docker image that will be upgraded to the current image before tests are run, if upgrade is enabled. ZgChainUpgradeBaseImageTag string } // LiveNetworkConfig wraps configuration options for running the end-to-end test suite // against a live network. It must be defined if E2E_RUN_KVTOOL_NETWORKS is false. type LiveNetworkConfig struct { ZgChainRpcUrl string ZgChainGrpcUrl string ZgChainEvmRpcUrl string UpgradeHeight int64 } // ParseSuiteConfig builds a SuiteConfig from environment variables. func ParseSuiteConfig() SuiteConfig { config := SuiteConfig{ // this mnemonic is expected to be a funded account that can seed the funds for all // new accounts created during tests. it will be available under Accounts["whale"] FundedAccountMnemonic: nonemptyStringEnv("E2E_0GCHAIN_FUNDED_ACCOUNT_MNEMONIC"), ZgchainERC20Address: nonemptyStringEnv("E2E_0GCHAIN_ERC20_ADDRESS"), IncludeIbcTests: mustParseBool("E2E_INCLUDE_IBC_TESTS"), } skipShutdownEnv := os.Getenv("E2E_SKIP_SHUTDOWN") if skipShutdownEnv != "" { config.SkipShutdown = mustParseBool("E2E_SKIP_SHUTDOWN") } useKvtoolNetworks := mustParseBool("E2E_RUN_KVTOOL_NETWORKS") if useKvtoolNetworks { kvtoolConfig := ParseKvtoolConfig() config.Kvtool = &kvtoolConfig } else { liveNetworkConfig := ParseLiveNetworkConfig() config.LiveNetwork = &liveNetworkConfig } return config } // ParseKvtoolConfig builds a KvtoolConfig from environment variables. func ParseKvtoolConfig() KvtoolConfig { config := KvtoolConfig{ ZgChainConfigTemplate: nonemptyStringEnv("E2E_KVTOOL_0GCHAIN_CONFIG_TEMPLATE"), IncludeAutomatedUpgrade: mustParseBool("E2E_INCLUDE_AUTOMATED_UPGRADE"), } if config.IncludeAutomatedUpgrade { config.ZgChainUpgradeName = nonemptyStringEnv("E2E_0GCHAIN_UPGRADE_NAME") config.ZgChainUpgradeBaseImageTag = nonemptyStringEnv("E2E_0GCHAIN_UPGRADE_BASE_IMAGE_TAG") upgradeHeight, err := strconv.ParseInt(nonemptyStringEnv("E2E_0GCHAIN_UPGRADE_HEIGHT"), 10, 64) if err != nil { panic(fmt.Sprintf("E2E_0GCHAIN_UPGRADE_HEIGHT must be a number: %s", err)) } config.ZgChainUpgradeHeight = upgradeHeight } return config } // ParseLiveNetworkConfig builds a LiveNetworkConfig from environment variables. func ParseLiveNetworkConfig() LiveNetworkConfig { config := LiveNetworkConfig{ ZgChainRpcUrl: nonemptyStringEnv("E2E_0GCHAIN_RPC_URL"), ZgChainGrpcUrl: nonemptyStringEnv("E2E_0GCHAIN_GRPC_URL"), ZgChainEvmRpcUrl: nonemptyStringEnv("E2E_0GCHAIN_EVM_RPC_URL"), } upgradeHeight := os.Getenv("E2E_0GCHAIN_UPGRADE_HEIGHT") if upgradeHeight != "" { parsedHeight, err := strconv.ParseInt(upgradeHeight, 10, 64) if err != nil { panic(fmt.Sprintf("E2E_0GCHAIN_UPGRADE_HEIGHT must be a number: %s", err)) } config.UpgradeHeight = parsedHeight } return config } // mustParseBool is a helper method that panics if the env variable `name` // cannot be parsed to a boolean func mustParseBool(name string) bool { envValue := os.Getenv(name) if envValue == "" { panic(fmt.Sprintf("%s is unset but expected a bool", name)) } value, err := strconv.ParseBool(envValue) if err != nil { panic(fmt.Sprintf("%s (%s) cannot be parsed to a bool: %s", name, envValue, err)) } return value } // nonemptyStringEnv is a helper method that panics if the env variable `name` // is empty or undefined. func nonemptyStringEnv(name string) string { value := os.Getenv(name) if value == "" { panic(fmt.Sprintf("no %s env variable provided", name)) } return value }