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

test(e2e): enable emissions pool in local e2e testing #1870

Merged
merged 10 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
* [1791](https://github.com/zeta-chain/node/pull/1791) - add e2e tests for feature of restricted address
* [1787](https://github.com/zeta-chain/node/pull/1787) - add unit tests for cross-chain evm hooks and e2e test failed withdraw to BTC legacy address
* [1840](https://github.com/zeta-chain/node/pull/1840) - fix code coverage test failures ignored in CI
* [1870](https://github.com/zeta-chain/node/pull/1870) - enable emissions pool in local e2e testing
* [1868](https://github.com/zeta-chain/node/pull/1868) - run e2e btc tests locally
* [1851](https://github.com/zeta-chain/node/pull/1851) - rename usdt to erc20 in e2e tests
* [1872](https://github.com/zeta-chain/node/pull/1872) - remove usage of RPC in unit test
Expand Down
100 changes: 35 additions & 65 deletions cmd/zetae2e/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,71 +44,19 @@ func NewLocalCmd() *cobra.Command {
Short: "Run Local E2E tests",
Run: localE2ETest,
}
cmd.Flags().Bool(
flagContractsDeployed,
false,
"set to to true if running tests again with existing state",
)
cmd.Flags().Int64(
flagWaitForHeight,
0,
"block height for tests to begin, ex. --wait-for 100",
)
cmd.Flags().String(
FlagConfigFile,
"",
"config file to use for the tests",
)
cmd.Flags().String(
flagConfigOut,
"",
"config file to write the deployed contracts from the setup",
)
cmd.Flags().Bool(
flagVerbose,
false,
"set to true to enable verbose logging",
)
cmd.Flags().Bool(
flagTestAdmin,
false,
"set to true to run admin tests",
)
cmd.Flags().Bool(
flagTestPerformance,
false,
"set to true to run performance tests",
)
cmd.Flags().Bool(
flagTestCustom,
false,
"set to true to run custom tests",
)
cmd.Flags().Bool(
flagSkipRegular,
false,
"set to true to skip regular tests",
)
cmd.Flags().Bool(
flagLight,
false,
"run the most basic regular tests, useful for quick checks",
)
cmd.Flags().Bool(
flagSetupOnly,
false,
"set to true to only setup the networks",
)
cmd.Flags().Bool(
flagSkipSetup,
false,
"set to true to skip setup",
)
cmd.Flags().Bool(
flagSkipBitcoinSetup,
false,
"set to true to skip bitcoin wallet setup",
)
cmd.Flags().Bool(flagContractsDeployed, false, "set to to true if running tests again with existing state")
cmd.Flags().Int64(flagWaitForHeight, 0, "block height for tests to begin, ex. --wait-for 100")
cmd.Flags().String(FlagConfigFile, "", "config file to use for the tests")
cmd.Flags().Bool(flagVerbose, false, "set to true to enable verbose logging")
cmd.Flags().Bool(flagTestAdmin, false, "set to true to run admin tests")
cmd.Flags().Bool(flagTestPerformance, false, "set to true to run performance tests")
cmd.Flags().Bool(flagTestCustom, false, "set to true to run custom tests")
cmd.Flags().Bool(flagSkipRegular, false, "set to true to skip regular tests")
cmd.Flags().Bool(flagLight, false, "run the most basic regular tests, useful for quick checks")
cmd.Flags().Bool(flagSetupOnly, false, "set to true to only setup the networks")
cmd.Flags().String(flagConfigOut, "", "config file to write the deployed contracts from the setup")
cmd.Flags().Bool(flagSkipSetup, false, "set to true to skip setup")
cmd.Flags().Bool(flagSkipBitcoinSetup, false, "set to true to skip bitcoin wallet setup")

return cmd
}
Expand Down Expand Up @@ -242,7 +190,16 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
startTime := time.Now()
deployerRunner.SetupEVM(contractsDeployed)
deployerRunner.SetZEVMContracts()

// NOTE: this method return an error so we handle it and panic if it occurs unlike other method that panics directly
// TODO: all methods should return errors instead of panicking and this current function should also return an error
// https://github.com/zeta-chain/node/issues/1500
if err := deployerRunner.FundEmissionsPool(); err != nil {
panic(err)
}

deployerRunner.MintERC20OnEvm(10000)

logger.Print("✅ setup completed in %s", time.Since(startTime))
}

Expand Down Expand Up @@ -346,4 +303,17 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
}

logger.Print("✅ e2e tests completed in %s", time.Since(testStartTime).String())

// print and validate report
networkReport, err := deployerRunner.GenerateNetworkReport()
if err != nil {
logger.Print("❌ failed to generate network report %v", err)
}
deployerRunner.PrintNetworkReport(networkReport)
if err := networkReport.Validate(); err != nil {
logger.Print("❌ network report validation failed %v", err)
os.Exit(1)
}

os.Exit(0)
}
105 changes: 105 additions & 0 deletions e2e/runner/e2etest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package runner

import "fmt"

// E2ETestFunc is a function representing a E2E test
// It takes a E2ERunner as an argument
type E2ETestFunc func(*E2ERunner, []string)

// E2ETest represents a E2E test with a name, args, description and test func
type E2ETest struct {
Name string
Description string
Args []string
ArgsDefinition []ArgDefinition
E2ETest E2ETestFunc
}

// NewE2ETest creates a new instance of E2ETest with specified parameters.
func NewE2ETest(name, description string, argsDefinition []ArgDefinition, e2eTestFunc E2ETestFunc) E2ETest {
return E2ETest{
Name: name,
Description: description,
ArgsDefinition: argsDefinition,
E2ETest: e2eTestFunc,
Args: []string{},
}
}

// ArgDefinition defines a structure for holding an argument's description along with it's default value.
type ArgDefinition struct {
Description string
DefaultValue string
}

// DefaultArgs extracts and returns array of default arguments from the ArgsDefinition.
func (e E2ETest) DefaultArgs() []string {
defaultArgs := make([]string, len(e.ArgsDefinition))
for i, spec := range e.ArgsDefinition {
defaultArgs[i] = spec.DefaultValue
}
return defaultArgs
}

// ArgsDescription returns a string representing the arguments description in a readable format.
func (e E2ETest) ArgsDescription() string {
argsDescription := ""
for _, def := range e.ArgsDefinition {
argDesc := fmt.Sprintf("%s (%s)", def.Description, def.DefaultValue)
if argsDescription != "" {
argsDescription += ", "
}
argsDescription += argDesc
}
return argsDescription
}

// E2ETestRunConfig defines the basic configuration for initiating an E2E test, including its name and optional runtime arguments.
type E2ETestRunConfig struct {
Name string
Args []string
}

// GetE2ETestsToRunByName prepares a list of E2ETests to run based on given test names without arguments
func (runner *E2ERunner) GetE2ETestsToRunByName(availableTests []E2ETest, testNames ...string) ([]E2ETest, error) {
tests := []E2ETestRunConfig{}
for _, testName := range testNames {
tests = append(tests, E2ETestRunConfig{
Name: testName,
Args: []string{},
})
}
return runner.GetE2ETestsToRunByConfig(availableTests, tests)
}

// GetE2ETestsToRunByConfig prepares a list of E2ETests to run based on provided test names and their corresponding arguments
func (runner *E2ERunner) GetE2ETestsToRunByConfig(availableTests []E2ETest, testConfigs []E2ETestRunConfig) ([]E2ETest, error) {
tests := []E2ETest{}
for _, testSpec := range testConfigs {
e2eTest, found := findE2ETestByName(availableTests, testSpec.Name)
if !found {
return nil, fmt.Errorf("e2e test %s not found", testSpec.Name)
}
e2eTestToRun := NewE2ETest(
e2eTest.Name,
e2eTest.Description,
e2eTest.ArgsDefinition,
e2eTest.E2ETest,
)
// update e2e test args
e2eTestToRun.Args = testSpec.Args
tests = append(tests, e2eTestToRun)
}

return tests, nil
}

// findE2ETest finds a e2e test by name
func findE2ETestByName(e2eTests []E2ETest, e2eTestName string) (E2ETest, bool) {
for _, test := range e2eTests {
if test.Name == e2eTestName {
return test, true
}
}
return E2ETest{}, false
}
76 changes: 75 additions & 1 deletion e2e/runner/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ import (
"strings"
"text/tabwriter"
"time"

sdkmath "cosmossdk.io/math"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/zeta-chain/zetacore/cmd/zetacored/config"
"github.com/zeta-chain/zetacore/e2e/txserver"
crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types"
)

// TestReport is a struct that contains the test report
// TestReport is a struct that contains the report for a specific e2e test
// It can be generated with the RunE2ETestsIntoReport method
type TestReport struct {
Name string
Success bool
Expand Down Expand Up @@ -53,3 +60,70 @@ func (runner *E2ERunner) PrintTestReports(tr TestReports) {
}
runner.Logger.PrintNoPrefix(table)
}

// NetworkReport is a struct that contains the report for the network used after running e2e tests
// This report has been initialized to check the emissions pool balance and if the pool is decreasing
// TODO: add more complete data and validation to the network
// https://github.com/zeta-chain/node/issues/1873
type NetworkReport struct {
EmissionsPoolBalance sdkmath.Int
Height uint64
CctxCount int
}

// Validate validates the network report
// This method is used to validate the network after running e2e tests
// It checks the emissions pool balance and if the pool is decreasing
func (nr NetworkReport) Validate() error {
if nr.EmissionsPoolBalance.GTE(sdkmath.NewIntFromBigInt(EmissionsPoolFunding)) {
return fmt.Errorf(
"emissions pool balance is not decreasing, expected less than %s, got %s",
EmissionsPoolFunding,
nr.EmissionsPoolBalance,
)
}
return nil
}

// GenerateNetworkReport generates a report for the network used after running e2e tests
func (runner *E2ERunner) GenerateNetworkReport() (NetworkReport, error) {
// get the emissions pool balance
balanceRes, err := runner.BankClient.Balance(runner.Ctx, &banktypes.QueryBalanceRequest{
Address: txserver.EmissionsPoolAddress,
Denom: config.BaseDenom,
})
if err != nil {
return NetworkReport{}, err
}
emissionsPoolBalance := balanceRes.Balance

// fetch the height and number of cctxs, this gives a better idea on the activity of the network

// get the block height
blockRes, err := runner.ZEVMClient.BlockNumber(runner.Ctx)
if err != nil {
return NetworkReport{}, err
}

// get the number of cctxs
cctxsRes, err := runner.CctxClient.CctxAll(runner.Ctx, &crosschaintypes.QueryAllCctxRequest{})
if err != nil {
return NetworkReport{}, err
}
cctxCount := len(cctxsRes.CrossChainTx)

return NetworkReport{
EmissionsPoolBalance: emissionsPoolBalance.Amount,
Height: blockRes,
CctxCount: cctxCount,
}, nil
}

// PrintNetworkReport prints the network report
func (runner *E2ERunner) PrintNetworkReport(nr NetworkReport) {
runner.Logger.Print(" ---📈 Network Report ---")
runner.Logger.Print("Block Height: %d", nr.Height)
runner.Logger.Print("CCTX Processed: %d", nr.CctxCount)
runner.Logger.Print("Emissions Pool Balance: %sZETA", nr.EmissionsPoolBalance.Quo(sdkmath.NewIntFromUint64(1e18)))

}
Loading
Loading