Add stdin option
This commit is contained in:
parent
a86452d22c
commit
01ec4dbb12
@ -24,6 +24,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -55,28 +56,37 @@ var (
|
||||
Name: "continue",
|
||||
Usage: "Continue running tests on error (true) or [default] exit immediately (false)",
|
||||
}
|
||||
ReadStdInFlag = cli.BoolFlag{
|
||||
Name: "stdin",
|
||||
Usage: "Accept input from stdin instead of reading from file",
|
||||
}
|
||||
)
|
||||
|
||||
func runTest(test, file string) error {
|
||||
// glog.Infoln("runTest", test, file)
|
||||
func runTestWithReader(test string, r io.Reader) error {
|
||||
glog.Infoln("runTest", test)
|
||||
var err error
|
||||
switch test {
|
||||
case "bc", "BlockTest", "BlockTests", "BlockChainTest":
|
||||
err = tests.RunBlockTest(file)
|
||||
case "bt", "BlockTest", "BlockTests", "BlockChainTest":
|
||||
err = tests.RunBlockTestWithReader(r)
|
||||
case "st", "state", "StateTest", "StateTests":
|
||||
err = tests.RunStateTest(file)
|
||||
err = tests.RunStateTestWithReader(r)
|
||||
case "tx", "TransactionTest", "TransactionTests":
|
||||
err = tests.RunTransactionTests(file)
|
||||
err = tests.RunTransactionTestsWithReader(r)
|
||||
case "vm", "VMTest", "VMTests":
|
||||
err = tests.RunVmTest(file)
|
||||
err = tests.RunVmTestWithReader(r)
|
||||
default:
|
||||
err = fmt.Errorf("Invalid test type specified:", test)
|
||||
err = fmt.Errorf("Invalid test type specified: %v", test)
|
||||
}
|
||||
return err
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getFiles(path string) ([]string, error) {
|
||||
// glog.Infoln("getFiles", path)
|
||||
glog.Infoln("getFiles", path)
|
||||
var files []string
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
@ -97,7 +107,7 @@ func getFiles(path string) ([]string, error) {
|
||||
// only go 1 depth and leave directory entires blank
|
||||
if !v.IsDir() && v.Name()[len(v.Name())-len(testExtension):len(v.Name())] == testExtension {
|
||||
files[i] = filepath.Join(path, v.Name())
|
||||
// glog.Infoln("Found file", files[i])
|
||||
glog.Infoln("Found file", files[i])
|
||||
}
|
||||
}
|
||||
case mode.IsRegular():
|
||||
@ -118,7 +128,7 @@ func runSuite(test, file string) {
|
||||
}
|
||||
|
||||
for _, curTest := range tests {
|
||||
// glog.Infoln("runSuite", curTest, file)
|
||||
glog.Infoln("runSuite", curTest, file)
|
||||
var err error
|
||||
var files []string
|
||||
if test == defaultTest {
|
||||
@ -134,16 +144,19 @@ func runSuite(test, file string) {
|
||||
if len(files) == 0 {
|
||||
glog.Warningln("No files matched path")
|
||||
}
|
||||
for _, testfile := range files {
|
||||
for _, curFile := range files {
|
||||
// Skip blank entries
|
||||
if len(testfile) == 0 {
|
||||
if len(curFile) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO allow io.Reader to be passed so Stdin can be piped
|
||||
// RunVmTest(strings.NewReader(os.Args[2]))
|
||||
// RunVmTest(os.Stdin)
|
||||
err := runTest(curTest, testfile)
|
||||
r, err := os.Open(curFile)
|
||||
if err != nil {
|
||||
glog.Fatalln(err)
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
err = runTestWithReader(curTest, r)
|
||||
if err != nil {
|
||||
if continueOnError {
|
||||
glog.Errorln(err)
|
||||
@ -160,8 +173,16 @@ func setupApp(c *cli.Context) {
|
||||
flagTest := c.GlobalString(TestFlag.Name)
|
||||
flagFile := c.GlobalString(FileFlag.Name)
|
||||
continueOnError = c.GlobalBool(ContinueOnErrorFlag.Name)
|
||||
useStdIn := c.GlobalBool(ReadStdInFlag.Name)
|
||||
|
||||
runSuite(flagTest, flagFile)
|
||||
if !useStdIn {
|
||||
runSuite(flagTest, flagFile)
|
||||
} else {
|
||||
if err := runTestWithReader(flagTest, os.Stdin); err != nil {
|
||||
glog.Fatalln(err)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
@ -178,6 +199,7 @@ func main() {
|
||||
TestFlag,
|
||||
FileFlag,
|
||||
ContinueOnErrorFlag,
|
||||
ReadStdInFlag,
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@ -85,15 +86,42 @@ type btTransaction struct {
|
||||
Value string
|
||||
}
|
||||
|
||||
func RunBlockTest(filepath string) error {
|
||||
bt, err := LoadBlockTests(filepath)
|
||||
func RunBlockTestWithReader(r io.Reader) error {
|
||||
btjs := make(map[string]*btJSON)
|
||||
if err := readJson(r, &btjs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bt, err := convertBlockTests(btjs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// map skipped tests to boolean set
|
||||
skipTest := make(map[string]bool, len(blockSkipTests))
|
||||
for _, name := range blockSkipTests {
|
||||
if err := runBlockTests(bt); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunBlockTest(file string) error {
|
||||
btjs := make(map[string]*btJSON)
|
||||
if err := readJsonFile(file, &btjs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bt, err := convertBlockTests(btjs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := runBlockTests(bt); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runBlockTests(bt map[string]*BlockTest) error {
|
||||
skipTest := make(map[string]bool, len(BlockSkipTests))
|
||||
for _, name := range BlockSkipTests {
|
||||
skipTest[name] = true
|
||||
}
|
||||
|
||||
@ -103,17 +131,19 @@ func RunBlockTest(filepath string) error {
|
||||
glog.Infoln("Skipping block test", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// test the block
|
||||
if err := testBlock(test); err != nil {
|
||||
if err := runBlockTest(test); err != nil {
|
||||
return err
|
||||
}
|
||||
glog.Infoln("Block test passed: ", name)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func testBlock(test *BlockTest) error {
|
||||
cfg := testEthConfig()
|
||||
}
|
||||
func runBlockTest(test *BlockTest) error {
|
||||
cfg := test.makeEthConfig()
|
||||
ethereum, err := eth.New(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -144,7 +174,7 @@ func testBlock(test *BlockTest) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func testEthConfig() *eth.Config {
|
||||
func (test *BlockTest) makeEthConfig() *eth.Config {
|
||||
ks := crypto.NewKeyStorePassphrase(filepath.Join(common.DefaultDataDir(), "keystore"))
|
||||
|
||||
return ð.Config{
|
||||
@ -230,7 +260,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
|
||||
if b.BlockHeader == nil {
|
||||
return fmt.Errorf("Block insertion should have failed")
|
||||
}
|
||||
err = validateBlockHeader(b.BlockHeader, cb.Header())
|
||||
err = t.validateBlockHeader(b.BlockHeader, cb.Header())
|
||||
if err != nil {
|
||||
return fmt.Errorf("Block header validation failed: ", err)
|
||||
}
|
||||
@ -238,7 +268,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateBlockHeader(h *btHeader, h2 *types.Header) error {
|
||||
func (s *BlockTest) validateBlockHeader(h *btHeader, h2 *types.Header) error {
|
||||
expectedBloom := mustConvertBytes(h.Bloom)
|
||||
if !bytes.Equal(expectedBloom, h2.Bloom.Bytes()) {
|
||||
return fmt.Errorf("Bloom: expected: %v, decoded: %v", expectedBloom, h2.Bloom.Bytes())
|
||||
@ -341,7 +371,18 @@ func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertTest(in *btJSON) (out *BlockTest, err error) {
|
||||
func convertBlockTests(in map[string]*btJSON) (map[string]*BlockTest, error) {
|
||||
out := make(map[string]*BlockTest)
|
||||
for name, test := range in {
|
||||
var err error
|
||||
if out[name], err = convertBlockTest(test); err != nil {
|
||||
return out, fmt.Errorf("bad test %q: %v", name, err)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func convertBlockTest(in *btJSON) (out *BlockTest, err error) {
|
||||
// the conversion handles errors by catching panics.
|
||||
// you might consider this ugly, but the alternative (passing errors)
|
||||
// would be much harder to read.
|
||||
@ -450,19 +491,12 @@ func mustConvertUint(in string, base int) uint64 {
|
||||
}
|
||||
|
||||
func LoadBlockTests(file string) (map[string]*BlockTest, error) {
|
||||
bt := make(map[string]*btJSON)
|
||||
if err := readTestFile(file, &bt); err != nil {
|
||||
btjs := make(map[string]*btJSON)
|
||||
if err := readJsonFile(file, &btjs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := make(map[string]*BlockTest)
|
||||
for name, in := range bt {
|
||||
var err error
|
||||
if out[name], err = convertTest(in); err != nil {
|
||||
return out, fmt.Errorf("bad test %q: %v", name, err)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
return convertBlockTests(btjs)
|
||||
}
|
||||
|
||||
// Nothing to see here, please move along...
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
// "github.com/ethereum/go-ethereum/logger/glog"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -17,13 +19,40 @@ var (
|
||||
transactionTestDir = filepath.Join(baseDir, "TransactionTests")
|
||||
vmTestDir = filepath.Join(baseDir, "VMTests")
|
||||
|
||||
blockSkipTests = []string{"SimpleTx3"}
|
||||
transSkipTests = []string{"TransactionWithHihghNonce256"}
|
||||
stateSkipTests = []string{"mload32bitBound_return", "mload32bitBound_return2"}
|
||||
vmSkipTests = []string{}
|
||||
BlockSkipTests = []string{"SimpleTx3"}
|
||||
TransSkipTests = []string{"TransactionWithHihghNonce256"}
|
||||
StateSkipTests = []string{"mload32bitBound_return", "mload32bitBound_return2"}
|
||||
VmSkipTests = []string{}
|
||||
)
|
||||
|
||||
func readJSON(reader io.Reader, value interface{}) error {
|
||||
// type TestRunner interface {
|
||||
// // LoadTest()
|
||||
// RunTest() error
|
||||
// }
|
||||
|
||||
// func RunTests(bt map[string]TestRunner, skipTests []string) error {
|
||||
// // map skipped tests to boolean set
|
||||
// skipTest := make(map[string]bool, len(skipTests))
|
||||
// for _, name := range skipTests {
|
||||
// skipTest[name] = true
|
||||
// }
|
||||
|
||||
// for name, test := range bt {
|
||||
// // if the test should be skipped, return
|
||||
// if skipTest[name] {
|
||||
// glog.Infoln("Skipping block test", name)
|
||||
// return nil
|
||||
// }
|
||||
// // test the block
|
||||
// if err := test.RunTest(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// glog.Infoln("Block test passed: ", name)
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func readJson(reader io.Reader, value interface{}) error {
|
||||
data, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading JSON file", err.Error())
|
||||
@ -39,6 +68,34 @@ func readJSON(reader io.Reader, value interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func readJsonHttp(uri string, value interface{}) error {
|
||||
resp, err := http.Get(uri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
err = readJson(resp.Body, value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readJsonFile(fn string, value interface{}) error {
|
||||
file, err := os.Open(fn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
err = readJson(file, value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s in file %s", err.Error(), fn)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// findLine returns the line number for the given offset into data.
|
||||
func findLine(data []byte, offset int64) (line int) {
|
||||
line = 1
|
||||
@ -52,31 +109,3 @@ func findLine(data []byte, offset int64) (line int) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func readHttpFile(uri string, value interface{}) error {
|
||||
resp, err := http.Get(uri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
err = readJSON(resp.Body, value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readTestFile(fn string, value interface{}) error {
|
||||
file, err := os.Open(fn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
err = readJSON(file, value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s in file %s", err.Error(), fn)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package tests
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
@ -15,101 +16,134 @@ import (
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
)
|
||||
|
||||
func RunStateTest(p string) error {
|
||||
skipTest := make(map[string]bool, len(stateSkipTests))
|
||||
for _, name := range stateSkipTests {
|
||||
skipTest[name] = true
|
||||
func RunStateTestWithReader(r io.Reader) error {
|
||||
tests := make(map[string]VmTest)
|
||||
if err := readJson(r, &tests); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := runStateTests(tests); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunStateTest(p string) error {
|
||||
tests := make(map[string]VmTest)
|
||||
readTestFile(p, &tests)
|
||||
if err := readJsonFile(p, &tests); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := runStateTests(tests); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func runStateTests(tests map[string]VmTest) error {
|
||||
skipTest := make(map[string]bool, len(StateSkipTests))
|
||||
for _, name := range StateSkipTests {
|
||||
skipTest[name] = true
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
if skipTest[name] {
|
||||
glog.Infoln("Skipping state test", name)
|
||||
return nil
|
||||
}
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb := state.New(common.Hash{}, db)
|
||||
for addr, account := range test.Pre {
|
||||
obj := StateObjectFromAccount(db, addr, account)
|
||||
statedb.SetStateObject(obj)
|
||||
for a, v := range account.Storage {
|
||||
obj.SetState(common.HexToHash(a), common.HexToHash(s))
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Yeah, yeah...
|
||||
env := make(map[string]string)
|
||||
env["currentCoinbase"] = test.Env.CurrentCoinbase
|
||||
env["currentDifficulty"] = test.Env.CurrentDifficulty
|
||||
env["currentGasLimit"] = test.Env.CurrentGasLimit
|
||||
env["currentNumber"] = test.Env.CurrentNumber
|
||||
env["previousHash"] = test.Env.PreviousHash
|
||||
if n, ok := test.Env.CurrentTimestamp.(float64); ok {
|
||||
env["currentTimestamp"] = strconv.Itoa(int(n))
|
||||
} else {
|
||||
env["currentTimestamp"] = test.Env.CurrentTimestamp.(string)
|
||||
}
|
||||
|
||||
var (
|
||||
ret []byte
|
||||
// gas *big.Int
|
||||
// err error
|
||||
logs state.Logs
|
||||
)
|
||||
|
||||
ret, logs, _, _ = RunState(statedb, env, test.Transaction)
|
||||
|
||||
// // Compare expected and actual return
|
||||
rexp := common.FromHex(test.Out)
|
||||
if bytes.Compare(rexp, ret) != 0 {
|
||||
return fmt.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret)
|
||||
}
|
||||
|
||||
// check post state
|
||||
for addr, account := range test.Post {
|
||||
obj := statedb.GetStateObject(common.HexToAddress(addr))
|
||||
if obj == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if obj.Balance().Cmp(common.Big(account.Balance)) != 0 {
|
||||
return fmt.Errorf("%s's : (%x) balance failed. Expected %v, got %v => %v\n", name, obj.Address().Bytes()[:4], account.Balance, obj.Balance(), new(big.Int).Sub(common.Big(account.Balance), obj.Balance()))
|
||||
}
|
||||
|
||||
if obj.Nonce() != common.String2Big(account.Nonce).Uint64() {
|
||||
return fmt.Errorf("%s's : (%x) nonce failed. Expected %v, got %v\n", name, obj.Address().Bytes()[:4], account.Nonce, obj.Nonce())
|
||||
}
|
||||
|
||||
for addr, value := range account.Storage {
|
||||
v := obj.GetState(common.HexToHash(addr)).Bytes()
|
||||
vexp := common.FromHex(value)
|
||||
|
||||
if bytes.Compare(v, vexp) != 0 {
|
||||
return fmt.Errorf("%s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)\n", name, obj.Address().Bytes()[0:4], addr, vexp, v, common.BigD(vexp), common.BigD(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
statedb.Sync()
|
||||
//if !bytes.Equal(common.Hex2Bytes(test.PostStateRoot), statedb.Root()) {
|
||||
if common.HexToHash(test.PostStateRoot) != statedb.Root() {
|
||||
return fmt.Errorf("%s's : Post state root error. Expected %s, got %x", name, test.PostStateRoot, statedb.Root())
|
||||
}
|
||||
|
||||
// check logs
|
||||
if len(test.Logs) > 0 {
|
||||
lerr := checkLogs(test.Logs, logs)
|
||||
if lerr != nil {
|
||||
return fmt.Errorf("'%s' ", name, lerr.Error())
|
||||
}
|
||||
if err := runStateTest(test); err != nil {
|
||||
return fmt.Errorf("%s: %s\n", name, err.Error())
|
||||
}
|
||||
|
||||
glog.Infoln("State test passed: ", name)
|
||||
//fmt.Println(string(statedb.Dump()))
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func runStateTest(test VmTest) error {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb := state.New(common.Hash{}, db)
|
||||
for addr, account := range test.Pre {
|
||||
obj := StateObjectFromAccount(db, addr, account)
|
||||
statedb.SetStateObject(obj)
|
||||
for a, v := range account.Storage {
|
||||
obj.SetState(common.HexToHash(a), common.HexToHash(v))
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Yeah, yeah...
|
||||
env := make(map[string]string)
|
||||
env["currentCoinbase"] = test.Env.CurrentCoinbase
|
||||
env["currentDifficulty"] = test.Env.CurrentDifficulty
|
||||
env["currentGasLimit"] = test.Env.CurrentGasLimit
|
||||
env["currentNumber"] = test.Env.CurrentNumber
|
||||
env["previousHash"] = test.Env.PreviousHash
|
||||
if n, ok := test.Env.CurrentTimestamp.(float64); ok {
|
||||
env["currentTimestamp"] = strconv.Itoa(int(n))
|
||||
} else {
|
||||
env["currentTimestamp"] = test.Env.CurrentTimestamp.(string)
|
||||
}
|
||||
|
||||
var (
|
||||
ret []byte
|
||||
// gas *big.Int
|
||||
// err error
|
||||
logs state.Logs
|
||||
)
|
||||
|
||||
ret, logs, _, _ = RunState(statedb, env, test.Transaction)
|
||||
|
||||
// // Compare expected and actual return
|
||||
rexp := common.FromHex(test.Out)
|
||||
if bytes.Compare(rexp, ret) != 0 {
|
||||
return fmt.Errorf("return failed. Expected %x, got %x\n", rexp, ret)
|
||||
}
|
||||
|
||||
// check post state
|
||||
for addr, account := range test.Post {
|
||||
obj := statedb.GetStateObject(common.HexToAddress(addr))
|
||||
if obj == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if obj.Balance().Cmp(common.Big(account.Balance)) != 0 {
|
||||
return fmt.Errorf("(%x) balance failed. Expected %v, got %v => %v\n", obj.Address().Bytes()[:4], account.Balance, obj.Balance(), new(big.Int).Sub(common.Big(account.Balance), obj.Balance()))
|
||||
}
|
||||
|
||||
if obj.Nonce() != common.String2Big(account.Nonce).Uint64() {
|
||||
return fmt.Errorf("(%x) nonce failed. Expected %v, got %v\n", obj.Address().Bytes()[:4], account.Nonce, obj.Nonce())
|
||||
}
|
||||
|
||||
for addr, value := range account.Storage {
|
||||
v := obj.GetState(common.HexToHash(addr)).Bytes()
|
||||
vexp := common.FromHex(value)
|
||||
|
||||
if bytes.Compare(v, vexp) != 0 {
|
||||
return fmt.Errorf("(%x: %s) storage failed. Expected %x, got %x (%v %v)\n", obj.Address().Bytes()[0:4], addr, vexp, v, common.BigD(vexp), common.BigD(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
statedb.Sync()
|
||||
//if !bytes.Equal(common.Hex2Bytes(test.PostStateRoot), statedb.Root()) {
|
||||
if common.HexToHash(test.PostStateRoot) != statedb.Root() {
|
||||
return fmt.Errorf("Post state root error. Expected %s, got %x", test.PostStateRoot, statedb.Root())
|
||||
}
|
||||
|
||||
// check logs
|
||||
if len(test.Logs) > 0 {
|
||||
if err := checkLogs(test.Logs, logs); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@ -31,14 +32,14 @@ type TransactionTest struct {
|
||||
Transaction TtTransaction
|
||||
}
|
||||
|
||||
func RunTransactionTests(file string) error {
|
||||
skipTest := make(map[string]bool, len(transSkipTests))
|
||||
for _, name := range transSkipTests {
|
||||
func RunTransactionTestsWithReader(r io.Reader) error {
|
||||
skipTest := make(map[string]bool, len(TransSkipTests))
|
||||
for _, name := range TransSkipTests {
|
||||
skipTest[name] = true
|
||||
}
|
||||
|
||||
bt := make(map[string]TransactionTest)
|
||||
if err := readTestFile(file, &bt); err != nil {
|
||||
if err := readJson(r, &bt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -49,7 +50,7 @@ func RunTransactionTests(file string) error {
|
||||
return nil
|
||||
}
|
||||
// test the block
|
||||
if err := runTest(test); err != nil {
|
||||
if err := runTransactionTest(test); err != nil {
|
||||
return err
|
||||
}
|
||||
glog.Infoln("Transaction test passed: ", name)
|
||||
@ -58,7 +59,35 @@ func RunTransactionTests(file string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runTest(txTest TransactionTest) (err error) {
|
||||
func RunTransactionTests(file string) error {
|
||||
skipTest := make(map[string]bool, len(TransSkipTests))
|
||||
for _, name := range TransSkipTests {
|
||||
skipTest[name] = true
|
||||
}
|
||||
|
||||
bt := make(map[string]TransactionTest)
|
||||
if err := readJsonFile(file, &bt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for name, test := range bt {
|
||||
// if the test should be skipped, return
|
||||
if skipTest[name] {
|
||||
glog.Infoln("Skipping transaction test", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// test the block
|
||||
if err := runTransactionTest(test); err != nil {
|
||||
return err
|
||||
}
|
||||
glog.Infoln("Transaction test passed: ", name)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runTransactionTest(txTest TransactionTest) (err error) {
|
||||
tx := new(types.Transaction)
|
||||
err = rlp.DecodeBytes(mustConvertBytes(txTest.Rlp), tx)
|
||||
|
||||
|
@ -3,6 +3,7 @@ package tests
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
@ -13,94 +14,53 @@ import (
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
)
|
||||
|
||||
func RunVmTest(p string) error {
|
||||
skipTest := make(map[string]bool, len(vmSkipTests))
|
||||
for _, name := range vmSkipTests {
|
||||
skipTest[name] = true
|
||||
}
|
||||
|
||||
func RunVmTestWithReader(r io.Reader) error {
|
||||
tests := make(map[string]VmTest)
|
||||
err := readTestFile(p, &tests)
|
||||
err := readJson(r, &tests)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := runVmTests(tests); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunVmTest(p string) error {
|
||||
|
||||
tests := make(map[string]VmTest)
|
||||
err := readJsonFile(p, &tests)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := runVmTests(tests); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runVmTests(tests map[string]VmTest) error {
|
||||
skipTest := make(map[string]bool, len(VmSkipTests))
|
||||
for _, name := range VmSkipTests {
|
||||
skipTest[name] = true
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
if skipTest[name] {
|
||||
glog.Infoln("Skipping VM test", name)
|
||||
return nil
|
||||
}
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb := state.New(common.Hash{}, db)
|
||||
for addr, account := range test.Pre {
|
||||
obj := StateObjectFromAccount(db, addr, account)
|
||||
statedb.SetStateObject(obj)
|
||||
for a, v := range account.Storage {
|
||||
obj.SetState(common.HexToHash(a), common.HexToHash(v))
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Yeah, yeah...
|
||||
env := make(map[string]string)
|
||||
env["currentCoinbase"] = test.Env.CurrentCoinbase
|
||||
env["currentDifficulty"] = test.Env.CurrentDifficulty
|
||||
env["currentGasLimit"] = test.Env.CurrentGasLimit
|
||||
env["currentNumber"] = test.Env.CurrentNumber
|
||||
env["previousHash"] = test.Env.PreviousHash
|
||||
if n, ok := test.Env.CurrentTimestamp.(float64); ok {
|
||||
env["currentTimestamp"] = strconv.Itoa(int(n))
|
||||
} else {
|
||||
env["currentTimestamp"] = test.Env.CurrentTimestamp.(string)
|
||||
}
|
||||
|
||||
var (
|
||||
ret []byte
|
||||
gas *big.Int
|
||||
err error
|
||||
logs state.Logs
|
||||
)
|
||||
|
||||
ret, logs, gas, err = RunVm(statedb, env, test.Exec)
|
||||
|
||||
// Compare expectedand actual return
|
||||
rexp := common.FromHex(test.Out)
|
||||
if bytes.Compare(rexp, ret) != 0 {
|
||||
return fmt.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret)
|
||||
}
|
||||
|
||||
// Check gas usage
|
||||
if len(test.Gas) == 0 && err == nil {
|
||||
return fmt.Errorf("%s's gas unspecified, indicating an error. VM returned (incorrectly) successfull", name)
|
||||
} else {
|
||||
gexp := common.Big(test.Gas)
|
||||
if gexp.Cmp(gas) != 0 {
|
||||
return fmt.Errorf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas)
|
||||
}
|
||||
}
|
||||
|
||||
// check post state
|
||||
for addr, account := range test.Post {
|
||||
obj := statedb.GetStateObject(common.HexToAddress(addr))
|
||||
if obj == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for addr, value := range account.Storage {
|
||||
v := obj.GetState(common.HexToHash(addr))
|
||||
vexp := common.HexToHash(value)
|
||||
|
||||
if v != vexp {
|
||||
return t.Errorf("%s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)\n", name, obj.Address().Bytes()[0:4], addr, vexp, v, vexp.Big(), v.Big())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check logs
|
||||
if len(test.Logs) > 0 {
|
||||
lerr := checkLogs(test.Logs, logs)
|
||||
if lerr != nil {
|
||||
return fmt.Errorf("'%s' ", name, lerr.Error())
|
||||
}
|
||||
if err := runVmTest(test); err != nil {
|
||||
return fmt.Errorf("%s %s", name, err.Error())
|
||||
}
|
||||
|
||||
glog.Infoln("VM test passed: ", name)
|
||||
@ -109,6 +69,83 @@ func RunVmTest(p string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runVmTest(test VmTest) error {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb := state.New(common.Hash{}, db)
|
||||
for addr, account := range test.Pre {
|
||||
obj := StateObjectFromAccount(db, addr, account)
|
||||
statedb.SetStateObject(obj)
|
||||
for a, v := range account.Storage {
|
||||
obj.SetState(common.HexToHash(a), common.HexToHash(v))
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Yeah, yeah...
|
||||
env := make(map[string]string)
|
||||
env["currentCoinbase"] = test.Env.CurrentCoinbase
|
||||
env["currentDifficulty"] = test.Env.CurrentDifficulty
|
||||
env["currentGasLimit"] = test.Env.CurrentGasLimit
|
||||
env["currentNumber"] = test.Env.CurrentNumber
|
||||
env["previousHash"] = test.Env.PreviousHash
|
||||
if n, ok := test.Env.CurrentTimestamp.(float64); ok {
|
||||
env["currentTimestamp"] = strconv.Itoa(int(n))
|
||||
} else {
|
||||
env["currentTimestamp"] = test.Env.CurrentTimestamp.(string)
|
||||
}
|
||||
|
||||
var (
|
||||
ret []byte
|
||||
gas *big.Int
|
||||
err error
|
||||
logs state.Logs
|
||||
)
|
||||
|
||||
ret, logs, gas, err = RunVm(statedb, env, test.Exec)
|
||||
|
||||
// Compare expectedand actual return
|
||||
rexp := common.FromHex(test.Out)
|
||||
if bytes.Compare(rexp, ret) != 0 {
|
||||
return fmt.Errorf("return failed. Expected %x, got %x\n", rexp, ret)
|
||||
}
|
||||
|
||||
// Check gas usage
|
||||
if len(test.Gas) == 0 && err == nil {
|
||||
return fmt.Errorf("gas unspecified, indicating an error. VM returned (incorrectly) successfull")
|
||||
} else {
|
||||
gexp := common.Big(test.Gas)
|
||||
if gexp.Cmp(gas) != 0 {
|
||||
return fmt.Errorf("gas failed. Expected %v, got %v\n", gexp, gas)
|
||||
}
|
||||
}
|
||||
|
||||
// check post state
|
||||
for addr, account := range test.Post {
|
||||
obj := statedb.GetStateObject(common.HexToAddress(addr))
|
||||
if obj == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for addr, value := range account.Storage {
|
||||
v := obj.GetState(common.HexToHash(addr))
|
||||
vexp := common.HexToHash(value)
|
||||
|
||||
if v != vexp {
|
||||
return fmt.Errorf("(%x: %s) storage failed. Expected %x, got %x (%v %v)\n", obj.Address().Bytes()[0:4], addr, vexp, v, vexp.BigD(vexp), v.Big(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check logs
|
||||
if len(test.Logs) > 0 {
|
||||
lerr := checkLogs(test.Logs, logs)
|
||||
if lerr != nil {
|
||||
return lerr
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Logs, *big.Int, error) {
|
||||
var (
|
||||
to = common.HexToAddress(exec["address"])
|
||||
|
Loading…
Reference in New Issue
Block a user