github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/cmd/evm/staterunner.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // Copyright 2019 The go-aigar Authors 3 // This file is part of the go-aigar library. 4 // 5 // The go-aigar library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-aigar library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>. 17 18 package main 19 20 import ( 21 "encoding/json" 22 "errors" 23 "fmt" 24 "io/ioutil" 25 "os" 26 27 "github.com/AigarNetwork/aigar/core/state" 28 "github.com/AigarNetwork/aigar/core/vm" 29 "github.com/AigarNetwork/aigar/log" 30 "github.com/AigarNetwork/aigar/tests" 31 32 cli "gopkg.in/urfave/cli.v1" 33 ) 34 35 var stateTestCommand = cli.Command{ 36 Action: stateTestCmd, 37 Name: "statetest", 38 Usage: "executes the given state tests", 39 ArgsUsage: "<file>", 40 } 41 42 // StatetestResult contains the execution status after running a state test, any 43 // error that might have occurred and a dump of the final state if requested. 44 type StatetestResult struct { 45 Name string `json:"name"` 46 Pass bool `json:"pass"` 47 Fork string `json:"fork"` 48 Error string `json:"error,omitempty"` 49 State *state.Dump `json:"state,omitempty"` 50 } 51 52 func stateTestCmd(ctx *cli.Context) error { 53 if len(ctx.Args().First()) == 0 { 54 return errors.New("path-to-test argument required") 55 } 56 // Configure the go-ethereum logger 57 glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) 58 glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name))) 59 log.Root().SetHandler(glogger) 60 61 // Configure the EVM logger 62 config := &vm.LogConfig{ 63 DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name), 64 DisableStack: ctx.GlobalBool(DisableStackFlag.Name), 65 } 66 var ( 67 tracer vm.Tracer 68 debugger *vm.StructLogger 69 ) 70 switch { 71 case ctx.GlobalBool(MachineFlag.Name): 72 tracer = vm.NewJSONLogger(config, os.Stderr) 73 74 case ctx.GlobalBool(DebugFlag.Name): 75 debugger = vm.NewStructLogger(config) 76 tracer = debugger 77 78 default: 79 debugger = vm.NewStructLogger(config) 80 } 81 // Load the test content from the input file 82 src, err := ioutil.ReadFile(ctx.Args().First()) 83 if err != nil { 84 return err 85 } 86 var tests map[string]tests.StateTest 87 if err = json.Unmarshal(src, &tests); err != nil { 88 return err 89 } 90 // Iterate over all the tests, run them and aggregate the results 91 cfg := vm.Config{ 92 Tracer: tracer, 93 Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), 94 } 95 results := make([]StatetestResult, 0, len(tests)) 96 for key, test := range tests { 97 for _, st := range test.Subtests() { 98 // Run the test and aggregate the result 99 result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true} 100 state, err := test.Run(st, cfg) 101 // print state root for evmlab tracing 102 if ctx.GlobalBool(MachineFlag.Name) && state != nil { 103 fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", state.IntermediateRoot(false)) 104 } 105 if err != nil { 106 // Test failed, mark as so and dump any state to aid debugging 107 result.Pass, result.Error = false, err.Error() 108 if ctx.GlobalBool(DumpFlag.Name) && state != nil { 109 dump := state.RawDump(false, false, true) 110 result.State = &dump 111 } 112 } 113 114 results = append(results, *result) 115 116 // Print any structured logs collected 117 if ctx.GlobalBool(DebugFlag.Name) { 118 if debugger != nil { 119 fmt.Fprintln(os.Stderr, "#### TRACE ####") 120 vm.WriteTrace(os.Stderr, debugger.StructLogs()) 121 } 122 } 123 } 124 } 125 out, _ := json.MarshalIndent(results, "", " ") 126 fmt.Println(string(out)) 127 return nil 128 }