@@ -23,6 +23,7 @@ import (
2323 "os"
2424 "regexp"
2525 "slices"
26+ "sync"
2627
2728 "github.com/ethereum/go-ethereum/common"
2829 "github.com/ethereum/go-ethereum/core/rawdb"
@@ -57,6 +58,7 @@ var stateTestCommand = &cli.Command{
5758 HumanReadableFlag ,
5859 idxFlag ,
5960 RunFlag ,
61+ WorkersFlag ,
6062 }, traceFlags ),
6163}
6264
@@ -65,16 +67,14 @@ func stateTestCmd(ctx *cli.Context) error {
6567
6668 // If path is provided, run the tests at that path.
6769 if len (path ) != 0 {
68- var (
69- collected = collectFiles (path )
70- results []testResult
71- )
72- for _ , fname := range collected {
73- r , err := runStateTest (ctx , fname )
74- if err != nil {
75- return err
76- }
77- results = append (results , r ... )
70+ collected := collectFiles (path )
71+ workers := ctx .Int (WorkersFlag .Name )
72+ if workers <= 0 {
73+ workers = 1
74+ }
75+ results , err := runStateTestsParallel (ctx , collected , workers )
76+ if err != nil {
77+ return err
7878 }
7979 report (ctx , results )
8080 return nil
@@ -95,6 +95,63 @@ func stateTestCmd(ctx *cli.Context) error {
9595 return nil
9696}
9797
98+ func runStateTestsParallel (ctx * cli.Context , files []string , workers int ) ([]testResult , error ) {
99+ if workers == 1 {
100+ var results []testResult
101+ for _ , fname := range files {
102+ r , err := runStateTest (ctx , fname )
103+ if err != nil {
104+ return nil , err
105+ }
106+ results = append (results , r ... )
107+ }
108+ return results , nil
109+ }
110+ var (
111+ wg sync.WaitGroup
112+ fileCh = make (chan struct {
113+ index int
114+ fname string
115+ }, len (files ))
116+ resultCh = make (chan fileResult , len (files ))
117+ )
118+ for i , fname := range files {
119+ fileCh <- struct {
120+ index int
121+ fname string
122+ }{i , fname }
123+ }
124+ close (fileCh )
125+
126+ for w := 0 ; w < workers ; w ++ {
127+ wg .Add (1 )
128+ go func () {
129+ defer wg .Done ()
130+ for item := range fileCh {
131+ r , err := runStateTest (ctx , item .fname )
132+ resultCh <- fileResult {index : item .index , results : r , err : err }
133+ }
134+ }()
135+ }
136+ go func () {
137+ wg .Wait ()
138+ close (resultCh )
139+ }()
140+
141+ ordered := make ([]fileResult , len (files ))
142+ for fr := range resultCh {
143+ if fr .err != nil {
144+ return nil , fr .err
145+ }
146+ ordered [fr .index ] = fr
147+ }
148+ var results []testResult
149+ for _ , fr := range ordered {
150+ results = append (results , fr .results ... )
151+ }
152+ return results , nil
153+ }
154+
98155// runStateTest loads the state-test given by fname, and executes the test.
99156func runStateTest (ctx * cli.Context , fname string ) ([]testResult , error ) {
100157 src , err := os .ReadFile (fname )
@@ -103,7 +160,7 @@ func runStateTest(ctx *cli.Context, fname string) ([]testResult, error) {
103160 }
104161 var testsByName map [string ]tests.StateTest
105162 if err := json .Unmarshal (src , & testsByName ); err != nil {
106- return nil , fmt . Errorf ( "unable to read test file %s: %w" , fname , err )
163+ return nil , nil // Skip non-fixture JSON files
107164 }
108165
109166 cfg := vm.Config {Tracer : tracerFromFlags (ctx )}
0 commit comments