Skip to content
Merged
Changes from all commits
Commits
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
58 changes: 28 additions & 30 deletions cmd/evm/staterunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
package main

import (
"bufio"
"encoding/json"
"errors"
"fmt"
"os"

Expand All @@ -34,7 +34,7 @@ import (
var stateTestCommand = &cli.Command{
Action: stateTestCmd,
Name: "statetest",
Usage: "executes the given state tests",
Usage: "Executes the given state tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).",
ArgsUsage: "<file>",
}

Expand All @@ -50,9 +50,6 @@ 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)))
Expand All @@ -65,34 +62,43 @@ func stateTestCmd(ctx *cli.Context) error {
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
}
var (
tracer vm.EVMLogger
debugger *logger.StructLogger
)
var cfg vm.Config
switch {
case ctx.Bool(MachineFlag.Name):
tracer = logger.NewJSONLogger(config, os.Stderr)
cfg.Tracer = logger.NewJSONLogger(config, os.Stderr)

case ctx.Bool(DebugFlag.Name):
debugger = logger.NewStructLogger(config)
tracer = debugger

default:
debugger = logger.NewStructLogger(config)
cfg.Tracer = logger.NewStructLogger(config)
}
// Load the test content from the input file
src, err := os.ReadFile(ctx.Args().First())
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)
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() {
Expand All @@ -103,28 +109,20 @@ func stateTestCmd(ctx *cli.Context) error {
if s != nil {
root := s.IntermediateRoot(false)
result.Root = &root
if ctx.Bool(MachineFlag.Name) {
if jsonOut {
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 ctx.Bool(DumpFlag.Name) && s != nil {
if dump && 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, "", " ")
Expand Down