Add stdin option
This commit is contained in:
parent
a86452d22c
commit
01ec4dbb12
@ -24,6 +24,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -55,28 +56,37 @@ var (
|
|||||||
Name: "continue",
|
Name: "continue",
|
||||||
Usage: "Continue running tests on error (true) or [default] exit immediately (false)",
|
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 {
|
func runTestWithReader(test string, r io.Reader) error {
|
||||||
// glog.Infoln("runTest", test, file)
|
glog.Infoln("runTest", test)
|
||||||
var err error
|
var err error
|
||||||
switch test {
|
switch test {
|
||||||
case "bc", "BlockTest", "BlockTests", "BlockChainTest":
|
case "bt", "BlockTest", "BlockTests", "BlockChainTest":
|
||||||
err = tests.RunBlockTest(file)
|
err = tests.RunBlockTestWithReader(r)
|
||||||
case "st", "state", "StateTest", "StateTests":
|
case "st", "state", "StateTest", "StateTests":
|
||||||
err = tests.RunStateTest(file)
|
err = tests.RunStateTestWithReader(r)
|
||||||
case "tx", "TransactionTest", "TransactionTests":
|
case "tx", "TransactionTest", "TransactionTests":
|
||||||
err = tests.RunTransactionTests(file)
|
err = tests.RunTransactionTestsWithReader(r)
|
||||||
case "vm", "VMTest", "VMTests":
|
case "vm", "VMTest", "VMTests":
|
||||||
err = tests.RunVmTest(file)
|
err = tests.RunVmTestWithReader(r)
|
||||||
default:
|
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) {
|
func getFiles(path string) ([]string, error) {
|
||||||
// glog.Infoln("getFiles", path)
|
glog.Infoln("getFiles", path)
|
||||||
var files []string
|
var files []string
|
||||||
f, err := os.Open(path)
|
f, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -97,7 +107,7 @@ func getFiles(path string) ([]string, error) {
|
|||||||
// only go 1 depth and leave directory entires blank
|
// only go 1 depth and leave directory entires blank
|
||||||
if !v.IsDir() && v.Name()[len(v.Name())-len(testExtension):len(v.Name())] == testExtension {
|
if !v.IsDir() && v.Name()[len(v.Name())-len(testExtension):len(v.Name())] == testExtension {
|
||||||
files[i] = filepath.Join(path, v.Name())
|
files[i] = filepath.Join(path, v.Name())
|
||||||
// glog.Infoln("Found file", files[i])
|
glog.Infoln("Found file", files[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case mode.IsRegular():
|
case mode.IsRegular():
|
||||||
@ -118,7 +128,7 @@ func runSuite(test, file string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, curTest := range tests {
|
for _, curTest := range tests {
|
||||||
// glog.Infoln("runSuite", curTest, file)
|
glog.Infoln("runSuite", curTest, file)
|
||||||
var err error
|
var err error
|
||||||
var files []string
|
var files []string
|
||||||
if test == defaultTest {
|
if test == defaultTest {
|
||||||
@ -134,16 +144,19 @@ func runSuite(test, file string) {
|
|||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
glog.Warningln("No files matched path")
|
glog.Warningln("No files matched path")
|
||||||
}
|
}
|
||||||
for _, testfile := range files {
|
for _, curFile := range files {
|
||||||
// Skip blank entries
|
// Skip blank entries
|
||||||
if len(testfile) == 0 {
|
if len(curFile) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO allow io.Reader to be passed so Stdin can be piped
|
r, err := os.Open(curFile)
|
||||||
// RunVmTest(strings.NewReader(os.Args[2]))
|
if err != nil {
|
||||||
// RunVmTest(os.Stdin)
|
glog.Fatalln(err)
|
||||||
err := runTest(curTest, testfile)
|
}
|
||||||
|
defer r.Close()
|
||||||
|
|
||||||
|
err = runTestWithReader(curTest, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if continueOnError {
|
if continueOnError {
|
||||||
glog.Errorln(err)
|
glog.Errorln(err)
|
||||||
@ -160,8 +173,16 @@ func setupApp(c *cli.Context) {
|
|||||||
flagTest := c.GlobalString(TestFlag.Name)
|
flagTest := c.GlobalString(TestFlag.Name)
|
||||||
flagFile := c.GlobalString(FileFlag.Name)
|
flagFile := c.GlobalString(FileFlag.Name)
|
||||||
continueOnError = c.GlobalBool(ContinueOnErrorFlag.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() {
|
func main() {
|
||||||
@ -178,6 +199,7 @@ func main() {
|
|||||||
TestFlag,
|
TestFlag,
|
||||||
FileFlag,
|
FileFlag,
|
||||||
ContinueOnErrorFlag,
|
ContinueOnErrorFlag,
|
||||||
|
ReadStdInFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := app.Run(os.Args); err != nil {
|
if err := app.Run(os.Args); err != nil {
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -85,15 +86,42 @@ type btTransaction struct {
|
|||||||
Value string
|
Value string
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunBlockTest(filepath string) error {
|
func RunBlockTestWithReader(r io.Reader) error {
|
||||||
bt, err := LoadBlockTests(filepath)
|
btjs := make(map[string]*btJSON)
|
||||||
|
if err := readJson(r, &btjs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
bt, err := convertBlockTests(btjs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// map skipped tests to boolean set
|
if err := runBlockTests(bt); err != nil {
|
||||||
skipTest := make(map[string]bool, len(blockSkipTests))
|
return err
|
||||||
for _, name := range blockSkipTests {
|
}
|
||||||
|
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
|
skipTest[name] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,17 +131,19 @@ func RunBlockTest(filepath string) error {
|
|||||||
glog.Infoln("Skipping block test", name)
|
glog.Infoln("Skipping block test", name)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// test the block
|
// test the block
|
||||||
if err := testBlock(test); err != nil {
|
if err := runBlockTest(test); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
glog.Infoln("Block test passed: ", name)
|
glog.Infoln("Block test passed: ", name)
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
|
||||||
|
|
||||||
func testBlock(test *BlockTest) error {
|
}
|
||||||
cfg := testEthConfig()
|
func runBlockTest(test *BlockTest) error {
|
||||||
|
cfg := test.makeEthConfig()
|
||||||
ethereum, err := eth.New(cfg)
|
ethereum, err := eth.New(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -144,7 +174,7 @@ func testBlock(test *BlockTest) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func testEthConfig() *eth.Config {
|
func (test *BlockTest) makeEthConfig() *eth.Config {
|
||||||
ks := crypto.NewKeyStorePassphrase(filepath.Join(common.DefaultDataDir(), "keystore"))
|
ks := crypto.NewKeyStorePassphrase(filepath.Join(common.DefaultDataDir(), "keystore"))
|
||||||
|
|
||||||
return ð.Config{
|
return ð.Config{
|
||||||
@ -230,7 +260,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
|
|||||||
if b.BlockHeader == nil {
|
if b.BlockHeader == nil {
|
||||||
return fmt.Errorf("Block insertion should have failed")
|
return fmt.Errorf("Block insertion should have failed")
|
||||||
}
|
}
|
||||||
err = validateBlockHeader(b.BlockHeader, cb.Header())
|
err = t.validateBlockHeader(b.BlockHeader, cb.Header())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Block header validation failed: ", err)
|
return fmt.Errorf("Block header validation failed: ", err)
|
||||||
}
|
}
|
||||||
@ -238,7 +268,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateBlockHeader(h *btHeader, h2 *types.Header) error {
|
func (s *BlockTest) validateBlockHeader(h *btHeader, h2 *types.Header) error {
|
||||||
expectedBloom := mustConvertBytes(h.Bloom)
|
expectedBloom := mustConvertBytes(h.Bloom)
|
||||||
if !bytes.Equal(expectedBloom, h2.Bloom.Bytes()) {
|
if !bytes.Equal(expectedBloom, h2.Bloom.Bytes()) {
|
||||||
return fmt.Errorf("Bloom: expected: %v, decoded: %v", 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
|
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.
|
// the conversion handles errors by catching panics.
|
||||||
// you might consider this ugly, but the alternative (passing errors)
|
// you might consider this ugly, but the alternative (passing errors)
|
||||||
// would be much harder to read.
|
// 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) {
|
func LoadBlockTests(file string) (map[string]*BlockTest, error) {
|
||||||
bt := make(map[string]*btJSON)
|
btjs := make(map[string]*btJSON)
|
||||||
if err := readTestFile(file, &bt); err != nil {
|
if err := readJsonFile(file, &btjs); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
out := make(map[string]*BlockTest)
|
return convertBlockTests(btjs)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing to see here, please move along...
|
// Nothing to see here, please move along...
|
||||||
|
@ -8,6 +8,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
// "github.com/ethereum/go-ethereum/logger/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -17,13 +19,40 @@ var (
|
|||||||
transactionTestDir = filepath.Join(baseDir, "TransactionTests")
|
transactionTestDir = filepath.Join(baseDir, "TransactionTests")
|
||||||
vmTestDir = filepath.Join(baseDir, "VMTests")
|
vmTestDir = filepath.Join(baseDir, "VMTests")
|
||||||
|
|
||||||
blockSkipTests = []string{"SimpleTx3"}
|
BlockSkipTests = []string{"SimpleTx3"}
|
||||||
transSkipTests = []string{"TransactionWithHihghNonce256"}
|
TransSkipTests = []string{"TransactionWithHihghNonce256"}
|
||||||
stateSkipTests = []string{"mload32bitBound_return", "mload32bitBound_return2"}
|
StateSkipTests = []string{"mload32bitBound_return", "mload32bitBound_return2"}
|
||||||
vmSkipTests = []string{}
|
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)
|
data, err := ioutil.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error reading JSON file", err.Error())
|
return fmt.Errorf("Error reading JSON file", err.Error())
|
||||||
@ -39,6 +68,34 @@ func readJSON(reader io.Reader, value interface{}) error {
|
|||||||
return nil
|
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.
|
// findLine returns the line number for the given offset into data.
|
||||||
func findLine(data []byte, offset int64) (line int) {
|
func findLine(data []byte, offset int64) (line int) {
|
||||||
line = 1
|
line = 1
|
||||||
@ -52,31 +109,3 @@ func findLine(data []byte, offset int64) (line int) {
|
|||||||
}
|
}
|
||||||
return
|
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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@ -15,101 +16,134 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RunStateTest(p string) error {
|
func RunStateTestWithReader(r io.Reader) error {
|
||||||
skipTest := make(map[string]bool, len(stateSkipTests))
|
tests := make(map[string]VmTest)
|
||||||
for _, name := range stateSkipTests {
|
if err := readJson(r, &tests); err != nil {
|
||||||
skipTest[name] = true
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := runStateTests(tests); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunStateTest(p string) error {
|
||||||
tests := make(map[string]VmTest)
|
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 {
|
for name, test := range tests {
|
||||||
if skipTest[name] {
|
if skipTest[name] {
|
||||||
glog.Infoln("Skipping state test", name)
|
glog.Infoln("Skipping state test", name)
|
||||||
return nil
|
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...
|
if err := runStateTest(test); err != nil {
|
||||||
env := make(map[string]string)
|
return fmt.Errorf("%s: %s\n", name, err.Error())
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.Infoln("State test passed: ", name)
|
glog.Infoln("State test passed: ", name)
|
||||||
//fmt.Println(string(statedb.Dump()))
|
//fmt.Println(string(statedb.Dump()))
|
||||||
}
|
}
|
||||||
return nil
|
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) {
|
func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) {
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -31,14 +32,14 @@ type TransactionTest struct {
|
|||||||
Transaction TtTransaction
|
Transaction TtTransaction
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunTransactionTests(file string) error {
|
func RunTransactionTestsWithReader(r io.Reader) error {
|
||||||
skipTest := make(map[string]bool, len(transSkipTests))
|
skipTest := make(map[string]bool, len(TransSkipTests))
|
||||||
for _, name := range transSkipTests {
|
for _, name := range TransSkipTests {
|
||||||
skipTest[name] = true
|
skipTest[name] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
bt := make(map[string]TransactionTest)
|
bt := make(map[string]TransactionTest)
|
||||||
if err := readTestFile(file, &bt); err != nil {
|
if err := readJson(r, &bt); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ func RunTransactionTests(file string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// test the block
|
// test the block
|
||||||
if err := runTest(test); err != nil {
|
if err := runTransactionTest(test); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
glog.Infoln("Transaction test passed: ", name)
|
glog.Infoln("Transaction test passed: ", name)
|
||||||
@ -58,7 +59,35 @@ func RunTransactionTests(file string) error {
|
|||||||
return nil
|
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)
|
tx := new(types.Transaction)
|
||||||
err = rlp.DecodeBytes(mustConvertBytes(txTest.Rlp), tx)
|
err = rlp.DecodeBytes(mustConvertBytes(txTest.Rlp), tx)
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package tests
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@ -13,94 +14,53 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RunVmTest(p string) error {
|
func RunVmTestWithReader(r io.Reader) error {
|
||||||
skipTest := make(map[string]bool, len(vmSkipTests))
|
|
||||||
for _, name := range vmSkipTests {
|
|
||||||
skipTest[name] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := make(map[string]VmTest)
|
tests := make(map[string]VmTest)
|
||||||
err := readTestFile(p, &tests)
|
err := readJson(r, &tests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
for name, test := range tests {
|
||||||
if skipTest[name] {
|
if skipTest[name] {
|
||||||
glog.Infoln("Skipping VM test", name)
|
glog.Infoln("Skipping VM test", name)
|
||||||
return nil
|
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...
|
if err := runVmTest(test); err != nil {
|
||||||
env := make(map[string]string)
|
return fmt.Errorf("%s %s", name, err.Error())
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.Infoln("VM test passed: ", name)
|
glog.Infoln("VM test passed: ", name)
|
||||||
@ -109,6 +69,83 @@ func RunVmTest(p string) error {
|
|||||||
return nil
|
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) {
|
func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Logs, *big.Int, error) {
|
||||||
var (
|
var (
|
||||||
to = common.HexToAddress(exec["address"])
|
to = common.HexToAddress(exec["address"])
|
||||||
|
Loading…
Reference in New Issue
Block a user