vm_test_util.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // Copyright 2015 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. "github.com/ethereum/go-ethereum/params"
  30. )
  31. func RunVmTestWithReader(r io.Reader, skipTests []string) error {
  32. tests := make(map[string]VmTest)
  33. err := readJson(r, &tests)
  34. if err != nil {
  35. return err
  36. }
  37. if err != nil {
  38. return err
  39. }
  40. if err := runVmTests(tests, skipTests); err != nil {
  41. return err
  42. }
  43. return nil
  44. }
  45. type bconf struct {
  46. name string
  47. precomp bool
  48. jit bool
  49. }
  50. func BenchVmTest(p string, conf bconf, b *testing.B) error {
  51. tests := make(map[string]VmTest)
  52. err := readJsonFile(p, &tests)
  53. if err != nil {
  54. return err
  55. }
  56. test, ok := tests[conf.name]
  57. if !ok {
  58. return fmt.Errorf("test not found: %s", conf.name)
  59. }
  60. env := make(map[string]string)
  61. env["currentCoinbase"] = test.Env.CurrentCoinbase
  62. env["currentDifficulty"] = test.Env.CurrentDifficulty
  63. env["currentGasLimit"] = test.Env.CurrentGasLimit
  64. env["currentNumber"] = test.Env.CurrentNumber
  65. env["previousHash"] = test.Env.PreviousHash
  66. if n, ok := test.Env.CurrentTimestamp.(float64); ok {
  67. env["currentTimestamp"] = strconv.Itoa(int(n))
  68. } else {
  69. env["currentTimestamp"] = test.Env.CurrentTimestamp.(string)
  70. }
  71. /*
  72. if conf.precomp {
  73. program := vm.NewProgram(test.code)
  74. err := vm.AttachProgram(program)
  75. if err != nil {
  76. return err
  77. }
  78. }
  79. */
  80. b.ResetTimer()
  81. for i := 0; i < b.N; i++ {
  82. benchVmTest(test, env, b)
  83. }
  84. return nil
  85. }
  86. func benchVmTest(test VmTest, env map[string]string, b *testing.B) {
  87. b.StopTimer()
  88. db, _ := ethdb.NewMemDatabase()
  89. statedb := makePreState(db, test.Pre)
  90. b.StartTimer()
  91. RunVm(statedb, env, test.Exec)
  92. }
  93. func RunVmTest(p string, skipTests []string) error {
  94. tests := make(map[string]VmTest)
  95. err := readJsonFile(p, &tests)
  96. if err != nil {
  97. return err
  98. }
  99. if err := runVmTests(tests, skipTests); err != nil {
  100. return err
  101. }
  102. return nil
  103. }
  104. func runVmTests(tests map[string]VmTest, skipTests []string) error {
  105. skipTest := make(map[string]bool, len(skipTests))
  106. for _, name := range skipTests {
  107. skipTest[name] = true
  108. }
  109. for name, test := range tests {
  110. if skipTest[name] {
  111. glog.Infoln("Skipping VM test", name)
  112. return nil
  113. }
  114. if err := runVmTest(test); err != nil {
  115. return fmt.Errorf("%s %s", name, err.Error())
  116. }
  117. glog.Infoln("VM test passed: ", name)
  118. //fmt.Println(string(statedb.Dump()))
  119. }
  120. return nil
  121. }
  122. func runVmTest(test VmTest) error {
  123. db, _ := ethdb.NewMemDatabase()
  124. statedb := makePreState(db, test.Pre)
  125. // XXX Yeah, yeah...
  126. env := make(map[string]string)
  127. env["currentCoinbase"] = test.Env.CurrentCoinbase
  128. env["currentDifficulty"] = test.Env.CurrentDifficulty
  129. env["currentGasLimit"] = test.Env.CurrentGasLimit
  130. env["currentNumber"] = test.Env.CurrentNumber
  131. env["previousHash"] = test.Env.PreviousHash
  132. if n, ok := test.Env.CurrentTimestamp.(float64); ok {
  133. env["currentTimestamp"] = strconv.Itoa(int(n))
  134. } else {
  135. env["currentTimestamp"] = test.Env.CurrentTimestamp.(string)
  136. }
  137. var (
  138. ret []byte
  139. gas *big.Int
  140. err error
  141. logs vm.Logs
  142. )
  143. ret, logs, gas, err = RunVm(statedb, env, test.Exec)
  144. // Compare expected and actual return
  145. rexp := common.FromHex(test.Out)
  146. if bytes.Compare(rexp, ret) != 0 {
  147. return fmt.Errorf("return failed. Expected %x, got %x\n", rexp, ret)
  148. }
  149. // Check gas usage
  150. if len(test.Gas) == 0 && err == nil {
  151. return fmt.Errorf("gas unspecified, indicating an error. VM returned (incorrectly) successfull")
  152. } else {
  153. gexp := common.Big(test.Gas)
  154. if gexp.Cmp(gas) != 0 {
  155. return fmt.Errorf("gas failed. Expected %v, got %v\n", gexp, gas)
  156. }
  157. }
  158. // check post state
  159. for addr, account := range test.Post {
  160. obj := statedb.GetStateObject(common.HexToAddress(addr))
  161. if obj == nil {
  162. continue
  163. }
  164. for addr, value := range account.Storage {
  165. v := statedb.GetState(obj.Address(), common.HexToHash(addr))
  166. vexp := common.HexToHash(value)
  167. if v != vexp {
  168. 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())
  169. }
  170. }
  171. }
  172. // check logs
  173. if len(test.Logs) > 0 {
  174. lerr := checkLogs(test.Logs, logs)
  175. if lerr != nil {
  176. return lerr
  177. }
  178. }
  179. return nil
  180. }
  181. func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, vm.Logs, *big.Int, error) {
  182. var (
  183. to = common.HexToAddress(exec["address"])
  184. from = common.HexToAddress(exec["caller"])
  185. data = common.FromHex(exec["data"])
  186. gas = common.Big(exec["gas"])
  187. price = common.Big(exec["gasPrice"])
  188. value = common.Big(exec["value"])
  189. )
  190. // Reset the pre-compiled contracts for VM tests.
  191. vm.Precompiled = make(map[string]*vm.PrecompiledAccount)
  192. caller := state.GetOrNewStateObject(from)
  193. vmenv := NewEnvFromMap(RuleSet{params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, true}, state, env, exec)
  194. vmenv.vmTest = true
  195. vmenv.skipTransfer = true
  196. vmenv.initial = true
  197. ret, err := vmenv.Call(caller, to, data, gas, price, value)
  198. return ret, vmenv.state.Logs(), vmenv.Gas, err
  199. }