github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/cmd/evm/staterunner.go (about) 1 2 package main 3 4 import ( 5 "encoding/json" 6 "errors" 7 "fmt" 8 "io/ioutil" 9 "os" 10 11 "github.com/quickchainproject/quickchain/core/state" 12 "github.com/quickchainproject/quickchain/core/vm" 13 "github.com/quickchainproject/quickchain/log" 14 "github.com/quickchainproject/quickchain/tests" 15 16 cli "gopkg.in/urfave/cli.v1" 17 ) 18 19 var stateTestCommand = cli.Command{ 20 Action: stateTestCmd, 21 Name: "statetest", 22 Usage: "executes the given state tests", 23 ArgsUsage: "<file>", 24 } 25 26 type StatetestResult struct { 27 Name string `json:"name"` 28 Pass bool `json:"pass"` 29 Fork string `json:"fork"` 30 Error string `json:"error,omitempty"` 31 State *state.Dump `json:"state,omitempty"` 32 } 33 34 func stateTestCmd(ctx *cli.Context) error { 35 if len(ctx.Args().First()) == 0 { 36 return errors.New("path-to-test argument required") 37 } 38 // Configure the quickchain logger 39 glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) 40 glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name))) 41 log.Root().SetHandler(glogger) 42 43 // Configure the EVM logger 44 config := &vm.LogConfig{ 45 DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name), 46 DisableStack: ctx.GlobalBool(DisableStackFlag.Name), 47 } 48 var ( 49 tracer vm.Tracer 50 debugger *vm.StructLogger 51 ) 52 switch { 53 case ctx.GlobalBool(MachineFlag.Name): 54 tracer = NewJSONLogger(config, os.Stderr) 55 56 case ctx.GlobalBool(DebugFlag.Name): 57 debugger = vm.NewStructLogger(config) 58 tracer = debugger 59 60 default: 61 debugger = vm.NewStructLogger(config) 62 } 63 // Load the test content from the input file 64 src, err := ioutil.ReadFile(ctx.Args().First()) 65 if err != nil { 66 return err 67 } 68 var tests map[string]tests.StateTest 69 if err = json.Unmarshal(src, &tests); err != nil { 70 return err 71 } 72 // Iterate over all the tests, run them and aggregate the results 73 cfg := vm.Config{ 74 Tracer: tracer, 75 Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), 76 } 77 results := make([]StatetestResult, 0, len(tests)) 78 for key, test := range tests { 79 for _, st := range test.Subtests() { 80 // Run the test and aggregate the result 81 result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true} 82 state, err := test.Run(st, cfg) 83 if err != nil { 84 // Test failed, mark as so and dump any state to aid debugging 85 result.Pass, result.Error = false, err.Error() 86 if ctx.GlobalBool(DumpFlag.Name) && state != nil { 87 dump := state.RawDump() 88 result.State = &dump 89 } 90 } 91 // print state root for evmlab tracing (already committed above, so no need to delete objects again 92 if ctx.GlobalBool(MachineFlag.Name) && state != nil { 93 fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", state.IntermediateRoot(false)) 94 } 95 96 results = append(results, *result) 97 98 // Print any structured logs collected 99 if ctx.GlobalBool(DebugFlag.Name) { 100 if debugger != nil { 101 fmt.Fprintln(os.Stderr, "#### TRACE ####") 102 vm.WriteTrace(os.Stderr, debugger.StructLogs()) 103 } 104 } 105 } 106 } 107 out, _ := json.MarshalIndent(results, "", " ") 108 fmt.Println(string(out)) 109 return nil 110 }