diff --git a/cmd/evm/staterunner.go b/cmd/evm/staterunner.go index ed102e6054..e9229eaeca 100644 --- a/cmd/evm/staterunner.go +++ b/cmd/evm/staterunner.go @@ -17,8 +17,8 @@ package main import ( - "bufio" "encoding/json" + "errors" "fmt" "os" @@ -34,7 +34,7 @@ import ( var stateTestCommand = &cli.Command{ Action: stateTestCmd, Name: "statetest", - Usage: "Executes the given state tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).", + Usage: "executes the given state tests", ArgsUsage: "", } @@ -50,6 +50,9 @@ type StatetestResult struct { } func stateTestCmd(ctx *cli.Context) error { + if len(ctx.Args().First()) == 0 { + return errors.New("path-to-test argument required") + } // Configure the go-ethereum logger glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name))) @@ -62,43 +65,34 @@ func stateTestCmd(ctx *cli.Context) error { DisableStorage: ctx.Bool(DisableStorageFlag.Name), EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name), } - var cfg vm.Config + var ( + tracer vm.EVMLogger + debugger *logger.StructLogger + ) switch { case ctx.Bool(MachineFlag.Name): - cfg.Tracer = logger.NewJSONLogger(config, os.Stderr) + tracer = logger.NewJSONLogger(config, os.Stderr) case ctx.Bool(DebugFlag.Name): - cfg.Tracer = logger.NewStructLogger(config) + debugger = logger.NewStructLogger(config) + tracer = debugger + + default: + debugger = logger.NewStructLogger(config) } // Load the test content from the input file - if len(ctx.Args().First()) != 0 { - return runStateTest(ctx.Args().First(), cfg, ctx.Bool(MachineFlag.Name), ctx.Bool(DumpFlag.Name)) - } - // Read filenames from stdin and execute back-to-back - scanner := bufio.NewScanner(os.Stdin) - for scanner.Scan() { - fname := scanner.Text() - if len(fname) == 0 { - return nil - } - if err := runStateTest(fname, cfg, ctx.Bool(MachineFlag.Name), ctx.Bool(DumpFlag.Name)); err != nil { - return err - } - } - return nil -} - -// runStateTest loads the state-test given by fname, and executes the test. -func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error { - src, err := os.ReadFile(fname) + src, err := os.ReadFile(ctx.Args().First()) if err != nil { return err } var tests map[string]tests.StateTest - if err := json.Unmarshal(src, &tests); err != nil { + if err = json.Unmarshal(src, &tests); err != nil { return err } // Iterate over all the tests, run them and aggregate the results + cfg := vm.Config{ + Tracer: tracer, + } results := make([]StatetestResult, 0, len(tests)) for key, test := range tests { for _, st := range test.Subtests() { @@ -109,20 +103,28 @@ func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error { if s != nil { root := s.IntermediateRoot(false) result.Root = &root - if jsonOut { + if ctx.Bool(MachineFlag.Name) { fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root) } } if err != nil { // Test failed, mark as so and dump any state to aid debugging result.Pass, result.Error = false, err.Error() - if dump && s != nil { + if ctx.Bool(DumpFlag.Name) && s != nil { dump := s.RawDump(nil) result.State = &dump } } results = append(results, *result) + + // Print any structured logs collected + if ctx.Bool(DebugFlag.Name) { + if debugger != nil { + fmt.Fprintln(os.Stderr, "#### TRACE ####") + logger.WriteTrace(os.Stderr, debugger.StructLogs()) + } + } } } out, _ := json.MarshalIndent(results, "", " ")