github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/cmd/geth/blocktestcmd.go (about)

     1  // Copyright 2015 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  	"fmt"
    21  	"os"
    22  
    23  	"github.com/codegangsta/cli"
    24  	"github.com/ethereum/go-ethereum/cmd/utils"
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/eth"
    27  	"github.com/ethereum/go-ethereum/ethdb"
    28  	"github.com/ethereum/go-ethereum/tests"
    29  )
    30  
    31  var blocktestCommand = cli.Command{
    32  	Action: runBlockTest,
    33  	Name:   "blocktest",
    34  	Usage:  `loads a block test file`,
    35  	Description: `
    36  The first argument should be a block test file.
    37  The second argument is the name of a block test from the file.
    38  
    39  The block test will be loaded into an in-memory database.
    40  If loading succeeds, the RPC server is started. Clients will
    41  be able to interact with the chain defined by the test.
    42  `,
    43  }
    44  
    45  func runBlockTest(ctx *cli.Context) {
    46  	var (
    47  		file, testname string
    48  		rpc            bool
    49  	)
    50  	args := ctx.Args()
    51  	switch {
    52  	case len(args) == 1:
    53  		file = args[0]
    54  	case len(args) == 2:
    55  		file, testname = args[0], args[1]
    56  	case len(args) == 3:
    57  		file, testname = args[0], args[1]
    58  		rpc = true
    59  	default:
    60  		utils.Fatalf(`Usage: ethereum blocktest <path-to-test-file> [ <test-name> [ "rpc" ] ]`)
    61  	}
    62  	bt, err := tests.LoadBlockTests(file)
    63  	if err != nil {
    64  		utils.Fatalf("%v", err)
    65  	}
    66  
    67  	// run all tests if no test name is specified
    68  	if testname == "" {
    69  		ecode := 0
    70  		for name, test := range bt {
    71  			fmt.Printf("----------------- Running Block Test %q\n", name)
    72  			ethereum, err := runOneBlockTest(ctx, test)
    73  			if err != nil {
    74  				fmt.Println(err)
    75  				fmt.Println("FAIL")
    76  				ecode = 1
    77  			}
    78  			if ethereum != nil {
    79  				ethereum.Stop()
    80  				ethereum.WaitForShutdown()
    81  			}
    82  		}
    83  		os.Exit(ecode)
    84  		return
    85  	}
    86  	// otherwise, run the given test
    87  	test, ok := bt[testname]
    88  	if !ok {
    89  		utils.Fatalf("Test file does not contain test named %q", testname)
    90  	}
    91  	ethereum, err := runOneBlockTest(ctx, test)
    92  	if err != nil {
    93  		utils.Fatalf("%v", err)
    94  	}
    95  	defer ethereum.Stop()
    96  	if rpc {
    97  		fmt.Println("Block Test post state validated, starting RPC interface.")
    98  		startEth(ctx, ethereum)
    99  		utils.StartRPC(ethereum, ctx)
   100  		ethereum.WaitForShutdown()
   101  	}
   102  }
   103  
   104  func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) {
   105  	cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
   106  	cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() }
   107  	cfg.MaxPeers = 0 // disable network
   108  	cfg.Shh = false  // disable whisper
   109  	cfg.NAT = nil    // disable port mapping
   110  
   111  	ethereum, err := eth.New(cfg)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	// if err := ethereum.Start(); err != nil {
   116  	// 	return nil, err
   117  	// }
   118  
   119  	// import the genesis block
   120  	ethereum.ResetWithGenesisBlock(test.Genesis)
   121  
   122  	// import pre accounts
   123  	statedb, err := test.InsertPreState(ethereum)
   124  	if err != nil {
   125  		return ethereum, fmt.Errorf("InsertPreState: %v", err)
   126  	}
   127  
   128  	if err := test.TryBlocksInsert(ethereum.ChainManager()); err != nil {
   129  		return ethereum, fmt.Errorf("Block Test load error: %v", err)
   130  	}
   131  
   132  	if err := test.ValidatePostState(statedb); err != nil {
   133  		return ethereum, fmt.Errorf("post state validation failed: %v", err)
   134  	}
   135  	return ethereum, nil
   136  }