@ -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 " ,
Usage : "Executes the given state tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution). " ,
ArgsUsage : "<file>" ,
}
@ -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 ) ) )
@ -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 ) :
t racer = 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 ( ) {
@ -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 , "" , " " )