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