From 6dee74f2c377af7534a358ebbe45d53bc02ea724 Mon Sep 17 00:00:00 2001 From: Maru Newby Date: Tue, 30 Jul 2024 18:17:40 -0700 Subject: [PATCH] [e2e] Enhance post-test bootstrap checks - bootstrap all subnets (a request for hypersdk) - enable post-bootstrap interaction with the node by returning it from the check function and ensuring the node is only stopped at the end of the test (a request for hypersdk) - add bootstrap check to xsvm e2e --- tests/e2e/c/dynamic_fees.go | 2 +- tests/e2e/c/interchain_workflow.go | 2 +- tests/e2e/p/interchain_workflow.go | 2 +- tests/e2e/p/staking_rewards.go | 2 +- tests/e2e/p/validator_sets.go | 2 +- tests/e2e/vms/xsvm.go | 2 ++ tests/e2e/x/interchain_workflow.go | 2 +- tests/fixture/e2e/helpers.go | 39 ++++++++++++++++++++---------- tests/upgrade/upgrade_test.go | 2 +- 9 files changed, 35 insertions(+), 20 deletions(-) diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index c3dda77b985c..a632f57aaad1 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -162,6 +162,6 @@ var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { _ = e2e.SendEthTransaction(ethClient, signedTx) }) - e2e.CheckBootstrapIsPossible(privateNetwork) + _ = e2e.CheckBootstrapIsPossible(privateNetwork, ginkgo.DeferCleanup) }) }) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index bfb342818a5f..3984bd20b7a4 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -163,6 +163,6 @@ var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { require.Positive(balances[avaxAssetID]) }) - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + _ = e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork(), ginkgo.DeferCleanup) }) }) diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index 548c82ac1211..262c4106b66d 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -216,6 +216,6 @@ var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainL ginkgo.By("stopping validator node to free up resources for a bootstrap check") require.NoError(node.Stop(e2e.DefaultContext())) - e2e.CheckBootstrapIsPossible(network) + _ = e2e.CheckBootstrapIsPossible(network, ginkgo.DeferCleanup) }) }) diff --git a/tests/e2e/p/staking_rewards.go b/tests/e2e/p/staking_rewards.go index e988cf43c2c4..4f8e83545f4a 100644 --- a/tests/e2e/p/staking_rewards.go +++ b/tests/e2e/p/staking_rewards.go @@ -305,6 +305,6 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() { ginkgo.By("stopping alpha to free up resources for a bootstrap check") require.NoError(alphaNode.Stop(e2e.DefaultContext())) - e2e.CheckBootstrapIsPossible(network) + _ = e2e.CheckBootstrapIsPossible(network, ginkgo.DeferCleanup) }) }) diff --git a/tests/e2e/p/validator_sets.go b/tests/e2e/p/validator_sets.go index a3f3e1e9f075..2fd1cfffda52 100644 --- a/tests/e2e/p/validator_sets.go +++ b/tests/e2e/p/validator_sets.go @@ -111,6 +111,6 @@ var _ = e2e.DescribePChain("[Validator Sets]", func() { } }) - e2e.CheckBootstrapIsPossible(network) + _ = e2e.CheckBootstrapIsPossible(network, ginkgo.DeferCleanup) }) }) diff --git a/tests/e2e/vms/xsvm.go b/tests/e2e/vms/xsvm.go index 5d3557acd405..cfcea19217b3 100644 --- a/tests/e2e/vms/xsvm.go +++ b/tests/e2e/vms/xsvm.go @@ -160,6 +160,8 @@ var _ = ginkgo.Describe("[XSVM]", func() { destinationBalance, err := destinationClient.Balance(e2e.DefaultContext(), destinationKey.Address(), sourceChain.ChainID) require.NoError(err) require.Equal(units.Schmeckle, destinationBalance) + + _ = e2e.CheckBootstrapIsPossible(network, ginkgo.DeferCleanup) }) }) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index ecc52f41f032..f8edaefbadf9 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -151,6 +151,6 @@ var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainL require.Positive(balances[avaxAssetID]) }) - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + _ = e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork(), ginkgo.DeferCleanup) }) }) diff --git a/tests/fixture/e2e/helpers.go b/tests/fixture/e2e/helpers.go index 6f6e5382dc7a..d0114d2d7fea 100644 --- a/tests/fixture/e2e/helpers.go +++ b/tests/fixture/e2e/helpers.go @@ -17,6 +17,7 @@ import ( "github.com/ava-labs/coreth/interfaces" "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" "github.com/ava-labs/avalanchego/tests/fixture/tmpnet" @@ -53,6 +54,11 @@ const ( PrivateNetworksDirName = "private_networks" ) +// RegisterCleanupFunc is a function that registers a function intended to be called at +// the end of a given test. A function that accepts this type can avoid a direct +// dependency on ginkgo's DeferCleanup function. +type RegisterCleanupFunc func(args ...interface{}) + // Create a new wallet for the provided keychain against the specified node URI. func NewWallet(keychain *secp256k1fx.Keychain, nodeURI tmpnet.NodeURI) primary.Wallet { tests.Outf("{{blue}} initializing a new wallet for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) @@ -185,34 +191,41 @@ func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { return common.WithBaseFee(baseFee) } -// Verify that a new node can bootstrap into the network. This function is safe to call -// from `Teardown` by virtue of not depending on ginkgo.DeferCleanup. -func CheckBootstrapIsPossible(network *tmpnet.Network) { +// Verify that a new node can bootstrap into the network. If the check wasn't skipped, +// the node will be returned to the caller. +func CheckBootstrapIsPossible(network *tmpnet.Network, registerCleanup RegisterCleanupFunc) *tmpnet.Node { require := require.New(ginkgo.GinkgoT()) if len(os.Getenv(SkipBootstrapChecksEnvName)) > 0 { tests.Outf("{{yellow}}Skipping bootstrap check due to the %s env var being set", SkipBootstrapChecksEnvName) - return + return nil } ginkgo.By("checking if bootstrap is possible with the current network state") - ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout) - defer cancel() + // Ensure all subnets are bootstrapped + subnetIDs := make([]string, len(network.Subnets)) + for i, subnet := range network.Subnets { + subnetIDs[i] = subnet.SubnetID.String() + } + flags := tmpnet.FlagsMap{ + config.TrackSubnetsKey: strings.Join(subnetIDs, ","), + } - node := tmpnet.NewEphemeralNode(tmpnet.FlagsMap{}) - require.NoError(network.StartNode(ctx, ginkgo.GinkgoWriter, node)) + node := tmpnet.NewEphemeralNode(flags) + require.NoError(network.StartNode(DefaultContext(), ginkgo.GinkgoWriter, node)) // StartNode will initiate node stop if an error is encountered during start, // so no further cleanup effort is required if an error is seen here. - // Ensure the node is always stopped at the end of the check - defer func() { - ctx, cancel = context.WithTimeout(context.Background(), DefaultTimeout) + // Register a cleanup to ensure the node is stopped after the check + registerCleanup(func() { + ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout) defer cancel() require.NoError(node.Stop(ctx)) - }() + }) // Check that the node becomes healthy within timeout - require.NoError(tmpnet.WaitForHealthy(ctx, node)) + require.NoError(tmpnet.WaitForHealthy(DefaultContext(), node)) + return node } // Start a temporary network with the provided avalanchego binary. diff --git a/tests/upgrade/upgrade_test.go b/tests/upgrade/upgrade_test.go index c885a0821b8c..57aafcc5359c 100644 --- a/tests/upgrade/upgrade_test.go +++ b/tests/upgrade/upgrade_test.go @@ -59,6 +59,6 @@ var _ = ginkgo.Describe("[Upgrade]", func() { e2e.WaitForHealthy(node) } - e2e.CheckBootstrapIsPossible(network) + _ = e2e.CheckBootstrapIsPossible(network, ginkgo.DeferCleanup) }) })