github.com/ethereum/go-ethereum@v1.16.1/cmd/evm/blockrunner.go (about)

     1  // Copyright 2023 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package main
    18  
    19  import (
    20  	"encoding/json"
    21  	"errors"
    22  	"fmt"
    23  	"maps"
    24  	"os"
    25  	"regexp"
    26  	"slices"
    27  
    28  	"github.com/ethereum/go-ethereum/core"
    29  	"github.com/ethereum/go-ethereum/core/rawdb"
    30  	"github.com/ethereum/go-ethereum/tests"
    31  	"github.com/urfave/cli/v2"
    32  )
    33  
    34  var blockTestCommand = &cli.Command{
    35  	Action:    blockTestCmd,
    36  	Name:      "blocktest",
    37  	Usage:     "Executes the given blockchain tests",
    38  	ArgsUsage: "<path>",
    39  	Flags: slices.Concat([]cli.Flag{
    40  		DumpFlag,
    41  		HumanReadableFlag,
    42  		RunFlag,
    43  		WitnessCrossCheckFlag,
    44  	}, traceFlags),
    45  }
    46  
    47  func blockTestCmd(ctx *cli.Context) error {
    48  	path := ctx.Args().First()
    49  	if len(path) == 0 {
    50  		return errors.New("path argument required")
    51  	}
    52  	var (
    53  		collected = collectFiles(path)
    54  		results   []testResult
    55  	)
    56  	for _, fname := range collected {
    57  		r, err := runBlockTest(ctx, fname)
    58  		if err != nil {
    59  			return err
    60  		}
    61  		results = append(results, r...)
    62  	}
    63  	report(ctx, results)
    64  	return nil
    65  }
    66  
    67  func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
    68  	src, err := os.ReadFile(fname)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	var tests map[string]*tests.BlockTest
    73  	if err = json.Unmarshal(src, &tests); err != nil {
    74  		return nil, err
    75  	}
    76  	re, err := regexp.Compile(ctx.String(RunFlag.Name))
    77  	if err != nil {
    78  		return nil, fmt.Errorf("invalid regex -%s: %v", RunFlag.Name, err)
    79  	}
    80  	tracer := tracerFromFlags(ctx)
    81  
    82  	// Pull out keys to sort and ensure tests are run in order.
    83  	keys := slices.Sorted(maps.Keys(tests))
    84  
    85  	// Run all the tests.
    86  	var results []testResult
    87  	for _, name := range keys {
    88  		if !re.MatchString(name) {
    89  			continue
    90  		}
    91  		result := &testResult{Name: name, Pass: true}
    92  		if err := tests[name].Run(false, rawdb.HashScheme, ctx.Bool(WitnessCrossCheckFlag.Name), tracer, func(res error, chain *core.BlockChain) {
    93  			if ctx.Bool(DumpFlag.Name) {
    94  				if s, _ := chain.State(); s != nil {
    95  					result.State = dump(s)
    96  				}
    97  			}
    98  		}); err != nil {
    99  			result.Pass, result.Error = false, err.Error()
   100  		}
   101  		results = append(results, *result)
   102  	}
   103  	return results, nil
   104  }