diff --git a/cmd/zetae2e/run.go b/cmd/zetae2e/run.go index 954dfd9661..fe83b4f874 100644 --- a/cmd/zetae2e/run.go +++ b/cmd/zetae2e/run.go @@ -3,6 +3,7 @@ package main import ( "context" "errors" + "strings" "time" ethcommon "github.com/ethereum/go-ethereum/common" @@ -23,12 +24,21 @@ const FungibleAdminMnemonic = "snow grace federal cupboard arrive fancy gym lady // NewRunCmd returns the run command // which runs the E2E from a config file describing the tests, networks, and accounts func NewRunCmd() *cobra.Command { + var configFile string + cmd := &cobra.Command{ - Use: "run [config-file]", - Short: "Run E2E tests from a config file", - RunE: runE2ETest, - Args: cobra.ExactArgs(1), + Use: "run [testname1]:[arg1],[arg2] [testname2]:[arg1],[arg2]...", + Short: "Run one or more E2E tests with optional arguments", + Long: `Run one or more E2E tests specified by their names and optional arguments. +For example: zetae2e run deposit:1000 withdraw: --config confuing.yml`, + RunE: runE2ETest, + Args: cobra.MinimumNArgs(1), // Ensures at least one test is provided } + + cmd.Flags().StringVarP(&configFile, "config", "c", "", "path to the configuration file") + cmd.MarkFlagRequired("config") + + // Retain the verbose flag cmd.Flags().Bool( flagVerbose, false, @@ -40,7 +50,11 @@ func NewRunCmd() *cobra.Command { func runE2ETest(cmd *cobra.Command, args []string) error { // read the config file - conf, err := config.ReadConfig(args[0]) + configPath, err := cmd.Flags().GetString("config") + if err != nil { + return err + } + conf, err := config.ReadConfig(configPath) if err != nil { return err } @@ -67,6 +81,18 @@ func runE2ETest(cmd *cobra.Command, args []string) error { return errors.New("invalid EVM address") } + // parse test names and arguments + testList := []runner.E2ETest{} + for _, arg := range args { + parts := strings.SplitN(arg, ":", 2) + testName := parts[0] + var testArgs []string + if len(parts) > 1 && parts[1] != "" { + testArgs = strings.Split(parts[1], ",") + } + testList = append(testList, runner.E2ETest{Name: testName, Args: testArgs}) + } + // initialize deployer runner with config testRunner, err := zetae2econfig.RunnerFromConfig( ctx, @@ -105,7 +131,7 @@ func runE2ETest(cmd *cobra.Command, args []string) error { //run tests reports, err := testRunner.RunE2ETestsFromNamesIntoReport( e2etests.AllE2ETests, - conf.TestList..., + testList, ) if err != nil { cancel() diff --git a/e2e/e2etests/e2etests.go b/e2e/e2etests/e2etests.go index 6fc0c4a56a..275353f8de 100644 --- a/e2e/e2etests/e2etests.go +++ b/e2e/e2etests/e2etests.go @@ -45,174 +45,203 @@ const ( var AllE2ETests = []runner.E2ETest{ { TestContextUpgradeName, + []string{}, "tests sending ETH on ZEVM and check context data using ContextApp", "", TestContextUpgrade, }, { TestDepositAndCallRefundName, + []string{}, "deposit ZRC20 into ZEVM and call a contract that reverts; should refund", "", TestDepositAndCallRefund, }, { TestMultipleERC20DepositName, + []string{}, "deposit USDT ERC20 into ZEVM in multiple deposits", "", TestMultipleERC20Deposit, }, { TestERC20WithdrawName, + []string{}, "withdraw ERC20 from ZEVM", "", TestERC20Withdraw, }, { TestMultipleWithdrawsName, + []string{}, "withdraw ERC20 from ZEVM in multiple deposits", "", TestMultipleWithdraws, }, { TestZetaWithdrawName, + []string{}, "withdraw ZETA from ZEVM to Ethereum", "", TestZetaWithdraw, }, { TestZetaDepositName, + []string{}, "deposit ZETA from Ethereum to ZEVM", "", TestZetaDeposit, }, { TestZetaWithdrawBTCRevertName, + []string{}, "sending ZETA from ZEVM to Bitcoin with a message that should revert cctxs", "", TestZetaWithdrawBTCRevert, }, { TestMessagePassingName, + []string{}, "goerli->goerli message passing (sending ZETA only)", "", TestMessagePassing, }, { TestZRC20SwapName, + []string{}, "swap ZRC20 USDT for ZRC20 ETH", "", TestZRC20Swap, }, { TestBitcoinWithdrawName, + []string{}, "withdraw BTC from ZEVM", "", TestBitcoinWithdraw, }, { TestCrosschainSwapName, + []string{}, "testing Bitcoin ERC20 cross-chain swap", "", TestCrosschainSwap, }, { TestMessagePassingRevertFailName, + []string{}, "goerli->goerli message passing (revert fail)", "", TestMessagePassingRevertFail, }, { TestMessagePassingRevertSuccessName, + []string{}, "goerli->goerli message passing (revert success)", "", TestMessagePassingRevertSuccess, }, { TestPauseZRC20Name, + []string{}, "pausing ZRC20 on ZetaChain", "", TestPauseZRC20, }, { TestERC20DepositAndCallRefundName, + []string{}, "deposit a non-gas ZRC20 into ZEVM and call a contract that reverts", "", TestERC20DepositAndCallRefund, }, { TestUpdateBytecodeName, + []string{}, "update ZRC20 bytecode swap", "", TestUpdateBytecode, }, { TestEtherDepositAndCallName, + []string{}, "deposit ZRC20 into ZEVM and call a contract", "", TestEtherDepositAndCall, }, { TestDepositEtherLiquidityCapName, + []string{}, "deposit Ethers into ZEVM with a liquidity cap", "", TestDepositEtherLiquidityCap, }, { TestMyTestName, + []string{}, "performing custom test", "", TestMyTest, }, { TestERC20DepositName, + []string{}, "deposit ERC20 into ZEVM", "", TestERC20Deposit, }, { TestEtherDepositName, + []string{}, "deposit Ether into ZEVM", "amount in wei (default 0.01ETH)", TestEtherDeposit, }, { TestEtherWithdrawName, + []string{}, "withdraw Ether from ZEVM", "", TestEtherWithdraw, }, { TestBitcoinDepositName, + []string{}, "deposit Bitcoin into ZEVM", "", TestBitcoinDeposit, }, { TestDonationEtherName, + []string{}, "donate Ether to the TSS", "", TestDonationEther, }, { TestStressEtherWithdrawName, + []string{}, "stress test Ether withdrawal", "", TestStressEtherWithdraw, }, { TestStressBTCWithdrawName, + []string{}, "stress test BTC withdrawal", "", TestStressBTCWithdraw, }, { TestStressEtherDepositName, + []string{}, "stress test Ether deposit", "", TestStressEtherDeposit, }, { TestStressBTCDepositName, + []string{}, "stress test BTC deposit", "", TestStressBTCDeposit, diff --git a/e2e/runner/runner.go b/e2e/runner/runner.go index 67bf9dfdf7..7dd0f84e6e 100644 --- a/e2e/runner/runner.go +++ b/e2e/runner/runner.go @@ -166,14 +166,15 @@ type E2ETestFunc func(*E2ERunner, []string) // E2ETest represents a E2E test with a name type E2ETest struct { Name string + Args []string // TODO: should args be here, probably there is a cleaner way Description string ArgumentsDescription string E2ETest E2ETestFunc } // RunE2ETestsFromNames runs a list of E2E tests by name in a list of e2e tests -func (runner *E2ERunner) RunE2ETestsFromNames(e2eTests []E2ETest, e2eTestNames ...string) error { - for _, e2eTestName := range e2eTestNames { +func (runner *E2ERunner) RunE2ETestsFromNames(e2eTests []E2ETest, e2eTestsToRun ...E2ETest) error { + for _, e2eTestName := range e2eTestsToRun { e2eTest, ok := findE2ETest(e2eTestName, e2eTests) if !ok { return fmt.Errorf("e2e test %s not found", e2eTestName) @@ -188,19 +189,18 @@ func (runner *E2ERunner) RunE2ETestsFromNames(e2eTests []E2ETest, e2eTestNames . // RunE2ETestsFromNamesIntoReport runs a list of e2e tests by name in a list of e2e tests and returns a report // The function doesn't return an error, it returns a report with the error -func (runner *E2ERunner) RunE2ETestsFromNamesIntoReport(e2eTests []E2ETest, e2eTestNames ...string) (TestReports, error) { +func (runner *E2ERunner) RunE2ETestsFromNamesIntoReport(e2eTests []E2ETest, e2eTestsToRun []E2ETest) (TestReports, error) { // get all tests so we can return an error if a test is not found - tests := make([]E2ETest, 0, len(e2eTestNames)) - for _, e2eTestName := range e2eTestNames { - e2eTest, ok := findE2ETest(e2eTestName, e2eTests) + tests := make([]E2ETest, 0, len(e2eTestsToRun)) + for _, e2eTestWithArgs := range e2eTestsToRun { + _, ok := findE2ETest(e2eTestWithArgs, e2eTests) if !ok { - return nil, fmt.Errorf("e2e test %s not found", e2eTestName) + return nil, fmt.Errorf("e2e test %s not found", e2eTestWithArgs.Name) } - tests = append(tests, e2eTest) } // go through all tests - reports := make(TestReports, 0, len(e2eTestNames)) + reports := make(TestReports, 0, len(e2eTestsToRun)) for _, test := range tests { // get info before test balancesBefore, err := runner.GetAccountBalances(true) @@ -238,18 +238,8 @@ func (runner *E2ERunner) RunE2ETestsFromNamesIntoReport(e2eTests []E2ETest, e2eT return reports, nil } -// RunE2ETests runs a list of e2e tests -func (runner *E2ERunner) RunE2ETests(e2eTests []E2ETest) (err error) { - for _, e2eTest := range e2eTests { - if err := runner.RunE2ETest(e2eTest, true); err != nil { - return err - } - } - return nil -} - // RunE2ETest runs a e2e test -func (runner *E2ERunner) RunE2ETest(e2eTestWithName E2ETest, checkAccounting bool) (err error) { +func (runner *E2ERunner) RunE2ETest(e2eTest E2ETest, checkAccounting bool) (err error) { // return an error on panic // https://github.com/zeta-chain/node/issues/1500 defer func() { @@ -257,15 +247,16 @@ func (runner *E2ERunner) RunE2ETest(e2eTestWithName E2ETest, checkAccounting boo // print stack trace stack := make([]byte, 4096) n := runtime.Stack(stack, false) - err = fmt.Errorf("%s failed: %v, stack trace %s", e2eTestWithName.Name, r, stack[:n]) + err = fmt.Errorf("%s failed: %v, stack trace %s", e2eTest.Name, r, stack[:n]) } }() startTime := time.Now() - runner.Logger.Print("⏳running - %s", e2eTestWithName.Description) + runner.Logger.Print("⏳running - %s", e2eTest.Description) // run e2e test - e2eTestWithName.E2ETest(runner, []string{}) + // TODO: E2ETest probably should not have Args directly, revisit + e2eTest.E2ETest(runner, e2eTest.Args) //check supplies if checkAccounting { @@ -274,15 +265,16 @@ func (runner *E2ERunner) RunE2ETest(e2eTestWithName E2ETest, checkAccounting boo } } - runner.Logger.Print("✅ completed in %s - %s", time.Since(startTime), e2eTestWithName.Description) + runner.Logger.Print("✅ completed in %s - %s", time.Since(startTime), e2eTest.Description) return err } // findE2ETest finds a e2e test by name -func findE2ETest(name string, e2eTests []E2ETest) (E2ETest, bool) { +func findE2ETest(e2eTest E2ETest, e2eTests []E2ETest) (E2ETest, bool) { for _, test := range e2eTests { - if test.Name == name { + if test.Name == e2eTest.Name { + test.Args = e2eTest.Args return test, true } }