Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c326b18
e2e: Add local network fixture
maru-ava Jul 20, 2023
c2ded4a
fixup: self-review cleanup
maru-ava Jul 25, 2023
af4c8d0
fixup: Respond to review feedback
maru-ava Jul 25, 2023
efb986a
fixup: More responding to review feedback
maru-ava Jul 25, 2023
10a4a94
fixup: Don't treat 'process already finished' as error on node stop
maru-ava Jul 25, 2023
72a5bb2
fixup: Switch from SIGKILL to SIGTERM to stop nodes
maru-ava Jul 25, 2023
517e203
fixup: respond to review comments 3
maru-ava Jul 25, 2023
baa4cad
fixup: Use a more descriptive name for node init timeout const
maru-ava Jul 25, 2023
d81cc17
fixup: Fix truncated function comment.
maru-ava Jul 25, 2023
48d4f85
fixup: respond to review feedback 4
maru-ava Jul 26, 2023
bc150c2
fixup: respond to review feedback 5
maru-ava Jul 26, 2023
c900e54
fixup: respond to review feedback 6
maru-ava Jul 26, 2023
1fc22c8
fixup: Refactor process liveness checks
maru-ava Jul 26, 2023
fdf0f9f
fixup: Fix the use of testnetctl --use-static-ports
maru-ava Jul 26, 2023
ebf3dc2
fixup: Ensure testing of static node ports in persistent network job
maru-ava Jul 26, 2023
19a5bff
fixup: Always use process context file to synchronize node start
maru-ava Jul 26, 2023
5df110b
fixup: Define err constant for static error
maru-ava Jul 26, 2023
ce5114d
fixup: wrap error instead of just printing it
maru-ava Jul 27, 2023
e48b861
fixup: respond to review comments 7.
maru-ava Jul 31, 2023
0422ea2
fixup: use WaitForProcessContext in Start to indicate start success
maru-ava Jul 31, 2023
af878b6
fixup: respond to review feedback 8
maru-ava Jul 31, 2023
dbac5fd
fixup: Add version command to testnetctl
maru-ava Aug 2, 2023
b3fedc6
fixup: Remove support for static ports
maru-ava Aug 2, 2023
9eb7cca
fixup: respond to review comments 9
maru-ava Aug 2, 2023
49cfe52
fixup: Remove unused constant
maru-ava Aug 2, 2023
5fa29ca
Update .github/workflows/test.e2e.persistent.yml
maru-ava Aug 7, 2023
932c2a0
Update tests/fixture/testnet/cmd/main.go
maru-ava Aug 7, 2023
afb9f55
Update tests/fixture/testnet/cmd/main.go
maru-ava Aug 7, 2023
4ff6dd6
Update tests/fixture/testnet/cmd/main.go
maru-ava Aug 7, 2023
e8d4a75
Update tests/fixture/testnet/local/node.go
maru-ava Aug 7, 2023
8ca9cdf
Update tests/fixture/testnet/local/node_test.go
maru-ava Aug 7, 2023
744be0c
Update tests/fixture/testnet/local/network_test.go
maru-ava Aug 7, 2023
533e896
Update tests/fixture/testnet/local/README.md
maru-ava Aug 7, 2023
643ce4b
fixup: Respond to review comments 10
maru-ava Aug 7, 2023
4f93b42
fixup: lint errors
maru-ava Aug 8, 2023
bf49c01
fixup: Add TODO comment about X-Chain and P-Chain configuration
maru-ava Aug 8, 2023
2cb928d
Remove unnecessary import alias
StephenButtolph Aug 8, 2023
0044324
Merge branch 'dev' into e2e-local-network
StephenButtolph Aug 8, 2023
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
31 changes: 31 additions & 0 deletions .github/workflows/test.e2e.persistent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Test e2e with persistent network

on:
push:
tags:
- "*"
branches:
- master
- dev
pull_request:

permissions:
contents: read

jobs:
test_e2e_persistent:
runs-on: ubuntu-latest
steps:
- name: Git checkout
uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: '~1.19.12'
check-latest: true
- name: Build the avalanchego binary
shell: bash
run: ./scripts/build.sh -r
- name: Run e2e tests with persistent network
shell: bash
run: ./scripts/tests.e2e.persistent.sh ./build/avalanchego
4 changes: 3 additions & 1 deletion config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const (

AvalancheGoDataDirVar = "AVALANCHEGO_DATA_DIR"
defaultUnexpandedDataDir = "$" + AvalancheGoDataDirVar

ProcessContextFilename = "process.json"
)

var (
Expand All @@ -50,7 +52,7 @@ var (
defaultSubnetConfigDir = filepath.Join(defaultConfigDir, "subnets")
defaultPluginDir = filepath.Join(defaultUnexpandedDataDir, "plugins")
defaultChainDataDir = filepath.Join(defaultUnexpandedDataDir, "chainData")
defaultProcessContextPath = filepath.Join(defaultUnexpandedDataDir, "process.json")
defaultProcessContextPath = filepath.Join(defaultUnexpandedDataDir, ProcessContextFilename)
)

func deprecateFlags(fs *pflag.FlagSet) error {
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ require (
github.com/rs/cors v1.7.0
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/spaolacci/murmur3 v1.1.0
github.com/spf13/cast v1.5.0
github.com/spf13/cobra v1.0.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.12.0
github.com/stretchr/testify v1.8.1
Expand Down Expand Up @@ -103,6 +105,7 @@ require (
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/klauspost/compress v1.15.15 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
Expand All @@ -124,7 +127,6 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sanity-io/litter v1.5.1 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect
github.com/subosito/gotenv v1.3.0 // indirect
Expand Down
64 changes: 64 additions & 0 deletions go.sum

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"errors"
"fmt"
"io"
"io/fs"
"net"
"os"
"path/filepath"
Expand Down Expand Up @@ -476,7 +477,7 @@ func (n *Node) Dispatch() error {

// Remove the process context file to communicate to an orchestrator
// that the node is no longer running.
if err := os.Remove(n.Config.ProcessContextFilePath); err != nil && !os.IsNotExist(err) {
if err := os.Remove(n.Config.ProcessContextFilePath); err != nil && !errors.Is(err, fs.ErrNotExist) {
n.Log.Error("removal of process context file failed",
zap.String("path", n.Config.ProcessContextFilePath),
zap.Error(err),
Expand Down
3 changes: 2 additions & 1 deletion scripts/build_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ AVALANCHE_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd .. && pwd )
# Load the constants
source "$AVALANCHE_PATH"/scripts/constants.sh

go test -shuffle=on -race -timeout="120s" -coverprofile="coverage.out" -covermode="atomic" $(go list ./... | grep -v /mocks | grep -v proto | grep -v tests)
# Ensure execution of fixture unit tests under tests/ but exclude ginkgo tests in tests/e2e and tests/upgrade
go test -shuffle=on -race -timeout="120s" -coverprofile="coverage.out" -covermode="atomic" $(go list ./... | grep -v /mocks | grep -v proto | grep -v tests/e2e | grep -v tests/upgrade)
16 changes: 16 additions & 0 deletions scripts/build_testnetctl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail

# Avalanchego root folder
AVALANCHE_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd .. && pwd )
# Load the constants
source "$AVALANCHE_PATH"/scripts/constants.sh

echo "Building testnetctl..."
go build -ldflags\
"-X github.com/ava-labs/avalanchego/version.GitCommit=$git_commit $static_ld_flags"\
-o "$AVALANCHE_PATH/build/testnetctl"\
"$AVALANCHE_PATH/tests/fixture/testnet/cmd/"*.go
64 changes: 64 additions & 0 deletions scripts/tests.e2e.persistent.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env bash

set -e
set -o nounset
set -o pipefail

################################################################
# This script deploys a persistent local network and configures
# tests.e2e.sh to execute the e2e suite against it.
################################################################

# e.g.,
# ./scripts/build.sh
# ./scripts/tests.e2e.persistent_network.sh ./build/avalanchego
if ! [[ "$0" =~ scripts/tests.e2e.persistent.sh ]]; then
echo "must be run from repository root"
exit 255
fi

AVALANCHEGO_PATH="${1-${AVALANCHEGO_PATH:-}}"
if [[ -z "${AVALANCHEGO_PATH}" ]]; then
echo "Missing AVALANCHEGO_PATH argument!"
echo "Usage: ${0} [AVALANCHEGO_PATH]" >>/dev/stderr
exit 255
fi
# Ensure an absolute path to avoid dependency on the working directory
# of script execution.
export AVALANCHEGO_PATH="$(realpath ${AVALANCHEGO_PATH})"

# Create a temporary directory to store persistent network
ROOT_DIR="$(mktemp -d -t e2e-testnet.XXXXX)"

# Provide visual separation between testing and setup/teardown
function print_separator {
printf '%*s\n' "${COLUMNS:-80}" '' | tr ' ' ─
}

# Ensure network cleanup on teardown
function cleanup {
print_separator
echo "cleaning up persistent network"
if [[ -n "${TESTNETCTL_NETWORK_DIR:-}" ]]; then
./build/testnetctl stop-network
fi
rm -r "${ROOT_DIR}"
}
trap cleanup EXIT

# Start a persistent network
./scripts/build_testnetctl.sh
print_separator
./build/testnetctl start-network --root-dir="${ROOT_DIR}"

# Determine the network configuration path from the latest symlink
LATEST_SYMLINK_PATH="${ROOT_DIR}/latest"
if [[ -h "${LATEST_SYMLINK_PATH}" ]]; then
export TESTNETCTL_NETWORK_DIR="$(realpath ${LATEST_SYMLINK_PATH})"
else
echo "failed to find configuration path: ${LATEST_SYMLINK_PATH} symlink not found"
exit 255
fi

print_separator
# TODO(marun) Enable e2e testing
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to run tests.e2e.sh in #1709

8 changes: 8 additions & 0 deletions tests/fixture/testnet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Test Network Fixture

This package contains configuration and interfaces that are
independent of a given orchestration mechanism
(e.g. [local](local/README.md)). The intent is to enable tests to be
written against the interfaces defined in this package and for
implementation-specific details of test network orchestration to be
limited to test setup and teardown.
124 changes: 124 additions & 0 deletions tests/fixture/testnet/cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package main

import (
"context"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"

"github.com/spf13/cobra"

"github.com/ava-labs/avalanchego/tests/fixture/testnet"
"github.com/ava-labs/avalanchego/tests/fixture/testnet/local"
"github.com/ava-labs/avalanchego/version"
)

const cliVersion = "0.0.1"

var (
errAvalancheGoRequired = fmt.Errorf("--avalanchego-path or %s are required", local.AvalancheGoPathEnvName)
errNetworkDirRequired = fmt.Errorf("--network-dir or %s are required", local.NetworkDirEnvName)
)

func main() {
rootCmd := &cobra.Command{
Use: "testnetctl",
Short: "testnetctl commands",
}

versionCmd := &cobra.Command{
Use: "version",
Short: "Print version details",
RunE: func(*cobra.Command, []string) error {
msg := cliVersion
if len(version.GitCommit) > 0 {
msg += ", commit=" + version.GitCommit
}
fmt.Fprintf(os.Stdout, msg+"\n")
return nil
},
}
rootCmd.AddCommand(versionCmd)

var (
rootDir string
execPath string
nodeCount uint8
fundedKeyCount uint8
)
startNetworkCmd := &cobra.Command{
Use: "start-network",
Short: "Start a new local network",
RunE: func(*cobra.Command, []string) error {
if len(execPath) == 0 {
return errAvalancheGoRequired
}

// Root dir will be defaulted on start if not provided

network := &local.LocalNetwork{
LocalConfig: local.LocalConfig{
ExecPath: execPath,
},
}
ctx, cancel := context.WithTimeout(context.Background(), local.DefaultNetworkStartTimeout)
defer cancel()
network, err := local.StartNetwork(ctx, os.Stdout, rootDir, network, int(nodeCount), int(fundedKeyCount))
if err != nil {
return err
}

// Symlink the new network to the 'latest' network to simplify usage
networkRootDir := filepath.Dir(network.Dir)
networkDirName := filepath.Base(network.Dir)
latestSymlinkPath := filepath.Join(networkRootDir, "latest")
if err := os.Remove(latestSymlinkPath); err != nil && !errors.Is(err, fs.ErrNotExist) {
return err
}
if err := os.Symlink(networkDirName, latestSymlinkPath); err != nil {
return err
}

fmt.Fprintf(os.Stdout, "\nConfigure testnetctl to target this network by default with one of the following statements:")
fmt.Fprintf(os.Stdout, "\n - source %s\n", network.EnvFilePath())
fmt.Fprintf(os.Stdout, " - %s\n", network.EnvFileContents())
fmt.Fprintf(os.Stdout, " - export %s=%s\n", local.NetworkDirEnvName, latestSymlinkPath)

return nil
},
}
startNetworkCmd.PersistentFlags().StringVar(&rootDir, "root-dir", os.Getenv(local.RootDirEnvName), "The path to the root directory for local networks")
startNetworkCmd.PersistentFlags().StringVar(&execPath, "avalanchego-path", os.Getenv(local.AvalancheGoPathEnvName), "The path to an avalanchego binary")
startNetworkCmd.PersistentFlags().Uint8Var(&nodeCount, "node-count", testnet.DefaultNodeCount, "Number of nodes the network should initially consist of")
startNetworkCmd.PersistentFlags().Uint8Var(&fundedKeyCount, "funded-key-count", testnet.DefaultFundedKeyCount, "Number of funded keys the network should start with")
rootCmd.AddCommand(startNetworkCmd)

var networkDir string
stopNetworkCmd := &cobra.Command{
Use: "stop-network",
Short: "Stop a local network",
RunE: func(*cobra.Command, []string) error {
if len(networkDir) == 0 {
return errNetworkDirRequired
}
if err := local.StopNetwork(networkDir); err != nil {
return err
}
fmt.Fprintf(os.Stdout, "Stopped network configured at: %s\n", networkDir)
return nil
},
}
stopNetworkCmd.PersistentFlags().StringVar(&networkDir, "network-dir", os.Getenv(local.NetworkDirEnvName), "The path to the configuration directory of a local network")
rootCmd.AddCommand(stopNetworkCmd)

if err := rootCmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "testnetctl failed: %v\n", err)
os.Exit(1)
}
os.Exit(0)
}
Loading