| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2015 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of go-ethereum. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // go-ethereum is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // go-ethereum is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2015-04-17 16:30:15 +02:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/codegangsta/cli" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/cmd/utils" | 
					
						
							| 
									
										
										
										
											2015-03-20 09:13:17 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/eth" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/ethdb" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/tests" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-27 13:43:49 +02:00
										 |  |  | var blocktestCommand = cli.Command{ | 
					
						
							| 
									
										
										
										
											2015-04-17 16:30:15 +02:00
										 |  |  | 	Action: runBlockTest, | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | 	Name:   "blocktest", | 
					
						
							|  |  |  | 	Usage:  `loads a block test file`, | 
					
						
							|  |  |  | 	Description: ` | 
					
						
							|  |  |  | The first argument should be a block test file. | 
					
						
							|  |  |  | The second argument is the name of a block test from the file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The block test will be loaded into an in-memory database. | 
					
						
							|  |  |  | If loading succeeds, the RPC server is started. Clients will | 
					
						
							|  |  |  | be able to interact with the chain defined by the test. | 
					
						
							|  |  |  | `, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-17 16:30:15 +02:00
										 |  |  | func runBlockTest(ctx *cli.Context) { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		file, testname string | 
					
						
							|  |  |  | 		rpc            bool | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	args := ctx.Args() | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	case len(args) == 1: | 
					
						
							|  |  |  | 		file = args[0] | 
					
						
							|  |  |  | 	case len(args) == 2: | 
					
						
							|  |  |  | 		file, testname = args[0], args[1] | 
					
						
							|  |  |  | 	case len(args) == 3: | 
					
						
							|  |  |  | 		file, testname = args[0], args[1] | 
					
						
							|  |  |  | 		rpc = true | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		utils.Fatalf(`Usage: ethereum blocktest <path-to-test-file> [ <test-name> [ "rpc" ] ]`) | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	bt, err := tests.LoadBlockTests(file) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("%v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-17 16:30:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// run all tests if no test name is specified | 
					
						
							|  |  |  | 	if testname == "" { | 
					
						
							|  |  |  | 		ecode := 0 | 
					
						
							|  |  |  | 		for name, test := range bt { | 
					
						
							|  |  |  | 			fmt.Printf("----------------- Running Block Test %q\n", name) | 
					
						
							|  |  |  | 			ethereum, err := runOneBlockTest(ctx, test) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				fmt.Println(err) | 
					
						
							|  |  |  | 				fmt.Println("FAIL") | 
					
						
							|  |  |  | 				ecode = 1 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if ethereum != nil { | 
					
						
							|  |  |  | 				ethereum.Stop() | 
					
						
							|  |  |  | 				ethereum.WaitForShutdown() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		os.Exit(ecode) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// otherwise, run the given test | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | 	test, ok := bt[testname] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		utils.Fatalf("Test file does not contain test named %q", testname) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-17 16:30:15 +02:00
										 |  |  | 	ethereum, err := runOneBlockTest(ctx, test) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("%v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer ethereum.Stop() | 
					
						
							|  |  |  | 	if rpc { | 
					
						
							|  |  |  | 		fmt.Println("Block Test post state validated, starting RPC interface.") | 
					
						
							|  |  |  | 		startEth(ctx, ethereum) | 
					
						
							|  |  |  | 		utils.StartRPC(ethereum, ctx) | 
					
						
							|  |  |  | 		ethereum.WaitForShutdown() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-17 16:30:15 +02:00
										 |  |  | func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) { | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | 	cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx) | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() } | 
					
						
							| 
									
										
										
										
											2015-03-20 01:59:38 +01:00
										 |  |  | 	cfg.MaxPeers = 0 // disable network | 
					
						
							| 
									
										
										
										
											2015-04-17 16:30:15 +02:00
										 |  |  | 	cfg.Shh = false  // disable whisper | 
					
						
							|  |  |  | 	cfg.NAT = nil    // disable port mapping | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | 	ethereum, err := eth.New(cfg) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2015-04-17 16:30:15 +02:00
										 |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-08 12:55:15 -04:00
										 |  |  | 	// if err := ethereum.Start(); err != nil { | 
					
						
							|  |  |  | 	// 	return nil, err | 
					
						
							|  |  |  | 	// } | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// import the genesis block | 
					
						
							|  |  |  | 	ethereum.ResetWithGenesisBlock(test.Genesis) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// import pre accounts | 
					
						
							| 
									
										
										
										
											2015-04-27 19:32:45 +02:00
										 |  |  | 	statedb, err := test.InsertPreState(ethereum) | 
					
						
							| 
									
										
										
										
											2015-03-20 09:10:13 +01:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2015-04-17 16:30:15 +02:00
										 |  |  | 		return ethereum, fmt.Errorf("InsertPreState: %v", err) | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-20 18:14:57 +02:00
										 |  |  | 	if err := test.TryBlocksInsert(ethereum.ChainManager()); err != nil { | 
					
						
							|  |  |  | 		return ethereum, fmt.Errorf("Block Test load error: %v", err) | 
					
						
							| 
									
										
										
										
											2015-03-20 09:10:13 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-20 18:14:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-20 09:10:13 +01:00
										 |  |  | 	if err := test.ValidatePostState(statedb); err != nil { | 
					
						
							| 
									
										
										
										
											2015-04-17 16:30:15 +02:00
										 |  |  | 		return ethereum, fmt.Errorf("post state validation failed: %v", err) | 
					
						
							| 
									
										
										
										
											2015-03-20 01:59:38 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-17 16:30:15 +02:00
										 |  |  | 	return ethereum, nil | 
					
						
							| 
									
										
										
										
											2015-03-13 18:37:13 +01:00
										 |  |  | } |