staterunner.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Copyright 2017 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. package main
  17. import (
  18. "encoding/json"
  19. "errors"
  20. "fmt"
  21. "io/ioutil"
  22. "os"
  23. "github.com/ethereum/go-ethereum/core/state"
  24. "github.com/ethereum/go-ethereum/core/vm"
  25. "github.com/ethereum/go-ethereum/log"
  26. "github.com/ethereum/go-ethereum/tests"
  27. cli "gopkg.in/urfave/cli.v1"
  28. )
  29. var stateTestCommand = cli.Command{
  30. Action: stateTestCmd,
  31. Name: "statetest",
  32. Usage: "executes the given state tests",
  33. ArgsUsage: "<file>",
  34. }
  35. // StatetestResult contains the execution status after running a state test, any
  36. // error that might have occurred and a dump of the final state if requested.
  37. type StatetestResult struct {
  38. Name string `json:"name"`
  39. Pass bool `json:"pass"`
  40. Fork string `json:"fork"`
  41. Error string `json:"error,omitempty"`
  42. State *state.Dump `json:"state,omitempty"`
  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-ethereum 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. // Configure the EVM logger
  53. config := &vm.LogConfig{
  54. DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name),
  55. DisableStack: ctx.GlobalBool(DisableStackFlag.Name),
  56. }
  57. var (
  58. tracer vm.Tracer
  59. debugger *vm.StructLogger
  60. )
  61. switch {
  62. case ctx.GlobalBool(MachineFlag.Name):
  63. tracer = vm.NewJSONLogger(config, os.Stderr)
  64. case ctx.GlobalBool(DebugFlag.Name):
  65. debugger = vm.NewStructLogger(config)
  66. tracer = debugger
  67. default:
  68. debugger = vm.NewStructLogger(config)
  69. }
  70. // Load the test content from the input file
  71. src, err := ioutil.ReadFile(ctx.Args().First())
  72. if err != nil {
  73. return err
  74. }
  75. var tests map[string]tests.StateTest
  76. if err = json.Unmarshal(src, &tests); err != nil {
  77. return err
  78. }
  79. // Iterate over all the tests, run them and aggregate the results
  80. cfg := vm.Config{
  81. Tracer: tracer,
  82. Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name),
  83. }
  84. results := make([]StatetestResult, 0, len(tests))
  85. for key, test := range tests {
  86. for _, st := range test.Subtests() {
  87. // Run the test and aggregate the result
  88. result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
  89. state, err := test.Run(st, cfg)
  90. // print state root for evmlab tracing
  91. if ctx.GlobalBool(MachineFlag.Name) && state != nil {
  92. fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", state.IntermediateRoot(false))
  93. }
  94. if err != nil {
  95. // Test failed, mark as so and dump any state to aid debugging
  96. result.Pass, result.Error = false, err.Error()
  97. if ctx.GlobalBool(DumpFlag.Name) && state != nil {
  98. dump := state.RawDump()
  99. result.State = &dump
  100. }
  101. }
  102. results = append(results, *result)
  103. // Print any structured logs collected
  104. if ctx.GlobalBool(DebugFlag.Name) {
  105. if debugger != nil {
  106. fmt.Fprintln(os.Stderr, "#### TRACE ####")
  107. vm.WriteTrace(os.Stderr, debugger.StructLogs())
  108. }
  109. }
  110. }
  111. }
  112. out, _ := json.MarshalIndent(results, "", " ")
  113. fmt.Println(string(out))
  114. return nil
  115. }