Skip to content

Commit 0a41e56

Browse files
committed
testing: Switch upgrade test to the testnet fixture
1 parent de4910c commit 0a41e56

File tree

8 files changed

+77
-199
lines changed

8 files changed

+77
-199
lines changed

.github/workflows/test.upgrade.yml

+9-1
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,12 @@ jobs:
3030
run: ./scripts/build.sh
3131
- name: Run upgrade tests
3232
shell: bash
33-
run: scripts/tests.upgrade.sh 1.10.1 ./build/avalanchego
33+
# 1.10.7 is the first version compatible with the testnet fixture by
34+
# virtue of writing a process context file on node start.
35+
run: ./scripts/tests.upgrade.sh 1.10.7
36+
- name: Upload testnet network dir
37+
uses: actions/upload-artifact@v3
38+
if: always()
39+
with:
40+
name: testnet-data
41+
path: ~/.testnetctl/networks/1000

go.mod

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ require (
1111
github.com/DataDog/zstd v1.5.2
1212
github.com/Microsoft/go-winio v0.5.2
1313
github.com/NYTimes/gziphandler v1.1.1
14-
github.com/ava-labs/avalanche-network-runner-sdk v0.3.0
1514
github.com/ava-labs/coreth v0.12.5-rc.6
1615
github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7
1716
github.com/btcsuite/btcd/btcutil v1.1.3

go.sum

-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah
6161
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
6262
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
6363
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
64-
github.com/ava-labs/avalanche-network-runner-sdk v0.3.0 h1:TVi9JEdKNU/RevYZ9PyW4pULbEdS+KQDA9Ki2DUvuAs=
65-
github.com/ava-labs/avalanche-network-runner-sdk v0.3.0/go.mod h1:SgKJvtqvgo/Bl/c8fxEHCLaSxEbzimYfBopcfrajxQk=
6664
github.com/ava-labs/coreth v0.12.5-rc.6 h1:OajGUyKkO5Q82XSuMa8T5UD6QywtCHUiZ4Tv3RFmRBU=
6765
github.com/ava-labs/coreth v0.12.5-rc.6/go.mod h1:s5wVyy+5UCCk2m0Tq3jVmy0UqOpKBDYqRE13gInCJVs=
6866
github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c=

scripts/install_anr.sh

-34
This file was deleted.

scripts/tests.upgrade.sh

+7-42
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
set -euo pipefail
44

55
# e.g.,
6-
# ./scripts/build.sh
7-
# ./scripts/tests.upgrade.sh 1.7.16 ./build/avalanchego
6+
# ./scripts/tests.upgrade.sh 1.7.16
7+
# AVALANCHEGO_PATH=./path/to/avalanchego ./scripts/tests.upgrade.sh 1.7.16 # Customization of avalanchego path
88
if ! [[ "$0" =~ scripts/tests.upgrade.sh ]]; then
99
echo "must be run from repository root"
1010
exit 255
@@ -13,16 +13,11 @@ fi
1313
VERSION="${1:-}"
1414
if [[ -z "${VERSION}" ]]; then
1515
echo "Missing version argument!"
16-
echo "Usage: ${0} [VERSION] [NEW-BINARY]" >>/dev/stderr
16+
echo "Usage: ${0} [VERSION]" >>/dev/stderr
1717
exit 255
1818
fi
1919

20-
NEW_BINARY="${2:-}"
21-
if [[ -z "${NEW_BINARY}" ]]; then
22-
echo "Missing new binary path argument!"
23-
echo "Usage: ${0} [VERSION] [NEW-BINARY]" >>/dev/stderr
24-
exit 255
25-
fi
20+
AVALANCHEGO_PATH="$(realpath ${AVALANCHEGO_PATH:-./build/avalanchego})"
2621

2722
#################################
2823
# download avalanchego
@@ -52,11 +47,6 @@ elif [[ ${GOOS} == "darwin" ]]; then
5247
fi
5348
find /tmp/avalanchego-v${VERSION}
5449

55-
#################################
56-
echo "installing avalanche-network-runner"
57-
ANR_WORKDIR="/tmp"
58-
./scripts/install_anr.sh
59-
6050
# Sourcing constants.sh ensures that the necessary CGO flags are set to
6151
# build the portable version of BLST. Without this, ginkgo may fail to
6252
# build the test binary if run on a host (e.g. github worker) that lacks
@@ -70,35 +60,10 @@ go install -v github.com/onsi/ginkgo/v2/ginkgo@v2.1.4
7060
ACK_GINKGO_RC=true ginkgo build ./tests/upgrade
7161
./tests/upgrade/upgrade.test --help
7262

73-
#################################
74-
# run "avalanche-network-runner" server
75-
echo "launch avalanche-network-runner in the background"
76-
$ANR_WORKDIR/avalanche-network-runner \
77-
server \
78-
--log-level debug \
79-
--port=":12340" \
80-
--disable-grpc-gateway &
81-
PID=${!}
82-
8363
#################################
8464
# By default, it runs all upgrade test cases!
85-
echo "running upgrade tests against the local cluster with ${NEW_BINARY}"
65+
echo "running upgrade tests against the local cluster with ${AVALANCHEGO_PATH}"
8666
./tests/upgrade/upgrade.test \
8767
--ginkgo.v \
88-
--log-level debug \
89-
--network-runner-grpc-endpoint="0.0.0.0:12340" \
90-
--network-runner-avalanchego-path=/tmp/avalanchego-v${VERSION}/avalanchego \
91-
--network-runner-avalanchego-path-to-upgrade=${NEW_BINARY} \
92-
--network-runner-avalanchego-log-level="WARN" || EXIT_CODE=$?
93-
94-
# "e2e.test" already terminates the cluster
95-
# just in case tests are aborted, manually terminate them again
96-
pkill -P ${PID} || true
97-
kill -2 ${PID}
98-
99-
if [[ "${EXIT_CODE:-}" -gt 0 ]]; then
100-
echo "FAILURE with exit code ${EXIT_CODE}"
101-
exit ${EXIT_CODE}
102-
else
103-
echo "ALL SUCCESS!"
104-
fi
68+
--avalanchego-path=/tmp/avalanchego-v${VERSION}/avalanchego \
69+
--avalanchego-path-to-upgrade-to=${AVALANCHEGO_PATH}

tests/e2e/e2e.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,7 @@ func AddEphemeralNode(network testnet.Network, flags testnet.FlagsMap) testnet.N
228228

229229
// Wait for the given node to report healthy.
230230
func WaitForHealthy(node testnet.Node) {
231-
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
232-
defer cancel()
233-
require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(ctx, node))
231+
require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node))
234232
}
235233

236234
// Sends an eth transaction, waits for the transaction receipt to be issued

tests/fixture/testnet/local/network.go

+20-11
Original file line numberDiff line numberDiff line change
@@ -658,20 +658,33 @@ func (ln *LocalNetwork) AddLocalNode(w io.Writer, node *LocalNode, isEphemeral b
658658
return nil, err
659659
}
660660

661-
// Collect staking addresses of running nodes for use in bootstraping the new node
662-
if err := ln.ReadNodes(); err != nil {
663-
return nil, fmt.Errorf("failed to read local network nodes: %w", err)
661+
bootstrapIPs, bootstrapIDs, err := ln.GetBootstrapIPsAndIds()
662+
if err != nil {
663+
return nil, err
664664
}
665665

666666
var (
667667
// Use dynamic port allocation.
668668
httpPort uint16 = 0
669669
stakingPort uint16 = 0
670+
)
671+
node.SetNetworkingConfigDefaults(httpPort, stakingPort, bootstrapIDs, bootstrapIPs)
672+
673+
if err := node.WriteConfig(); err != nil {
674+
return nil, err
675+
}
676+
return node, node.Start(w, ln.ExecPath)
677+
}
670678

679+
func (ln *LocalNetwork) GetBootstrapIPsAndIds() ([]string, []string, error) {
680+
// Collect staking addresses of running nodes for use in bootstrapping a node
681+
if err := ln.ReadNodes(); err != nil {
682+
return nil, nil, fmt.Errorf("failed to read local network nodes: %w", err)
683+
}
684+
var (
671685
bootstrapIPs = make([]string, 0, len(ln.Nodes))
672686
bootstrapIDs = make([]string, 0, len(ln.Nodes))
673687
)
674-
675688
for _, node := range ln.Nodes {
676689
if len(node.StakingAddress) == 0 {
677690
// Node is not running
@@ -681,14 +694,10 @@ func (ln *LocalNetwork) AddLocalNode(w io.Writer, node *LocalNode, isEphemeral b
681694
bootstrapIPs = append(bootstrapIPs, node.StakingAddress)
682695
bootstrapIDs = append(bootstrapIDs, node.NodeID.String())
683696
}
697+
684698
if len(bootstrapIDs) == 0 {
685-
return nil, errMissingBootstrapNodes
699+
return nil, nil, errMissingBootstrapNodes
686700
}
687701

688-
node.SetNetworkingConfigDefaults(httpPort, stakingPort, bootstrapIDs, bootstrapIPs)
689-
690-
if err := node.WriteConfig(); err != nil {
691-
return nil, err
692-
}
693-
return node, node.Start(w, ln.ExecPath)
702+
return bootstrapIPs, bootstrapIDs, nil
694703
}

tests/upgrade/upgrade_test.go

+40-105
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,78 @@
11
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
22
// See the file LICENSE for licensing terms.
33

4-
// Runs upgrade tests.
5-
package upgrade_test
4+
package upgrade
65

76
import (
8-
"context"
97
"flag"
108
"fmt"
11-
"os"
9+
"strings"
1210
"testing"
13-
"time"
1411

1512
"github.com/onsi/ginkgo/v2"
13+
1614
"github.com/onsi/gomega"
1715

18-
runner_sdk "github.com/ava-labs/avalanche-network-runner-sdk"
16+
"github.com/stretchr/testify/require"
1917

20-
"github.com/ava-labs/avalanchego/tests"
18+
"github.com/ava-labs/avalanchego/config"
19+
"github.com/ava-labs/avalanchego/tests/e2e"
2120
)
2221

23-
const DefaultTimeout = 2 * time.Minute
24-
2522
func TestUpgrade(t *testing.T) {
2623
gomega.RegisterFailHandler(ginkgo.Fail)
2724
ginkgo.RunSpecs(t, "upgrade test suites")
2825
}
2926

3027
var (
31-
logLevel string
32-
networkRunnerGRPCEp string
33-
networkRunnerAvalancheGoExecPath string
34-
networkRunnerAvalancheGoExecPathToUpgrade string
35-
networkRunnerAvalancheGoLogLevel string
28+
avalancheGoExecPath string
29+
avalancheGoExecPathToUpgradeTo string
3630
)
3731

3832
func init() {
3933
flag.StringVar(
40-
&logLevel,
41-
"log-level",
42-
"info",
43-
"log level",
44-
)
45-
flag.StringVar(
46-
&networkRunnerGRPCEp,
47-
"network-runner-grpc-endpoint",
48-
"",
49-
"gRPC server endpoint for network-runner",
50-
)
51-
flag.StringVar(
52-
&networkRunnerAvalancheGoExecPath,
53-
"network-runner-avalanchego-path",
34+
&avalancheGoExecPath,
35+
"avalanchego-path",
5436
"",
5537
"avalanchego executable path",
5638
)
5739
flag.StringVar(
58-
&networkRunnerAvalancheGoExecPathToUpgrade,
59-
"network-runner-avalanchego-path-to-upgrade",
40+
&avalancheGoExecPathToUpgradeTo,
41+
"avalanchego-path-to-upgrade-to",
6042
"",
61-
"avalanchego executable path (to upgrade to, only required for upgrade tests with local network-runner)",
62-
)
63-
flag.StringVar(
64-
&networkRunnerAvalancheGoLogLevel,
65-
"network-runner-avalanchego-log-level",
66-
"INFO",
67-
"avalanchego log-level",
43+
"avalanchego executable path to upgrade to",
6844
)
6945
}
7046

71-
var runnerCli runner_sdk.Client
72-
73-
var _ = ginkgo.BeforeSuite(func() {
74-
_, err := os.Stat(networkRunnerAvalancheGoExecPath)
75-
gomega.Expect(err).Should(gomega.BeNil())
76-
77-
_, err = os.Stat(networkRunnerAvalancheGoExecPathToUpgrade)
78-
gomega.Expect(err).Should(gomega.BeNil())
79-
80-
runnerCli, err = runner_sdk.New(runner_sdk.Config{
81-
LogLevel: logLevel,
82-
Endpoint: networkRunnerGRPCEp,
83-
DialTimeout: 10 * time.Second,
84-
})
85-
gomega.Expect(err).Should(gomega.BeNil())
86-
87-
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
88-
presp, err := runnerCli.Ping(ctx)
89-
cancel()
90-
gomega.Expect(err).Should(gomega.BeNil())
91-
tests.Outf("{{green}}network-runner running in PID %d{{/}}\n", presp.Pid)
92-
93-
tests.Outf("{{magenta}}starting network-runner with %q{{/}}\n", networkRunnerAvalancheGoExecPath)
94-
ctx, cancel = context.WithTimeout(context.Background(), DefaultTimeout)
95-
resp, err := runnerCli.Start(ctx, networkRunnerAvalancheGoExecPath,
96-
runner_sdk.WithNumNodes(5),
97-
runner_sdk.WithGlobalNodeConfig(fmt.Sprintf(`{"log-level":"%s"}`, networkRunnerAvalancheGoLogLevel)),
98-
)
99-
cancel()
100-
gomega.Expect(err).Should(gomega.BeNil())
101-
tests.Outf("{{green}}successfully started network-runner: {{/}} %+v\n", resp.ClusterInfo.NodeNames)
102-
103-
ctx, cancel = context.WithTimeout(context.Background(), DefaultTimeout)
104-
_, err = runnerCli.Health(ctx)
105-
cancel()
106-
gomega.Expect(err).Should(gomega.BeNil())
107-
})
108-
109-
var _ = ginkgo.AfterSuite(func() {
110-
tests.Outf("{{red}}shutting down network-runner cluster{{/}}\n")
111-
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
112-
_, err := runnerCli.Stop(ctx)
113-
cancel()
114-
gomega.Expect(err).Should(gomega.BeNil())
115-
116-
tests.Outf("{{red}}shutting down network-runner client{{/}}\n")
117-
err = runnerCli.Close()
118-
gomega.Expect(err).Should(gomega.BeNil())
119-
})
120-
12147
var _ = ginkgo.Describe("[Upgrade]", func() {
122-
ginkgo.It("can upgrade versions", func() {
123-
tests.Outf("{{magenta}}starting upgrade tests %q{{/}}\n", networkRunnerAvalancheGoExecPathToUpgrade)
124-
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
125-
sresp, err := runnerCli.Status(ctx)
126-
cancel()
127-
gomega.Expect(err).Should(gomega.BeNil())
128-
129-
for _, name := range sresp.ClusterInfo.NodeNames {
130-
tests.Outf("{{magenta}}restarting the node %q{{/}} with %q\n", name, networkRunnerAvalancheGoExecPathToUpgrade)
131-
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
132-
resp, err := runnerCli.RestartNode(ctx, name, runner_sdk.WithExecPath(networkRunnerAvalancheGoExecPathToUpgrade))
133-
cancel()
134-
gomega.Expect(err).Should(gomega.BeNil())
48+
require := require.New(ginkgo.GinkgoT())
13549

136-
ctx, cancel = context.WithTimeout(context.Background(), DefaultTimeout)
137-
_, err = runnerCli.Health(ctx)
138-
cancel()
139-
gomega.Expect(err).Should(gomega.BeNil())
140-
tests.Outf("{{green}}successfully upgraded %q to %q{{/}} (current info: %+v)\n", name, networkRunnerAvalancheGoExecPathToUpgrade, resp.ClusterInfo.NodeInfos)
50+
ginkgo.It("can upgrade versions", func() {
51+
// TODO(marun) How many nodes should the target network have to best validate upgrade?
52+
network := e2e.StartLocalNetwork(avalancheGoExecPath, e2e.DefaultNetworkDir)
53+
54+
ginkgo.By(fmt.Sprintf("restarting all nodes with %q binary", avalancheGoExecPathToUpgradeTo))
55+
for _, node := range network.Nodes {
56+
ginkgo.By(fmt.Sprintf("restarting node %q with %q binary", node.GetID(), avalancheGoExecPathToUpgradeTo))
57+
require.NoError(node.Stop())
58+
59+
// A node must start with sufficient bootstrap nodes to represent a quorum. Since the node's current
60+
// bootstrap configuration may not satisfy this requirement (i.e. if on network start the node was one of
61+
// the first validators), updating the node to bootstrap from all running validators maximizes the
62+
// chances of a successful start.
63+
//
64+
// TODO(marun) Refactor node start to do this automatically
65+
bootstrapIPs, bootstrapIDs, err := network.GetBootstrapIPsAndIds()
66+
require.NoError(err)
67+
require.NotEmpty(bootstrapIDs)
68+
node.Flags[config.BootstrapIDsKey] = strings.Join(bootstrapIDs, ",")
69+
node.Flags[config.BootstrapIPsKey] = strings.Join(bootstrapIPs, ",")
70+
require.NoError(node.WriteConfig())
71+
72+
require.NoError(node.Start(ginkgo.GinkgoWriter, avalancheGoExecPath))
73+
74+
ginkgo.By(fmt.Sprintf("waiting for node %q to report healthy after restart", node.GetID()))
75+
e2e.WaitForHealthy(node)
14176
}
14277
})
14378
})

0 commit comments

Comments
 (0)