vm_test_util.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. // Copyright 2014 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser 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. // The go-ethereum library 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 Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package tests
  17. import (
  18. "bytes"
  19. "fmt"
  20. "io"
  21. "math/big"
  22. "strconv"
  23. "testing"
  24. "github.com/ethereum/go-ethereum/common"
  25. "github.com/ethereum/go-ethereum/core/state"
  26. "github.com/ethereum/go-ethereum/core/vm"
  27. "github.com/ethereum/go-ethereum/ethdb"
  28. "github.com/ethereum/go-ethereum/logger/glog"
  29. )
  30. func RunVmTestWithReader(r io.Reader, skipTests []string) error {
  31. tests := make(map[string]VmTest)
  32. err := readJson(r, &tests)
  33. if err != nil {
  34. return err
  35. }
  36. if err != nil {
  37. return err
  38. }
  39. if err := runVmTests(tests, skipTests); err != nil {
  40. return err
  41. }
  42. return nil
  43. }
  44. type bconf struct {
  45. name string
  46. precomp bool
  47. jit bool
  48. }
  49. func BenchVmTest(p string, conf bconf, b *testing.B) error {
  50. tests := make(map[string]VmTest)
  51. err := readJsonFile(p, &tests)
  52. if err != nil {
  53. return err
  54. }
  55. test, ok := tests[conf.name]
  56. if !ok {
  57. return fmt.Errorf("test not found: %s", conf.name)
  58. }
  59. pJit := vm.EnableJit
  60. vm.EnableJit = conf.jit
  61. pForceJit := vm.ForceJit
  62. vm.ForceJit = conf.precomp
  63. env := make(map[string]string)
  64. env["currentCoinbase"] = test.Env.CurrentCoinbase
  65. env["currentDifficulty"] = test.Env.CurrentDifficulty
  66. env["currentGasLimit"] = test.Env.CurrentGasLimit
  67. env["currentNumber"] = test.Env.CurrentNumber
  68. env["previousHash"] = test.Env.PreviousHash
  69. if n, ok := test.Env.CurrentTimestamp.(float64); ok {
  70. env["currentTimestamp"] = strconv.Itoa(int(n))
  71. } else {
  72. env["currentTimestamp"] = test.Env.CurrentTimestamp.(string)
  73. }
  74. /*
  75. if conf.precomp {
  76. program := vm.NewProgram(test.code)
  77. err := vm.AttachProgram(program)
  78. if err != nil {
  79. return err
  80. }
  81. }
  82. */
  83. b.ResetTimer()
  84. for i := 0; i < b.N; i++ {
  85. benchVmTest(test, env, b)
  86. }
  87. vm.EnableJit = pJit
  88. vm.ForceJit = pForceJit
  89. return nil
  90. }
  91. func benchVmTest(test VmTest, env map[string]string, b *testing.B) {
  92. b.StopTimer()
  93. db, _ := ethdb.NewMemDatabase()
  94. statedb := state.New(common.Hash{}, db)
  95. for addr, account := range test.Pre {
  96. obj := StateObjectFromAccount(db, addr, account)
  97. statedb.SetStateObject(obj)
  98. for a, v := range account.Storage {
  99. obj.SetState(common.HexToHash(a), common.HexToHash(v))
  100. }
  101. }
  102. b.StartTimer()
  103. RunVm(statedb, env, test.Exec)
  104. }
  105. func RunVmTest(p string, skipTests []string) error {
  106. tests := make(map[string]VmTest)
  107. err := readJsonFile(p, &tests)
  108. if err != nil {
  109. return err
  110. }
  111. if err := runVmTests(tests, skipTests); err != nil {
  112. return err
  113. }
  114. return nil
  115. }
  116. func runVmTests(tests map[string]VmTest, skipTests []string) error {
  117. skipTest := make(map[string]bool, len(skipTests))
  118. for _, name := range skipTests {
  119. skipTest[name] = true
  120. }
  121. for name, test := range tests {
  122. if skipTest[name] {
  123. glog.Infoln("Skipping VM test", name)
  124. return nil
  125. }
  126. if err := runVmTest(test); err != nil {
  127. return fmt.Errorf("%s %s", name, err.Error())
  128. }
  129. glog.Infoln("VM test passed: ", name)
  130. //fmt.Println(string(statedb.Dump()))
  131. }
  132. return nil
  133. }
  134. func runVmTest(test VmTest) error {
  135. db, _ := ethdb.NewMemDatabase()
  136. statedb := state.New(common.Hash{}, db)
  137. for addr, account := range test.Pre {
  138. obj := StateObjectFromAccount(db, addr, account)
  139. statedb.SetStateObject(obj)
  140. for a, v := range account.Storage {
  141. obj.SetState(common.HexToHash(a), common.HexToHash(v))
  142. }
  143. }
  144. // XXX Yeah, yeah...
  145. env := make(map[string]string)
  146. env["currentCoinbase"] = test.Env.CurrentCoinbase
  147. env["currentDifficulty"] = test.Env.CurrentDifficulty
  148. env["currentGasLimit"] = test.Env.CurrentGasLimit
  149. env["currentNumber"] = test.Env.CurrentNumber
  150. env["previousHash"] = test.Env.PreviousHash
  151. if n, ok := test.Env.CurrentTimestamp.(float64); ok {
  152. env["currentTimestamp"] = strconv.Itoa(int(n))
  153. } else {
  154. env["currentTimestamp"] = test.Env.CurrentTimestamp.(string)
  155. }
  156. var (
  157. ret []byte
  158. gas *big.Int
  159. err error
  160. logs vm.Logs
  161. )
  162. ret, logs, gas, err = RunVm(statedb, env, test.Exec)
  163. // Compare expected and actual return
  164. rexp := common.FromHex(test.Out)
  165. if bytes.Compare(rexp, ret) != 0 {
  166. return fmt.Errorf("return failed. Expected %x, got %x\n", rexp, ret)
  167. }
  168. // Check gas usage
  169. if len(test.Gas) == 0 && err == nil {
  170. return fmt.Errorf("gas unspecified, indicating an error. VM returned (incorrectly) successfull")
  171. } else {
  172. gexp := common.Big(test.Gas)
  173. if gexp.Cmp(gas) != 0 {
  174. return fmt.Errorf("gas failed. Expected %v, got %v\n", gexp, gas)
  175. }
  176. }
  177. // check post state
  178. for addr, account := range test.Post {
  179. obj := statedb.GetStateObject(common.HexToAddress(addr))
  180. if obj == nil {
  181. continue
  182. }
  183. for addr, value := range account.Storage {
  184. v := obj.GetState(common.HexToHash(addr))
  185. vexp := common.HexToHash(value)
  186. if v != vexp {
  187. return fmt.Errorf("(%x: %s) storage failed. Expected %x, got %x (%v %v)\n", obj.Address().Bytes()[0:4], addr, vexp, v, vexp.Big(), v.Big())
  188. }
  189. }
  190. }
  191. // check logs
  192. if len(test.Logs) > 0 {
  193. lerr := checkLogs(test.Logs, logs)
  194. if lerr != nil {
  195. return lerr
  196. }
  197. }
  198. return nil
  199. }
  200. func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, vm.Logs, *big.Int, error) {
  201. var (
  202. to = common.HexToAddress(exec["address"])
  203. from = common.HexToAddress(exec["caller"])
  204. data = common.FromHex(exec["data"])
  205. gas = common.Big(exec["gas"])
  206. price = common.Big(exec["gasPrice"])
  207. value = common.Big(exec["value"])
  208. )
  209. // Reset the pre-compiled contracts for VM tests.
  210. vm.Precompiled = make(map[string]*vm.PrecompiledAccount)
  211. caller := state.GetOrNewStateObject(from)
  212. vmenv := NewEnvFromMap(state, env, exec)
  213. vmenv.vmTest = true
  214. vmenv.skipTransfer = true
  215. vmenv.initial = true
  216. ret, err := vmenv.Call(caller, to, data, gas, price, value)
  217. return ret, vmenv.state.Logs(), vmenv.Gas, err
  218. }