Skip to content
Open
Show file tree
Hide file tree
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
62 changes: 49 additions & 13 deletions cmd/evm/blockrunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,26 @@
package main

import (
"bufio"
"encoding/json"
"errors"
"fmt"
"maps"
"os"
"regexp"
"slices"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/tests"
"github.com/urfave/cli/v2"
)

var blockTestCommand = &cli.Command{
Action: blockTestCmd,
Name: "blocktest",
Usage: "Executes the given blockchain tests",
Usage: "Executes the given blockchain tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).",
ArgsUsage: "<path>",
Flags: slices.Concat([]cli.Flag{
DumpFlag,
Expand All @@ -46,21 +48,36 @@ var blockTestCommand = &cli.Command{

func blockTestCmd(ctx *cli.Context) error {
path := ctx.Args().First()
if len(path) == 0 {
return errors.New("path argument required")

// If path is provided, run the tests at that path.
if len(path) != 0 {
var (
collected = collectFiles(path)
results []testResult
)
for _, fname := range collected {
r, err := runBlockTest(ctx, fname)
if err != nil {
return err
}
results = append(results, r...)
}
report(ctx, results)
return nil
}
var (
collected = collectFiles(path)
results []testResult
)
for _, fname := range collected {
r, err := runBlockTest(ctx, fname)
// Otherwise, 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
}
results, err := runBlockTest(ctx, fname)
if err != nil {
return err
}
results = append(results, r...)
report(ctx, results)
}
report(ctx, results)
return nil
}

Expand All @@ -79,6 +96,11 @@ func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
}
tracer := tracerFromFlags(ctx)

// Suppress INFO logs when tracing to avoid polluting stderr
if tracer != nil {
log.SetDefault(log.NewLogger(log.DiscardHandler()))
}

// Pull out keys to sort and ensure tests are run in order.
keys := slices.Sorted(maps.Keys(tests))

Expand All @@ -88,16 +110,30 @@ func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
if !re.MatchString(name) {
continue
}
test := tests[name]
result := &testResult{Name: name, Pass: true}
if err := tests[name].Run(false, rawdb.PathScheme, ctx.Bool(WitnessCrossCheckFlag.Name), tracer, func(res error, chain *core.BlockChain) {
var finalRoot *common.Hash
if err := test.Run(false, rawdb.PathScheme, ctx.Bool(WitnessCrossCheckFlag.Name), tracer, func(res error, chain *core.BlockChain) {
if ctx.Bool(DumpFlag.Name) {
if s, _ := chain.State(); s != nil {
result.State = dump(s)
}
}
// Capture final state root for end marker
if chain != nil {
root := chain.CurrentBlock().Root
finalRoot = &root
}
}); err != nil {
result.Pass, result.Error = false, err.Error()
}

// Write result between transactions when tracing is enabled
if tracer != nil {
result.Fork = test.Network()
result.Root = finalRoot
report(ctx, []testResult{*result})
}
results = append(results, *result)
}
return results, nil
Expand Down
11 changes: 10 additions & 1 deletion tests/block_test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
if !ok {
return UnsupportedForkError{t.json.Network}
}
return t.run(config, snapshotter, scheme, witness, tracer, postCheck)
}

// Network returns the network/fork name for this test.
func (t *BlockTest) Network() string {
return t.json.Network
}

func (t *BlockTest) run(config *params.ChainConfig, snapshotter bool, scheme string, witness bool, tracer *tracing.Hooks, postCheck func(error, *core.BlockChain)) (result error) {
// import pre accounts & construct test genesis block & state root
var (
db = rawdb.NewMemoryDatabase()
Expand Down Expand Up @@ -259,7 +268,7 @@ func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error)
}
if b.BlockHeader == nil {
if data, err := json.MarshalIndent(cb.Header(), "", " "); err == nil {
fmt.Fprintf(os.Stderr, "block (index %d) insertion should have failed due to: %v:\n%v\n",
fmt.Fprintf(os.Stdout, "block (index %d) insertion should have failed due to: %v:\n%v\n",
bi, b.ExpectException, string(data))
}
return nil, fmt.Errorf("block (index %d) insertion should have failed due to: %v",
Expand Down