diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/block_test_util.go | 80 | ||||
-rw-r--r-- | tests/init.go | 75 | ||||
-rw-r--r-- | tests/state_test_util.go | 166 | ||||
-rw-r--r-- | tests/transaction_test_util.go | 39 | ||||
-rw-r--r-- | tests/vm_test_util.go | 167 |
5 files changed, 345 insertions, 182 deletions
diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 21fd07db6..5222b214b 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -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... diff --git a/tests/init.go b/tests/init.go index 164924ab8..326387341 100644 --- a/tests/init.go +++ b/tests/init.go @@ -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,44 +68,44 @@ func readJSON(reader io.Reader, value interface{}) error { return nil } -// findLine returns the line number for the given offset into data. -func findLine(data []byte, offset int64) (line int) { - line = 1 - for i, r := range string(data) { - if int64(i) >= offset { - return - } - if r == '\n' { - line++ - } - } - return -} - -func readHttpFile(uri string, value interface{}) error { +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) + err = readJson(resp.Body, value) if err != nil { return err } return nil } -func readTestFile(fn string, value interface{}) error { +func readJsonFile(fn string, value interface{}) error { file, err := os.Open(fn) if err != nil { return err } defer file.Close() - err = readJSON(file, value) + 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 + for i, r := range string(data) { + if int64(i) >= offset { + return + } + if r == '\n' { + line++ + } + } + return +} diff --git a/tests/state_test_util.go b/tests/state_test_util.go index ad14168c7..ad3aeea6c 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -3,6 +3,7 @@ package tests import ( "bytes" "fmt" + "io" "math/big" "strconv" @@ -15,100 +16,133 @@ 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) + if err := runStateTest(test); err != nil { + return fmt.Errorf("%s: %s\n", name, err.Error()) } - var ( - ret []byte - // gas *big.Int - // err error - logs state.Logs - ) + glog.Infoln("State test passed: ", name) + //fmt.Println(string(statedb.Dump())) + } + return nil - 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) +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)) } + } - // check post state - for addr, account := range test.Post { - obj := statedb.GetStateObject(common.HexToAddress(addr)) - if obj == nil { - continue - } + // 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) + } - 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())) - } + var ( + ret []byte + // gas *big.Int + // err error + logs state.Logs + ) - 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()) - } + 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) + } - for addr, value := range account.Storage { - v := obj.GetState(common.HexToHash(addr)).Bytes() - vexp := common.FromHex(value) + // check post state + for addr, account := range test.Post { + obj := statedb.GetStateObject(common.HexToAddress(addr)) + if obj == nil { + continue + } - 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)) - } - } + 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())) } - 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()) + 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()) } - // check logs - if len(test.Logs) > 0 { - lerr := checkLogs(test.Logs, logs) - if lerr != nil { - return fmt.Errorf("'%s' ", name, lerr.Error()) + 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)) } } + } - glog.Infoln("State test passed: ", name) - //fmt.Println(string(statedb.Dump())) + 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 } diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index ef133a99d..af33f2c58 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + "io" "runtime" "github.com/ethereum/go-ethereum/common" @@ -31,14 +32,41 @@ type TransactionTest struct { Transaction TtTransaction } +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 := readJson(r, &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 RunTransactionTests(file string) error { - skipTest := make(map[string]bool, len(transSkipTests)) - for _, name := range transSkipTests { + 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 := readJsonFile(file, &bt); err != nil { return err } @@ -48,8 +76,9 @@ func RunTransactionTests(file string) error { glog.Infoln("Skipping transaction test", name) 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 +87,7 @@ func RunTransactionTests(file string) error { return nil } -func runTest(txTest TransactionTest) (err error) { +func runTransactionTest(txTest TransactionTest) (err error) { tx := new(types.Transaction) err = rlp.DecodeBytes(mustConvertBytes(txTest.Rlp), tx) diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 4145d1ebf..f7f1198ec 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -3,6 +3,7 @@ package tests import ( "bytes" "fmt" + "io" "math/big" "strconv" @@ -13,99 +14,135 @@ 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 := 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 := readTestFile(p, &tests) + 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)) - } + + if err := runVmTest(test); err != nil { + return fmt.Errorf("%s %s", name, err.Error()) } - // 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) + glog.Infoln("VM test passed: ", name) + //fmt.Println(string(statedb.Dump())) + } + 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)) } + } - var ( - ret []byte - gas *big.Int - err error - logs state.Logs - ) + // 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) + } - ret, logs, gas, err = RunVm(statedb, env, test.Exec) + var ( + ret []byte + gas *big.Int + err error + logs state.Logs + ) - // 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) - } + ret, logs, gas, err = RunVm(statedb, env, test.Exec) - // 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) - } + // 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 - } + // 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) + 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()) - } + 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 fmt.Errorf("'%s' ", name, lerr.Error()) - } + // check logs + if len(test.Logs) > 0 { + lerr := checkLogs(test.Logs, logs) + if lerr != nil { + return lerr } - - glog.Infoln("VM test passed: ", name) - //fmt.Println(string(statedb.Dump())) } + return nil } |