mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-07 05:46:32 +00:00
In #5488 the E2E testnet generator changed to setting explicit `StartAt` heights for initial nodes. This broke the runner, which expected all initial nodes to have `StartAt: 0`, as well as validator set scheduling in the generator. Testnet loading now normalizes initial nodes to have `StartAt: 0`. This also tweaks waiting for misbehavior heights to only use an additional wait if there actually is any misbehavior in the testnet, and to output information when waiting.
209 lines
4.9 KiB
Go
209 lines
4.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/tendermint/tendermint/libs/log"
|
|
e2e "github.com/tendermint/tendermint/test/e2e/pkg"
|
|
)
|
|
|
|
var (
|
|
logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
|
)
|
|
|
|
func main() {
|
|
NewCLI().Run()
|
|
}
|
|
|
|
// CLI is the Cobra-based command-line interface.
|
|
type CLI struct {
|
|
root *cobra.Command
|
|
testnet *e2e.Testnet
|
|
preserve bool
|
|
}
|
|
|
|
// NewCLI sets up the CLI.
|
|
func NewCLI() *CLI {
|
|
cli := &CLI{}
|
|
cli.root = &cobra.Command{
|
|
Use: "runner",
|
|
Short: "End-to-end test runner",
|
|
SilenceUsage: true,
|
|
SilenceErrors: true, // we'll output them ourselves in Run()
|
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
|
file, err := cmd.Flags().GetString("file")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
testnet, err := e2e.LoadTestnet(file)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cli.testnet = testnet
|
|
return nil
|
|
},
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
if err := Cleanup(cli.testnet); err != nil {
|
|
return err
|
|
}
|
|
if err := Setup(cli.testnet); err != nil {
|
|
return err
|
|
}
|
|
|
|
chLoadResult := make(chan error)
|
|
ctx, loadCancel := context.WithCancel(context.Background())
|
|
defer loadCancel()
|
|
go func() {
|
|
err := Load(ctx, cli.testnet)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("Transaction load failed: %v", err.Error()))
|
|
}
|
|
chLoadResult <- err
|
|
}()
|
|
|
|
if err := Start(cli.testnet); err != nil {
|
|
return err
|
|
}
|
|
if lastMisbehavior := cli.testnet.LastMisbehaviorHeight(); lastMisbehavior > 0 {
|
|
// wait for misbehaviors before starting perturbations
|
|
if err := WaitUntil(cli.testnet, lastMisbehavior+5); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := Perturb(cli.testnet); err != nil {
|
|
return err
|
|
}
|
|
if err := Wait(cli.testnet, 5); err != nil { // allow some txs to go through
|
|
return err
|
|
}
|
|
|
|
loadCancel()
|
|
if err := <-chLoadResult; err != nil {
|
|
return err
|
|
}
|
|
// wait for network to settle before tests
|
|
if err := Wait(cli.testnet, 5); err != nil {
|
|
return err
|
|
}
|
|
if err := Test(cli.testnet); err != nil {
|
|
return err
|
|
}
|
|
if !cli.preserve {
|
|
if err := Cleanup(cli.testnet); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
cli.root.PersistentFlags().StringP("file", "f", "", "Testnet TOML manifest")
|
|
_ = cli.root.MarkPersistentFlagRequired("file")
|
|
|
|
cli.root.Flags().BoolVarP(&cli.preserve, "preserve", "p", false,
|
|
"Preserves the running of the test net after tests are completed")
|
|
|
|
cli.root.AddCommand(&cobra.Command{
|
|
Use: "setup",
|
|
Short: "Generates the testnet directory and configuration",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return Setup(cli.testnet)
|
|
},
|
|
})
|
|
|
|
cli.root.AddCommand(&cobra.Command{
|
|
Use: "start",
|
|
Short: "Starts the Docker testnet, waiting for nodes to become available",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
_, err := os.Stat(cli.testnet.Dir)
|
|
if os.IsNotExist(err) {
|
|
err = Setup(cli.testnet)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return Start(cli.testnet)
|
|
},
|
|
})
|
|
|
|
cli.root.AddCommand(&cobra.Command{
|
|
Use: "perturb",
|
|
Short: "Perturbs the Docker testnet, e.g. by restarting or disconnecting nodes",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return Perturb(cli.testnet)
|
|
},
|
|
})
|
|
|
|
cli.root.AddCommand(&cobra.Command{
|
|
Use: "wait",
|
|
Short: "Waits for a few blocks to be produced and all nodes to catch up",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return Wait(cli.testnet, 5)
|
|
},
|
|
})
|
|
|
|
cli.root.AddCommand(&cobra.Command{
|
|
Use: "stop",
|
|
Short: "Stops the Docker testnet",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
logger.Info("Stopping testnet")
|
|
return execCompose(cli.testnet.Dir, "down")
|
|
},
|
|
})
|
|
|
|
cli.root.AddCommand(&cobra.Command{
|
|
Use: "load",
|
|
Short: "Generates transaction load until the command is cancelled",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return Load(context.Background(), cli.testnet)
|
|
},
|
|
})
|
|
|
|
cli.root.AddCommand(&cobra.Command{
|
|
Use: "test",
|
|
Short: "Runs test cases against a running testnet",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return Test(cli.testnet)
|
|
},
|
|
})
|
|
|
|
cli.root.AddCommand(&cobra.Command{
|
|
Use: "cleanup",
|
|
Short: "Removes the testnet directory",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return Cleanup(cli.testnet)
|
|
},
|
|
})
|
|
|
|
cli.root.AddCommand(&cobra.Command{
|
|
Use: "logs",
|
|
Short: "Shows the testnet logs",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return execComposeVerbose(cli.testnet.Dir, "logs")
|
|
},
|
|
})
|
|
|
|
cli.root.AddCommand(&cobra.Command{
|
|
Use: "tail",
|
|
Short: "Tails the testnet logs",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return execComposeVerbose(cli.testnet.Dir, "logs", "--follow")
|
|
},
|
|
})
|
|
|
|
return cli
|
|
}
|
|
|
|
// Run runs the CLI.
|
|
func (cli *CLI) Run() {
|
|
if err := cli.root.Execute(); err != nil {
|
|
logger.Error(err.Error())
|
|
os.Exit(1)
|
|
}
|
|
}
|