@@ -25,8 +25,10 @@ import (
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)
@@ -79,6 +81,42 @@ func blockTestCmd(ctx *cli.Context) error {
7981 return nil
8082}
8183
84+ // blocktestEndMarker represents the final status of a blocktest execution.
85+ // It is written as the last line of trace output in JSONL format (single-line JSON).
86+ type blocktestEndMarker struct {
87+ TestEnd blocktestEndDetails `json:"testEnd"`
88+ }
89+
90+ type blocktestEndDetails struct {
91+ Name string `json:"name"`
92+ Pass bool `json:"pass"`
93+ Fork string `json:"fork,omitempty"`
94+ Root string `json:"root,omitempty"`
95+ Error string `json:"error,omitempty"`
96+ V int `json:"v"` // Version: 1
97+ }
98+
99+ // writeEndMarker writes the blocktest end marker to stderr in JSONL format.
100+ // This marker indicates the final outcome of the test as a single-line JSON object.
101+ func writeEndMarker (result * testResult , fork string , root * common.Hash ) {
102+ details := blocktestEndDetails {
103+ Name : result .Name ,
104+ Pass : result .Pass ,
105+ Fork : fork ,
106+ V : 1 ,
107+ }
108+ if ! result .Pass && result .Error != "" {
109+ details .Error = result .Error
110+ }
111+ if root != nil {
112+ details .Root = root .Hex ()
113+ }
114+ marker := blocktestEndMarker {TestEnd : details }
115+ if data , err := json .Marshal (marker ); err == nil {
116+ fmt .Fprintf (os .Stderr , "%s\n " , data )
117+ }
118+ }
119+
82120func runBlockTest (ctx * cli.Context , fname string ) ([]testResult , error ) {
83121 src , err := os .ReadFile (fname )
84122 if err != nil {
@@ -94,6 +132,11 @@ func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
94132 }
95133 tracer := tracerFromFlags (ctx )
96134
135+ // Suppress INFO logs when tracing to avoid polluting stderr
136+ if tracer != nil {
137+ log .SetDefault (log .NewLogger (log .DiscardHandler ()))
138+ }
139+
97140 // Pull out keys to sort and ensure tests are run in order.
98141 keys := slices .Sorted (maps .Keys (tests ))
99142
@@ -103,17 +146,30 @@ func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
103146 if ! re .MatchString (name ) {
104147 continue
105148 }
149+ test := tests [name ]
106150 result := & testResult {Name : name , Pass : true }
107- if err := tests [name ].Run (false , rawdb .PathScheme , ctx .Bool (WitnessCrossCheckFlag .Name ), tracer , func (res error , chain * core.BlockChain ) {
151+ var finalRoot * common.Hash
152+ if err := test .Run (false , rawdb .PathScheme , ctx .Bool (WitnessCrossCheckFlag .Name ), tracer , func (res error , chain * core.BlockChain ) {
108153 if ctx .Bool (DumpFlag .Name ) {
109154 if s , _ := chain .State (); s != nil {
110155 result .State = dump (s )
111156 }
112157 }
158+ // Capture final state root for end marker
159+ if chain != nil {
160+ root := chain .CurrentBlock ().Root
161+ finalRoot = & root
162+ }
113163 }); err != nil {
114164 result .Pass , result .Error = false , err .Error ()
115165 }
116166 results = append (results , * result )
167+
168+ // Write end marker when tracing is enabled
169+ if tracer != nil {
170+ fork := test .Network ()
171+ writeEndMarker (result , fork , finalRoot )
172+ }
117173 }
118174 return results , nil
119175}
0 commit comments