github.com/MagHErmit/tendermint@v0.282.1/test/e2e/runner/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"strconv"
     8  
     9  	"github.com/spf13/cobra"
    10  
    11  	"github.com/MagHErmit/tendermint/libs/log"
    12  	e2e "github.com/MagHErmit/tendermint/test/e2e/pkg"
    13  )
    14  
    15  var (
    16  	logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout))
    17  )
    18  
    19  func main() {
    20  	NewCLI().Run()
    21  }
    22  
    23  // CLI is the Cobra-based command-line interface.
    24  type CLI struct {
    25  	root     *cobra.Command
    26  	testnet  *e2e.Testnet
    27  	preserve bool
    28  }
    29  
    30  // NewCLI sets up the CLI.
    31  func NewCLI() *CLI {
    32  	cli := &CLI{}
    33  	cli.root = &cobra.Command{
    34  		Use:           "runner",
    35  		Short:         "End-to-end test runner",
    36  		SilenceUsage:  true,
    37  		SilenceErrors: true, // we'll output them ourselves in Run()
    38  		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
    39  			file, err := cmd.Flags().GetString("file")
    40  			if err != nil {
    41  				return err
    42  			}
    43  			testnet, err := e2e.LoadTestnet(file)
    44  			if err != nil {
    45  				return err
    46  			}
    47  
    48  			cli.testnet = testnet
    49  			return nil
    50  		},
    51  		RunE: func(cmd *cobra.Command, args []string) error {
    52  			if err := Cleanup(cli.testnet); err != nil {
    53  				return err
    54  			}
    55  			if err := Setup(cli.testnet); err != nil {
    56  				return err
    57  			}
    58  
    59  			chLoadResult := make(chan error)
    60  			ctx, loadCancel := context.WithCancel(context.Background())
    61  			defer loadCancel()
    62  			go func() {
    63  				err := Load(ctx, cli.testnet, 1)
    64  				if err != nil {
    65  					logger.Error(fmt.Sprintf("Transaction load failed: %v", err.Error()))
    66  				}
    67  				chLoadResult <- err
    68  			}()
    69  
    70  			if err := Start(cli.testnet); err != nil {
    71  				return err
    72  			}
    73  
    74  			if lastMisbehavior := cli.testnet.LastMisbehaviorHeight(); lastMisbehavior > 0 {
    75  				// wait for misbehaviors before starting perturbations. We do a separate
    76  				// wait for another 5 blocks, since the last misbehavior height may be
    77  				// in the past depending on network startup ordering.
    78  				if err := WaitUntil(cli.testnet, lastMisbehavior); err != nil {
    79  					return err
    80  				}
    81  			}
    82  			if err := Wait(cli.testnet, 5); err != nil { // allow some txs to go through
    83  				return err
    84  			}
    85  
    86  			if cli.testnet.HasPerturbations() {
    87  				if err := Perturb(cli.testnet); err != nil {
    88  					return err
    89  				}
    90  				if err := Wait(cli.testnet, 5); err != nil { // allow some txs to go through
    91  					return err
    92  				}
    93  			}
    94  
    95  			loadCancel()
    96  			if err := <-chLoadResult; err != nil {
    97  				return err
    98  			}
    99  			if err := Wait(cli.testnet, 5); err != nil { // wait for network to settle before tests
   100  				return err
   101  			}
   102  			if err := Test(cli.testnet); err != nil {
   103  				return err
   104  			}
   105  			if !cli.preserve {
   106  				if err := Cleanup(cli.testnet); err != nil {
   107  					return err
   108  				}
   109  			}
   110  			return nil
   111  		},
   112  	}
   113  
   114  	cli.root.PersistentFlags().StringP("file", "f", "", "Testnet TOML manifest")
   115  	_ = cli.root.MarkPersistentFlagRequired("file")
   116  
   117  	cli.root.Flags().BoolVarP(&cli.preserve, "preserve", "p", false,
   118  		"Preserves the running of the test net after tests are completed")
   119  
   120  	cli.root.AddCommand(&cobra.Command{
   121  		Use:   "setup",
   122  		Short: "Generates the testnet directory and configuration",
   123  		RunE: func(cmd *cobra.Command, args []string) error {
   124  			return Setup(cli.testnet)
   125  		},
   126  	})
   127  
   128  	cli.root.AddCommand(&cobra.Command{
   129  		Use:   "start",
   130  		Short: "Starts the Docker testnet, waiting for nodes to become available",
   131  		RunE: func(cmd *cobra.Command, args []string) error {
   132  			_, err := os.Stat(cli.testnet.Dir)
   133  			if os.IsNotExist(err) {
   134  				err = Setup(cli.testnet)
   135  			}
   136  			if err != nil {
   137  				return err
   138  			}
   139  			return Start(cli.testnet)
   140  		},
   141  	})
   142  
   143  	cli.root.AddCommand(&cobra.Command{
   144  		Use:   "perturb",
   145  		Short: "Perturbs the Docker testnet, e.g. by restarting or disconnecting nodes",
   146  		RunE: func(cmd *cobra.Command, args []string) error {
   147  			return Perturb(cli.testnet)
   148  		},
   149  	})
   150  
   151  	cli.root.AddCommand(&cobra.Command{
   152  		Use:   "wait",
   153  		Short: "Waits for a few blocks to be produced and all nodes to catch up",
   154  		RunE: func(cmd *cobra.Command, args []string) error {
   155  			return Wait(cli.testnet, 5)
   156  		},
   157  	})
   158  
   159  	cli.root.AddCommand(&cobra.Command{
   160  		Use:   "stop",
   161  		Short: "Stops the Docker testnet",
   162  		RunE: func(cmd *cobra.Command, args []string) error {
   163  			logger.Info("Stopping testnet")
   164  			return execCompose(cli.testnet.Dir, "down")
   165  		},
   166  	})
   167  
   168  	cli.root.AddCommand(&cobra.Command{
   169  		Use:   "load [multiplier]",
   170  		Args:  cobra.MaximumNArgs(1),
   171  		Short: "Generates transaction load until the command is canceled",
   172  		RunE: func(cmd *cobra.Command, args []string) (err error) {
   173  			m := 1
   174  
   175  			if len(args) == 1 {
   176  				m, err = strconv.Atoi(args[0])
   177  				if err != nil {
   178  					return err
   179  				}
   180  			}
   181  
   182  			return Load(context.Background(), cli.testnet, m)
   183  		},
   184  	})
   185  
   186  	cli.root.AddCommand(&cobra.Command{
   187  		Use:   "test",
   188  		Short: "Runs test cases against a running testnet",
   189  		RunE: func(cmd *cobra.Command, args []string) error {
   190  			return Test(cli.testnet)
   191  		},
   192  	})
   193  
   194  	cli.root.AddCommand(&cobra.Command{
   195  		Use:   "cleanup",
   196  		Short: "Removes the testnet directory",
   197  		RunE: func(cmd *cobra.Command, args []string) error {
   198  			return Cleanup(cli.testnet)
   199  		},
   200  	})
   201  
   202  	cli.root.AddCommand(&cobra.Command{
   203  		Use:   "logs",
   204  		Short: "Shows the testnet logs",
   205  		RunE: func(cmd *cobra.Command, args []string) error {
   206  			return execComposeVerbose(cli.testnet.Dir, "logs")
   207  		},
   208  	})
   209  
   210  	cli.root.AddCommand(&cobra.Command{
   211  		Use:   "tail",
   212  		Short: "Tails the testnet logs",
   213  		RunE: func(cmd *cobra.Command, args []string) error {
   214  			return execComposeVerbose(cli.testnet.Dir, "logs", "--follow")
   215  		},
   216  	})
   217  
   218  	cli.root.AddCommand(&cobra.Command{
   219  		Use:   "benchmark",
   220  		Short: "Benchmarks testnet",
   221  		Long: `Benchmarks the following metrics:
   222  	Mean Block Interval
   223  	Standard Deviation
   224  	Min Block Interval
   225  	Max Block Interval
   226  over a 100 block sampling period.
   227  
   228  Does not run any perbutations.
   229  		`,
   230  		RunE: func(cmd *cobra.Command, args []string) error {
   231  			if err := Cleanup(cli.testnet); err != nil {
   232  				return err
   233  			}
   234  			if err := Setup(cli.testnet); err != nil {
   235  				return err
   236  			}
   237  
   238  			chLoadResult := make(chan error)
   239  			ctx, loadCancel := context.WithCancel(context.Background())
   240  			defer loadCancel()
   241  			go func() {
   242  				err := Load(ctx, cli.testnet, 1)
   243  				if err != nil {
   244  					logger.Error(fmt.Sprintf("Transaction load failed: %v", err.Error()))
   245  				}
   246  				chLoadResult <- err
   247  			}()
   248  
   249  			if err := Start(cli.testnet); err != nil {
   250  				return err
   251  			}
   252  
   253  			if err := Wait(cli.testnet, 5); err != nil { // allow some txs to go through
   254  				return err
   255  			}
   256  
   257  			// we benchmark performance over the next 100 blocks
   258  			if err := Benchmark(cli.testnet, 100); err != nil {
   259  				return err
   260  			}
   261  
   262  			loadCancel()
   263  			if err := <-chLoadResult; err != nil {
   264  				return err
   265  			}
   266  
   267  			if err := Cleanup(cli.testnet); err != nil {
   268  				return err
   269  			}
   270  
   271  			return nil
   272  		},
   273  	})
   274  
   275  	return cli
   276  }
   277  
   278  // Run runs the CLI.
   279  func (cli *CLI) Run() {
   280  	if err := cli.root.Execute(); err != nil {
   281  		logger.Error(err.Error())
   282  		os.Exit(1)
   283  	}
   284  }