1717package main
1818
1919import (
20+ "bufio"
2021 "encoding/json"
21- "errors"
2222 "fmt"
2323 "maps"
2424 "os"
2525 "regexp"
2626 "slices"
2727
28+ "github.com/ethereum/go-ethereum/common"
2829 "github.com/ethereum/go-ethereum/core"
2930 "github.com/ethereum/go-ethereum/core/rawdb"
31+ "github.com/ethereum/go-ethereum/log"
3032 "github.com/ethereum/go-ethereum/tests"
3133 "github.com/urfave/cli/v2"
3234)
3335
3436var blockTestCommand = & cli.Command {
3537 Action : blockTestCmd ,
3638 Name : "blocktest" ,
37- Usage : "Executes the given blockchain tests" ,
39+ Usage : "Executes the given blockchain tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution). " ,
3840 ArgsUsage : "<path>" ,
3941 Flags : slices .Concat ([]cli.Flag {
4042 DumpFlag ,
4143 HumanReadableFlag ,
4244 RunFlag ,
4345 WitnessCrossCheckFlag ,
46+ FuzzFlag ,
4447 }, traceFlags ),
4548}
4649
4750func blockTestCmd (ctx * cli.Context ) error {
4851 path := ctx .Args ().First ()
49- if len (path ) == 0 {
50- return errors .New ("path argument required" )
52+
53+ // If path is provided, run the tests at that path.
54+ if len (path ) != 0 {
55+ var (
56+ collected = collectFiles (path )
57+ results []testResult
58+ )
59+ for _ , fname := range collected {
60+ r , err := runBlockTest (ctx , fname )
61+ if err != nil {
62+ return err
63+ }
64+ results = append (results , r ... )
65+ }
66+ report (ctx , results )
67+ return nil
5168 }
52- var (
53- collected = collectFiles (path )
54- results []testResult
55- )
56- for _ , fname := range collected {
57- r , err := runBlockTest (ctx , fname )
69+ // Otherwise, read filenames from stdin and execute back-to-back.
70+ scanner := bufio .NewScanner (os .Stdin )
71+ for scanner .Scan () {
72+ fname := scanner .Text ()
73+ if len (fname ) == 0 {
74+ return nil
75+ }
76+ results , err := runBlockTest (ctx , fname )
5877 if err != nil {
5978 return err
6079 }
61- results = append (results , r ... )
80+ // During fuzzing, we report the result after every block
81+ if ! ctx .IsSet (FuzzFlag .Name ) {
82+ report (ctx , results )
83+ }
6284 }
63- report (ctx , results )
6485 return nil
6586}
6687
@@ -79,6 +100,11 @@ func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
79100 }
80101 tracer := tracerFromFlags (ctx )
81102
103+ // Suppress INFO logs during fuzzing
104+ if ctx .IsSet (FuzzFlag .Name ) {
105+ log .SetDefault (log .NewLogger (log .DiscardHandler ()))
106+ }
107+
82108 // Pull out keys to sort and ensure tests are run in order.
83109 keys := slices .Sorted (maps .Keys (tests ))
84110
@@ -88,16 +114,35 @@ func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
88114 if ! re .MatchString (name ) {
89115 continue
90116 }
117+ test := tests [name ]
91118 result := & testResult {Name : name , Pass : true }
92- if err := tests [name ].Run (false , rawdb .PathScheme , ctx .Bool (WitnessCrossCheckFlag .Name ), tracer , func (res error , chain * core.BlockChain ) {
119+ var finalRoot * common.Hash
120+ if err := test .Run (false , rawdb .PathScheme , ctx .Bool (WitnessCrossCheckFlag .Name ), tracer , func (res error , chain * core.BlockChain ) {
93121 if ctx .Bool (DumpFlag .Name ) {
94122 if s , _ := chain .State (); s != nil {
95123 result .State = dump (s )
96124 }
97125 }
126+ // Capture final state root for end marker
127+ if chain != nil {
128+ root := chain .CurrentBlock ().Root
129+ finalRoot = & root
130+ }
98131 }); err != nil {
99132 result .Pass , result .Error = false , err .Error ()
100133 }
134+
135+ // Always assign fork (regardless of pass/fail or tracer)
136+ result .Fork = test .Network ()
137+ // Assign root if test succeeded
138+ if result .Pass && finalRoot != nil {
139+ result .Root = finalRoot
140+ }
141+
142+ // When fuzzing, write results after every block
143+ if ctx .IsSet (FuzzFlag .Name ) {
144+ report (ctx , []testResult {* result })
145+ }
101146 results = append (results , * result )
102147 }
103148 return results , nil
0 commit comments