From 6415ed0730f1e752036e0c79f913e133c318c231 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Mon, 8 Jun 2015 16:03:21 -0400 Subject: [PATCH 01/24] Require a first argument of test type --- cmd/ethtest/main.go | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go index c2c94d6c4..c33db45d2 100644 --- a/cmd/ethtest/main.go +++ b/cmd/ethtest/main.go @@ -225,9 +225,29 @@ func main() { helper.Logger.SetLogLevel(5) vm.Debug = true - if len(os.Args) > 1 { - os.Exit(RunVmTest(strings.NewReader(os.Args[1]))) - } else { - os.Exit(RunVmTest(os.Stdin)) + if len(os.Args) < 2 { + glog.Exit("Must specify test type") } + + test := os.Args[1] + + var code int + switch test { + case "vm", "VMTests": + glog.Exit("VMTests not yet implemented") + case "state", "StateTest": + if len(os.Args) > 2 { + code = RunVmTest(strings.NewReader(os.Args[2])) + } else { + code = RunVmTest(os.Stdin) + } + case "tx", "TransactionTests": + glog.Exit("TransactionTests not yet implemented") + case "bc", "BlockChainTest": + glog.Exit("BlockChainTest not yet implemented") + default: + glog.Exit("Invalid test type specified") + } + + os.Exit(code) } From 7b9fbb088a74de746dc3f0aa76dbbc8985c2b12c Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 10 Jun 2015 11:55:36 -0400 Subject: [PATCH 02/24] Flatten vm directory --- tests/{vm/gh_test.go => vm.go} | 0 tests/vm/.ethtest | 0 tests/vm/nowarn.go | 3 - tests/vm_test.go | 387 +++++++++++++++++++++++++++++++++ 4 files changed, 387 insertions(+), 3 deletions(-) rename tests/{vm/gh_test.go => vm.go} (100%) delete mode 100644 tests/vm/.ethtest delete mode 100644 tests/vm/nowarn.go create mode 100644 tests/vm_test.go diff --git a/tests/vm/gh_test.go b/tests/vm.go similarity index 100% rename from tests/vm/gh_test.go rename to tests/vm.go diff --git a/tests/vm/.ethtest b/tests/vm/.ethtest deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/vm/nowarn.go b/tests/vm/nowarn.go deleted file mode 100644 index 2a45a6cc6..000000000 --- a/tests/vm/nowarn.go +++ /dev/null @@ -1,3 +0,0 @@ -// This silences the warning given by 'go install ./...'. - -package vm diff --git a/tests/vm_test.go b/tests/vm_test.go new file mode 100644 index 000000000..2f76084d0 --- /dev/null +++ b/tests/vm_test.go @@ -0,0 +1,387 @@ +package vm + +import ( + "bytes" + "math/big" + "os" + "path/filepath" + "strconv" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/tests/helper" +) + +type Account struct { + Balance string + Code string + Nonce string + Storage map[string]string +} + +type Log struct { + AddressF string `json:"address"` + DataF string `json:"data"` + TopicsF []string `json:"topics"` + BloomF string `json:"bloom"` +} + +func (self Log) Address() []byte { return common.Hex2Bytes(self.AddressF) } +func (self Log) Data() []byte { return common.Hex2Bytes(self.DataF) } +func (self Log) RlpData() interface{} { return nil } +func (self Log) Topics() [][]byte { + t := make([][]byte, len(self.TopicsF)) + for i, topic := range self.TopicsF { + t[i] = common.Hex2Bytes(topic) + } + return t +} + +func StateObjectFromAccount(db common.Database, addr string, account Account) *state.StateObject { + obj := state.NewStateObject(common.HexToAddress(addr), db) + obj.SetBalance(common.Big(account.Balance)) + + if common.IsHex(account.Code) { + account.Code = account.Code[2:] + } + obj.SetCode(common.Hex2Bytes(account.Code)) + obj.SetNonce(common.Big(account.Nonce).Uint64()) + + return obj +} + +type Env struct { + CurrentCoinbase string + CurrentDifficulty string + CurrentGasLimit string + CurrentNumber string + CurrentTimestamp interface{} + PreviousHash string +} + +type VmTest struct { + Callcreates interface{} + //Env map[string]string + Env Env + Exec map[string]string + Transaction map[string]string + Logs []Log + Gas string + Out string + Post map[string]Account + Pre map[string]Account + PostStateRoot string +} + +func RunVmTest(p string, t *testing.T) { + + tests := make(map[string]VmTest) + helper.CreateFileTests(t, p, &tests) + + for name, test := range tests { + /* + vm.Debug = true + glog.SetV(4) + glog.SetToStderr(true) + if name != "Call50000_sha256" { + continue + } + */ + 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.NewValue(helper.FromHex(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 + ) + + isVmTest := len(test.Exec) > 0 + if isVmTest { + ret, logs, gas, err = helper.RunVm(statedb, env, test.Exec) + } else { + ret, logs, gas, err = helper.RunState(statedb, env, test.Transaction) + } + + switch name { + // the memory required for these tests (4294967297 bytes) would take too much time. + // on 19 May 2015 decided to skip these tests their output. + case "mload32bitBound_return", "mload32bitBound_return2": + default: + rexp := helper.FromHex(test.Out) + if bytes.Compare(rexp, ret) != 0 { + t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) + } + } + + if isVmTest { + if len(test.Gas) == 0 && err == nil { + t.Errorf("%s's gas unspecified, indicating an error. VM returned (incorrectly) successfull", name) + } else { + gexp := common.Big(test.Gas) + if gexp.Cmp(gas) != 0 { + t.Errorf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas) + } + } + } + + for addr, account := range test.Post { + obj := statedb.GetStateObject(common.HexToAddress(addr)) + if obj == nil { + continue + } + + if len(test.Exec) == 0 { + if obj.Balance().Cmp(common.Big(account.Balance)) != 0 { + t.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() { + t.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 := helper.FromHex(value) + + if bytes.Compare(v, vexp) != 0 { + t.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 !isVmTest { + statedb.Sync() + //if !bytes.Equal(common.Hex2Bytes(test.PostStateRoot), statedb.Root()) { + if common.HexToHash(test.PostStateRoot) != statedb.Root() { + t.Errorf("%s's : Post state root error. Expected %s, got %x", name, test.PostStateRoot, statedb.Root()) + } + } + + if len(test.Logs) > 0 { + if len(test.Logs) != len(logs) { + t.Errorf("log length mismatch. Expected %d, got %d", len(test.Logs), len(logs)) + } else { + for i, log := range test.Logs { + if common.HexToAddress(log.AddressF) != logs[i].Address { + t.Errorf("'%s' log address expected %v got %x", name, log.AddressF, logs[i].Address) + } + + if !bytes.Equal(logs[i].Data, helper.FromHex(log.DataF)) { + t.Errorf("'%s' log data expected %v got %x", name, log.DataF, logs[i].Data) + } + + if len(log.TopicsF) != len(logs[i].Topics) { + t.Errorf("'%s' log topics length expected %d got %d", name, len(log.TopicsF), logs[i].Topics) + } else { + for j, topic := range log.TopicsF { + if common.HexToHash(topic) != logs[i].Topics[j] { + t.Errorf("'%s' log topic[%d] expected %v got %x", name, j, topic, logs[i].Topics[j]) + } + } + } + genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256) + + if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) { + t.Errorf("'%s' bloom mismatch", name) + } + } + } + } + //fmt.Println(string(statedb.Dump())) + } + logger.Flush() +} + +// I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail. +func TestVMArithmetic(t *testing.T) { + const fn = "../files/VMTests/vmArithmeticTest.json" + RunVmTest(fn, t) +} + +func TestBitwiseLogicOperation(t *testing.T) { + const fn = "../files/VMTests/vmBitwiseLogicOperationTest.json" + RunVmTest(fn, t) +} + +func TestBlockInfo(t *testing.T) { + const fn = "../files/VMTests/vmBlockInfoTest.json" + RunVmTest(fn, t) +} + +func TestEnvironmentalInfo(t *testing.T) { + const fn = "../files/VMTests/vmEnvironmentalInfoTest.json" + RunVmTest(fn, t) +} + +func TestFlowOperation(t *testing.T) { + const fn = "../files/VMTests/vmIOandFlowOperationsTest.json" + RunVmTest(fn, t) +} + +func TestLogTest(t *testing.T) { + const fn = "../files/VMTests/vmLogTest.json" + RunVmTest(fn, t) +} + +func TestPerformance(t *testing.T) { + const fn = "../files/VMTests/vmPerformanceTest.json" + RunVmTest(fn, t) +} + +func TestPushDupSwap(t *testing.T) { + const fn = "../files/VMTests/vmPushDupSwapTest.json" + RunVmTest(fn, t) +} + +func TestVMSha3(t *testing.T) { + const fn = "../files/VMTests/vmSha3Test.json" + RunVmTest(fn, t) +} + +func TestVm(t *testing.T) { + const fn = "../files/VMTests/vmtests.json" + RunVmTest(fn, t) +} + +func TestVmLog(t *testing.T) { + const fn = "../files/VMTests/vmLogTest.json" + RunVmTest(fn, t) +} + +func TestInputLimits(t *testing.T) { + const fn = "../files/VMTests/vmInputLimits.json" + RunVmTest(fn, t) +} + +func TestInputLimitsLight(t *testing.T) { + const fn = "../files/VMTests/vmInputLimitsLight.json" + RunVmTest(fn, t) +} + +func TestStateSystemOperations(t *testing.T) { + const fn = "../files/StateTests/stSystemOperationsTest.json" + RunVmTest(fn, t) +} + +func TestStateExample(t *testing.T) { + const fn = "../files/StateTests/stExample.json" + RunVmTest(fn, t) +} + +func TestStatePreCompiledContracts(t *testing.T) { + const fn = "../files/StateTests/stPreCompiledContracts.json" + RunVmTest(fn, t) +} + +func TestStateRecursiveCreate(t *testing.T) { + const fn = "../files/StateTests/stRecursiveCreate.json" + RunVmTest(fn, t) +} + +func TestStateSpecial(t *testing.T) { + const fn = "../files/StateTests/stSpecialTest.json" + RunVmTest(fn, t) +} + +func TestStateRefund(t *testing.T) { + const fn = "../files/StateTests/stRefundTest.json" + RunVmTest(fn, t) +} + +func TestStateBlockHash(t *testing.T) { + const fn = "../files/StateTests/stBlockHashTest.json" + RunVmTest(fn, t) +} + +func TestStateInitCode(t *testing.T) { + const fn = "../files/StateTests/stInitCodeTest.json" + RunVmTest(fn, t) +} + +func TestStateLog(t *testing.T) { + const fn = "../files/StateTests/stLogTests.json" + RunVmTest(fn, t) +} + +func TestStateTransaction(t *testing.T) { + const fn = "../files/StateTests/stTransactionTest.json" + RunVmTest(fn, t) +} + +func TestCallCreateCallCode(t *testing.T) { + const fn = "../files/StateTests/stCallCreateCallCodeTest.json" + RunVmTest(fn, t) +} + +func TestMemory(t *testing.T) { + const fn = "../files/StateTests/stMemoryTest.json" + RunVmTest(fn, t) +} + +func TestMemoryStress(t *testing.T) { + if os.Getenv("TEST_VM_COMPLEX") == "" { + t.Skip() + } + const fn = "../files/StateTests/stMemoryStressTest.json" + RunVmTest(fn, t) +} + +func TestQuadraticComplexity(t *testing.T) { + if os.Getenv("TEST_VM_COMPLEX") == "" { + t.Skip() + } + const fn = "../files/StateTests/stQuadraticComplexityTest.json" + RunVmTest(fn, t) +} + +func TestSolidity(t *testing.T) { + const fn = "../files/StateTests/stSolidityTest.json" + RunVmTest(fn, t) +} + +func TestWallet(t *testing.T) { + const fn = "../files/StateTests/stWalletTest.json" + RunVmTest(fn, t) +} + +func TestStateTestsRandom(t *testing.T) { + fns, _ := filepath.Glob("../files/StateTests/RandomTests/*") + for _, fn := range fns { + RunVmTest(fn, t) + } +} + +func TestVMRandom(t *testing.T) { + fns, _ := filepath.Glob("../files/VMTests/RandomTests/*") + for _, fn := range fns { + RunVmTest(fn, t) + } +} From a67a15528aa5da902a17d49f5dad19db3975032a Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 10 Jun 2015 12:04:56 -0400 Subject: [PATCH 03/24] Split tests from helper code --- tests/block_test.go | 69 ------- tests/block_test_util.go | 66 +++++++ tests/state_test.go | 96 ++++++++++ tests/vm_test.go | 311 +------------------------------ tests/{vm.go => vm_test_util.go} | 183 +----------------- 5 files changed, 170 insertions(+), 555 deletions(-) create mode 100644 tests/state_test.go rename tests/{vm.go => vm_test_util.go} (60%) diff --git a/tests/block_test.go b/tests/block_test.go index d5136efce..c017b746e 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -1,14 +1,7 @@ package tests import ( - "path/filepath" "testing" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/ethdb" ) // TODO: refactor test setup & execution to better align with vm and tx tests @@ -50,65 +43,3 @@ func TestBcTotalDifficulty(t *testing.T) { func TestBcWallet(t *testing.T) { runBlockTestsInFile("files/BlockTests/bcWalletTest.json", []string{}, t) } - -func runBlockTestsInFile(filepath string, snafus []string, t *testing.T) { - bt, err := LoadBlockTests(filepath) - if err != nil { - t.Fatal(err) - } - - notWorking := make(map[string]bool, 100) - for _, name := range snafus { - notWorking[name] = true - } - - for name, test := range bt { - if !notWorking[name] { - runBlockTest(name, test, t) - } - } -} - -func runBlockTest(name string, test *BlockTest, t *testing.T) { - cfg := testEthConfig() - ethereum, err := eth.New(cfg) - if err != nil { - t.Fatalf("%v", err) - } - - err = ethereum.Start() - if err != nil { - t.Fatalf("%v", err) - } - - // import the genesis block - ethereum.ResetWithGenesisBlock(test.Genesis) - - // import pre accounts - statedb, err := test.InsertPreState(ethereum) - if err != nil { - t.Fatalf("InsertPreState: %v", err) - } - - err = test.TryBlocksInsert(ethereum.ChainManager()) - if err != nil { - t.Fatal(err) - } - - if err = test.ValidatePostState(statedb); err != nil { - t.Fatal("post state validation failed: %v", err) - } - t.Log("Test passed: ", name) -} - -func testEthConfig() *eth.Config { - ks := crypto.NewKeyStorePassphrase(filepath.Join(common.DefaultDataDir(), "keystore")) - - return ð.Config{ - DataDir: common.DefaultDataDir(), - Verbosity: 5, - Etherbase: "primary", - AccountManager: accounts.NewManager(ks), - NewDB: func(path string) (common.Database, error) { return ethdb.NewMemDatabase() }, - } -} diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 200fcbd59..224c14283 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -7,17 +7,21 @@ import ( "fmt" "io/ioutil" "math/big" + "path/filepath" "runtime" "strconv" "strings" + "testing" "time" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rlp" ) @@ -83,6 +87,68 @@ type btTransaction struct { Value string } +func runBlockTestsInFile(filepath string, snafus []string, t *testing.T) { + bt, err := LoadBlockTests(filepath) + if err != nil { + t.Fatal(err) + } + + notWorking := make(map[string]bool, 100) + for _, name := range snafus { + notWorking[name] = true + } + + for name, test := range bt { + if !notWorking[name] { + runBlockTest(name, test, t) + } + } +} + +func runBlockTest(name string, test *BlockTest, t *testing.T) { + cfg := testEthConfig() + ethereum, err := eth.New(cfg) + if err != nil { + t.Fatalf("%v", err) + } + + err = ethereum.Start() + if err != nil { + t.Fatalf("%v", err) + } + + // import the genesis block + ethereum.ResetWithGenesisBlock(test.Genesis) + + // import pre accounts + statedb, err := test.InsertPreState(ethereum) + if err != nil { + t.Fatalf("InsertPreState: %v", err) + } + + err = test.TryBlocksInsert(ethereum.ChainManager()) + if err != nil { + t.Fatal(err) + } + + if err = test.ValidatePostState(statedb); err != nil { + t.Fatal("post state validation failed: %v", err) + } + t.Log("Test passed: ", name) +} + +func testEthConfig() *eth.Config { + ks := crypto.NewKeyStorePassphrase(filepath.Join(common.DefaultDataDir(), "keystore")) + + return ð.Config{ + DataDir: common.DefaultDataDir(), + Verbosity: 5, + Etherbase: "primary", + AccountManager: accounts.NewManager(ks), + NewDB: func(path string) (common.Database, error) { return ethdb.NewMemDatabase() }, + } +} + // LoadBlockTests loads a block test JSON file. func LoadBlockTests(file string) (map[string]*BlockTest, error) { bt := make(map[string]*btJSON) diff --git a/tests/state_test.go b/tests/state_test.go new file mode 100644 index 000000000..5e7be124b --- /dev/null +++ b/tests/state_test.go @@ -0,0 +1,96 @@ +package tests + +import "testing" + +func TestStateSystemOperations(t *testing.T) { + const fn = "../files/StateTests/stSystemOperationsTest.json" + RunVmTest(fn, t) +} + +func TestStateExample(t *testing.T) { + const fn = "../files/StateTests/stExample.json" + RunVmTest(fn, t) +} + +func TestStatePreCompiledContracts(t *testing.T) { + const fn = "../files/StateTests/stPreCompiledContracts.json" + RunVmTest(fn, t) +} + +func TestStateRecursiveCreate(t *testing.T) { + const fn = "../files/StateTests/stRecursiveCreate.json" + RunVmTest(fn, t) +} + +func TestStateSpecial(t *testing.T) { + const fn = "../files/StateTests/stSpecialTest.json" + RunVmTest(fn, t) +} + +func TestStateRefund(t *testing.T) { + const fn = "../files/StateTests/stRefundTest.json" + RunVmTest(fn, t) +} + +func TestStateBlockHash(t *testing.T) { + const fn = "../files/StateTests/stBlockHashTest.json" + RunVmTest(fn, t) +} + +func TestStateInitCode(t *testing.T) { + const fn = "../files/StateTests/stInitCodeTest.json" + RunVmTest(fn, t) +} + +func TestStateLog(t *testing.T) { + const fn = "../files/StateTests/stLogTests.json" + RunVmTest(fn, t) +} + +func TestStateTransaction(t *testing.T) { + const fn = "../files/StateTests/stTransactionTest.json" + RunVmTest(fn, t) +} + +func TestCallCreateCallCode(t *testing.T) { + const fn = "../files/StateTests/stCallCreateCallCodeTest.json" + RunVmTest(fn, t) +} + +func TestMemory(t *testing.T) { + const fn = "../files/StateTests/stMemoryTest.json" + RunVmTest(fn, t) +} + +func TestMemoryStress(t *testing.T) { + if os.Getenv("TEST_VM_COMPLEX") == "" { + t.Skip() + } + const fn = "../files/StateTests/stMemoryStressTest.json" + RunVmTest(fn, t) +} + +func TestQuadraticComplexity(t *testing.T) { + if os.Getenv("TEST_VM_COMPLEX") == "" { + t.Skip() + } + const fn = "../files/StateTests/stQuadraticComplexityTest.json" + RunVmTest(fn, t) +} + +func TestSolidity(t *testing.T) { + const fn = "../files/StateTests/stSolidityTest.json" + RunVmTest(fn, t) +} + +func TestWallet(t *testing.T) { + const fn = "../files/StateTests/stWalletTest.json" + RunVmTest(fn, t) +} + +func TestStateTestsRandom(t *testing.T) { + fns, _ := filepath.Glob("../files/StateTests/RandomTests/*") + for _, fn := range fns { + RunVmTest(fn, t) + } +} diff --git a/tests/vm_test.go b/tests/vm_test.go index 2f76084d0..b42f83df8 100644 --- a/tests/vm_test.go +++ b/tests/vm_test.go @@ -1,225 +1,9 @@ -package vm +package tests import ( - "bytes" - "math/big" - "os" - "path/filepath" - "strconv" "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/logger" - "github.com/ethereum/go-ethereum/tests/helper" ) -type Account struct { - Balance string - Code string - Nonce string - Storage map[string]string -} - -type Log struct { - AddressF string `json:"address"` - DataF string `json:"data"` - TopicsF []string `json:"topics"` - BloomF string `json:"bloom"` -} - -func (self Log) Address() []byte { return common.Hex2Bytes(self.AddressF) } -func (self Log) Data() []byte { return common.Hex2Bytes(self.DataF) } -func (self Log) RlpData() interface{} { return nil } -func (self Log) Topics() [][]byte { - t := make([][]byte, len(self.TopicsF)) - for i, topic := range self.TopicsF { - t[i] = common.Hex2Bytes(topic) - } - return t -} - -func StateObjectFromAccount(db common.Database, addr string, account Account) *state.StateObject { - obj := state.NewStateObject(common.HexToAddress(addr), db) - obj.SetBalance(common.Big(account.Balance)) - - if common.IsHex(account.Code) { - account.Code = account.Code[2:] - } - obj.SetCode(common.Hex2Bytes(account.Code)) - obj.SetNonce(common.Big(account.Nonce).Uint64()) - - return obj -} - -type Env struct { - CurrentCoinbase string - CurrentDifficulty string - CurrentGasLimit string - CurrentNumber string - CurrentTimestamp interface{} - PreviousHash string -} - -type VmTest struct { - Callcreates interface{} - //Env map[string]string - Env Env - Exec map[string]string - Transaction map[string]string - Logs []Log - Gas string - Out string - Post map[string]Account - Pre map[string]Account - PostStateRoot string -} - -func RunVmTest(p string, t *testing.T) { - - tests := make(map[string]VmTest) - helper.CreateFileTests(t, p, &tests) - - for name, test := range tests { - /* - vm.Debug = true - glog.SetV(4) - glog.SetToStderr(true) - if name != "Call50000_sha256" { - continue - } - */ - 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.NewValue(helper.FromHex(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 - ) - - isVmTest := len(test.Exec) > 0 - if isVmTest { - ret, logs, gas, err = helper.RunVm(statedb, env, test.Exec) - } else { - ret, logs, gas, err = helper.RunState(statedb, env, test.Transaction) - } - - switch name { - // the memory required for these tests (4294967297 bytes) would take too much time. - // on 19 May 2015 decided to skip these tests their output. - case "mload32bitBound_return", "mload32bitBound_return2": - default: - rexp := helper.FromHex(test.Out) - if bytes.Compare(rexp, ret) != 0 { - t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) - } - } - - if isVmTest { - if len(test.Gas) == 0 && err == nil { - t.Errorf("%s's gas unspecified, indicating an error. VM returned (incorrectly) successfull", name) - } else { - gexp := common.Big(test.Gas) - if gexp.Cmp(gas) != 0 { - t.Errorf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas) - } - } - } - - for addr, account := range test.Post { - obj := statedb.GetStateObject(common.HexToAddress(addr)) - if obj == nil { - continue - } - - if len(test.Exec) == 0 { - if obj.Balance().Cmp(common.Big(account.Balance)) != 0 { - t.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() { - t.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 := helper.FromHex(value) - - if bytes.Compare(v, vexp) != 0 { - t.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 !isVmTest { - statedb.Sync() - //if !bytes.Equal(common.Hex2Bytes(test.PostStateRoot), statedb.Root()) { - if common.HexToHash(test.PostStateRoot) != statedb.Root() { - t.Errorf("%s's : Post state root error. Expected %s, got %x", name, test.PostStateRoot, statedb.Root()) - } - } - - if len(test.Logs) > 0 { - if len(test.Logs) != len(logs) { - t.Errorf("log length mismatch. Expected %d, got %d", len(test.Logs), len(logs)) - } else { - for i, log := range test.Logs { - if common.HexToAddress(log.AddressF) != logs[i].Address { - t.Errorf("'%s' log address expected %v got %x", name, log.AddressF, logs[i].Address) - } - - if !bytes.Equal(logs[i].Data, helper.FromHex(log.DataF)) { - t.Errorf("'%s' log data expected %v got %x", name, log.DataF, logs[i].Data) - } - - if len(log.TopicsF) != len(logs[i].Topics) { - t.Errorf("'%s' log topics length expected %d got %d", name, len(log.TopicsF), logs[i].Topics) - } else { - for j, topic := range log.TopicsF { - if common.HexToHash(topic) != logs[i].Topics[j] { - t.Errorf("'%s' log topic[%d] expected %v got %x", name, j, topic, logs[i].Topics[j]) - } - } - } - genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256) - - if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) { - t.Errorf("'%s' bloom mismatch", name) - } - } - } - } - //fmt.Println(string(statedb.Dump())) - } - logger.Flush() -} - // I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail. func TestVMArithmetic(t *testing.T) { const fn = "../files/VMTests/vmArithmeticTest.json" @@ -286,99 +70,6 @@ func TestInputLimitsLight(t *testing.T) { RunVmTest(fn, t) } -func TestStateSystemOperations(t *testing.T) { - const fn = "../files/StateTests/stSystemOperationsTest.json" - RunVmTest(fn, t) -} - -func TestStateExample(t *testing.T) { - const fn = "../files/StateTests/stExample.json" - RunVmTest(fn, t) -} - -func TestStatePreCompiledContracts(t *testing.T) { - const fn = "../files/StateTests/stPreCompiledContracts.json" - RunVmTest(fn, t) -} - -func TestStateRecursiveCreate(t *testing.T) { - const fn = "../files/StateTests/stRecursiveCreate.json" - RunVmTest(fn, t) -} - -func TestStateSpecial(t *testing.T) { - const fn = "../files/StateTests/stSpecialTest.json" - RunVmTest(fn, t) -} - -func TestStateRefund(t *testing.T) { - const fn = "../files/StateTests/stRefundTest.json" - RunVmTest(fn, t) -} - -func TestStateBlockHash(t *testing.T) { - const fn = "../files/StateTests/stBlockHashTest.json" - RunVmTest(fn, t) -} - -func TestStateInitCode(t *testing.T) { - const fn = "../files/StateTests/stInitCodeTest.json" - RunVmTest(fn, t) -} - -func TestStateLog(t *testing.T) { - const fn = "../files/StateTests/stLogTests.json" - RunVmTest(fn, t) -} - -func TestStateTransaction(t *testing.T) { - const fn = "../files/StateTests/stTransactionTest.json" - RunVmTest(fn, t) -} - -func TestCallCreateCallCode(t *testing.T) { - const fn = "../files/StateTests/stCallCreateCallCodeTest.json" - RunVmTest(fn, t) -} - -func TestMemory(t *testing.T) { - const fn = "../files/StateTests/stMemoryTest.json" - RunVmTest(fn, t) -} - -func TestMemoryStress(t *testing.T) { - if os.Getenv("TEST_VM_COMPLEX") == "" { - t.Skip() - } - const fn = "../files/StateTests/stMemoryStressTest.json" - RunVmTest(fn, t) -} - -func TestQuadraticComplexity(t *testing.T) { - if os.Getenv("TEST_VM_COMPLEX") == "" { - t.Skip() - } - const fn = "../files/StateTests/stQuadraticComplexityTest.json" - RunVmTest(fn, t) -} - -func TestSolidity(t *testing.T) { - const fn = "../files/StateTests/stSolidityTest.json" - RunVmTest(fn, t) -} - -func TestWallet(t *testing.T) { - const fn = "../files/StateTests/stWalletTest.json" - RunVmTest(fn, t) -} - -func TestStateTestsRandom(t *testing.T) { - fns, _ := filepath.Glob("../files/StateTests/RandomTests/*") - for _, fn := range fns { - RunVmTest(fn, t) - } -} - func TestVMRandom(t *testing.T) { fns, _ := filepath.Glob("../files/VMTests/RandomTests/*") for _, fn := range fns { diff --git a/tests/vm.go b/tests/vm_test_util.go similarity index 60% rename from tests/vm.go rename to tests/vm_test_util.go index be9e89d9c..f91070736 100644 --- a/tests/vm.go +++ b/tests/vm_test_util.go @@ -1,10 +1,8 @@ -package vm +package tests import ( "bytes" "math/big" - "os" - "path/filepath" "strconv" "testing" @@ -84,12 +82,12 @@ func RunVmTest(p string, t *testing.T) { for name, test := range tests { /* - vm.Debug = true - glog.SetV(4) - glog.SetToStderr(true) - if name != "Call50000_sha256" { - continue - } + vm.Debug = true + glog.SetV(4) + glog.SetToStderr(true) + if name != "Call50000_sha256" { + continue + } */ db, _ := ethdb.NewMemDatabase() statedb := state.New(common.Hash{}, db) @@ -219,170 +217,3 @@ func RunVmTest(p string, t *testing.T) { } logger.Flush() } - -// I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail. -func TestVMArithmetic(t *testing.T) { - const fn = "../files/VMTests/vmArithmeticTest.json" - RunVmTest(fn, t) -} - -func TestBitwiseLogicOperation(t *testing.T) { - const fn = "../files/VMTests/vmBitwiseLogicOperationTest.json" - RunVmTest(fn, t) -} - -func TestBlockInfo(t *testing.T) { - const fn = "../files/VMTests/vmBlockInfoTest.json" - RunVmTest(fn, t) -} - -func TestEnvironmentalInfo(t *testing.T) { - const fn = "../files/VMTests/vmEnvironmentalInfoTest.json" - RunVmTest(fn, t) -} - -func TestFlowOperation(t *testing.T) { - const fn = "../files/VMTests/vmIOandFlowOperationsTest.json" - RunVmTest(fn, t) -} - -func TestLogTest(t *testing.T) { - const fn = "../files/VMTests/vmLogTest.json" - RunVmTest(fn, t) -} - -func TestPerformance(t *testing.T) { - const fn = "../files/VMTests/vmPerformanceTest.json" - RunVmTest(fn, t) -} - -func TestPushDupSwap(t *testing.T) { - const fn = "../files/VMTests/vmPushDupSwapTest.json" - RunVmTest(fn, t) -} - -func TestVMSha3(t *testing.T) { - const fn = "../files/VMTests/vmSha3Test.json" - RunVmTest(fn, t) -} - -func TestVm(t *testing.T) { - const fn = "../files/VMTests/vmtests.json" - RunVmTest(fn, t) -} - -func TestVmLog(t *testing.T) { - const fn = "../files/VMTests/vmLogTest.json" - RunVmTest(fn, t) -} - -func TestInputLimits(t *testing.T) { - const fn = "../files/VMTests/vmInputLimits.json" - RunVmTest(fn, t) -} - -func TestInputLimitsLight(t *testing.T) { - const fn = "../files/VMTests/vmInputLimitsLight.json" - RunVmTest(fn, t) -} - -func TestStateSystemOperations(t *testing.T) { - const fn = "../files/StateTests/stSystemOperationsTest.json" - RunVmTest(fn, t) -} - -func TestStateExample(t *testing.T) { - const fn = "../files/StateTests/stExample.json" - RunVmTest(fn, t) -} - -func TestStatePreCompiledContracts(t *testing.T) { - const fn = "../files/StateTests/stPreCompiledContracts.json" - RunVmTest(fn, t) -} - -func TestStateRecursiveCreate(t *testing.T) { - const fn = "../files/StateTests/stRecursiveCreate.json" - RunVmTest(fn, t) -} - -func TestStateSpecial(t *testing.T) { - const fn = "../files/StateTests/stSpecialTest.json" - RunVmTest(fn, t) -} - -func TestStateRefund(t *testing.T) { - const fn = "../files/StateTests/stRefundTest.json" - RunVmTest(fn, t) -} - -func TestStateBlockHash(t *testing.T) { - const fn = "../files/StateTests/stBlockHashTest.json" - RunVmTest(fn, t) -} - -func TestStateInitCode(t *testing.T) { - const fn = "../files/StateTests/stInitCodeTest.json" - RunVmTest(fn, t) -} - -func TestStateLog(t *testing.T) { - const fn = "../files/StateTests/stLogTests.json" - RunVmTest(fn, t) -} - -func TestStateTransaction(t *testing.T) { - const fn = "../files/StateTests/stTransactionTest.json" - RunVmTest(fn, t) -} - -func TestCallCreateCallCode(t *testing.T) { - const fn = "../files/StateTests/stCallCreateCallCodeTest.json" - RunVmTest(fn, t) -} - -func TestMemory(t *testing.T) { - const fn = "../files/StateTests/stMemoryTest.json" - RunVmTest(fn, t) -} - -func TestMemoryStress(t *testing.T) { - if os.Getenv("TEST_VM_COMPLEX") == "" { - t.Skip() - } - const fn = "../files/StateTests/stMemoryStressTest.json" - RunVmTest(fn, t) -} - -func TestQuadraticComplexity(t *testing.T) { - if os.Getenv("TEST_VM_COMPLEX") == "" { - t.Skip() - } - const fn = "../files/StateTests/stQuadraticComplexityTest.json" - RunVmTest(fn, t) -} - -func TestSolidity(t *testing.T) { - const fn = "../files/StateTests/stSolidityTest.json" - RunVmTest(fn, t) -} - -func TestWallet(t *testing.T) { - const fn = "../files/StateTests/stWalletTest.json" - RunVmTest(fn, t) -} - -func TestStateTestsRandom(t *testing.T) { - fns, _ := filepath.Glob("../files/StateTests/RandomTests/*") - for _, fn := range fns { - RunVmTest(fn, t) - } -} - -func TestVMRandom(t *testing.T) { - t.Skip() // fucked as of 2015-06-09. unskip once unfucked /Gustav - fns, _ := filepath.Glob("../files/VMTests/RandomTests/*") - for _, fn := range fns { - RunVmTest(fn, t) - } -} From e82100367f794856a8807b5fcfe9f0043902a294 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 10 Jun 2015 12:34:38 -0400 Subject: [PATCH 04/24] Fix paths --- tests/block_test.go | 24 ++++++++++++---------- tests/state_test.go | 42 ++++++++++++++++++++++----------------- tests/transaction_test.go | 9 ++++++--- tests/vm_test.go | 31 ++++++++++++++++------------- 4 files changed, 61 insertions(+), 45 deletions(-) diff --git a/tests/block_test.go b/tests/block_test.go index c017b746e..1f2e5a15b 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -1,45 +1,49 @@ package tests import ( + "path/filepath" "testing" ) +var baseDir = filepath.Join(".", "files") +var blockTestDir = filepath.Join(baseDir, "BlockTests") + // TODO: refactor test setup & execution to better align with vm and tx tests func TestBcValidBlockTests(t *testing.T) { // SimpleTx3 genesis block does not validate against calculated state root // as of 2015-06-09. unskip once working /Gustav - runBlockTestsInFile("files/BlockTests/bcValidBlockTest.json", []string{"SimpleTx3"}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcValidBlockTest.json"), []string{"SimpleTx3"}, t) } func TestBcUncleTests(t *testing.T) { - runBlockTestsInFile("files/BlockTests/bcUncleTest.json", []string{}, t) - runBlockTestsInFile("files/BlockTests/bcBruncleTest.json", []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcUncleTest.json"), []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcBruncleTest.json"), []string{}, t) } func TestBcUncleHeaderValidityTests(t *testing.T) { - runBlockTestsInFile("files/BlockTests/bcUncleHeaderValiditiy.json", []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), []string{}, t) } func TestBcInvalidHeaderTests(t *testing.T) { - runBlockTestsInFile("files/BlockTests/bcInvalidHeaderTest.json", []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), []string{}, t) } func TestBcInvalidRLPTests(t *testing.T) { - runBlockTestsInFile("files/BlockTests/bcInvalidRLPTest.json", []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), []string{}, t) } func TestBcRPCAPITests(t *testing.T) { - runBlockTestsInFile("files/BlockTests/bcRPC_API_Test.json", []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcRPC_API_Test.json"), []string{}, t) } func TestBcForkBlockTests(t *testing.T) { - runBlockTestsInFile("files/BlockTests/bcForkBlockTest.json", []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcForkBlockTest.json"), []string{}, t) } func TestBcTotalDifficulty(t *testing.T) { - runBlockTestsInFile("files/BlockTests/bcTotalDifficultyTest.json", []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), []string{}, t) } func TestBcWallet(t *testing.T) { - runBlockTestsInFile("files/BlockTests/bcWalletTest.json", []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcWalletTest.json"), []string{}, t) } diff --git a/tests/state_test.go b/tests/state_test.go index 5e7be124b..fa000ec53 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -1,64 +1,70 @@ package tests -import "testing" +import ( + "os" + "path/filepath" + "testing" +) + +var stateTestDir = filepath.Join(baseDir, "StateTests") func TestStateSystemOperations(t *testing.T) { - const fn = "../files/StateTests/stSystemOperationsTest.json" + fn := filepath.Join(stateTestDir, "stSystemOperationsTest.json") RunVmTest(fn, t) } func TestStateExample(t *testing.T) { - const fn = "../files/StateTests/stExample.json" + fn := filepath.Join(stateTestDir, "stExample.json") RunVmTest(fn, t) } func TestStatePreCompiledContracts(t *testing.T) { - const fn = "../files/StateTests/stPreCompiledContracts.json" + fn := filepath.Join(stateTestDir, "stPreCompiledContracts.json") RunVmTest(fn, t) } func TestStateRecursiveCreate(t *testing.T) { - const fn = "../files/StateTests/stRecursiveCreate.json" + fn := filepath.Join(stateTestDir, "stRecursiveCreate.json") RunVmTest(fn, t) } func TestStateSpecial(t *testing.T) { - const fn = "../files/StateTests/stSpecialTest.json" + fn := filepath.Join(stateTestDir, "stSpecialTest.json") RunVmTest(fn, t) } func TestStateRefund(t *testing.T) { - const fn = "../files/StateTests/stRefundTest.json" + fn := filepath.Join(stateTestDir, "stRefundTest.json") RunVmTest(fn, t) } func TestStateBlockHash(t *testing.T) { - const fn = "../files/StateTests/stBlockHashTest.json" + fn := filepath.Join(stateTestDir, "stBlockHashTest.json") RunVmTest(fn, t) } func TestStateInitCode(t *testing.T) { - const fn = "../files/StateTests/stInitCodeTest.json" + fn := filepath.Join(stateTestDir, "stInitCodeTest.json") RunVmTest(fn, t) } func TestStateLog(t *testing.T) { - const fn = "../files/StateTests/stLogTests.json" + fn := filepath.Join(stateTestDir, "stLogTests.json") RunVmTest(fn, t) } func TestStateTransaction(t *testing.T) { - const fn = "../files/StateTests/stTransactionTest.json" + fn := filepath.Join(stateTestDir, "stTransactionTest.json") RunVmTest(fn, t) } func TestCallCreateCallCode(t *testing.T) { - const fn = "../files/StateTests/stCallCreateCallCodeTest.json" + fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json") RunVmTest(fn, t) } func TestMemory(t *testing.T) { - const fn = "../files/StateTests/stMemoryTest.json" + fn := filepath.Join(stateTestDir, "stMemoryTest.json") RunVmTest(fn, t) } @@ -66,7 +72,7 @@ func TestMemoryStress(t *testing.T) { if os.Getenv("TEST_VM_COMPLEX") == "" { t.Skip() } - const fn = "../files/StateTests/stMemoryStressTest.json" + fn := filepath.Join(stateTestDir, "stMemoryStressTest.json") RunVmTest(fn, t) } @@ -74,22 +80,22 @@ func TestQuadraticComplexity(t *testing.T) { if os.Getenv("TEST_VM_COMPLEX") == "" { t.Skip() } - const fn = "../files/StateTests/stQuadraticComplexityTest.json" + fn := filepath.Join(stateTestDir, "stQuadraticComplexityTest.json") RunVmTest(fn, t) } func TestSolidity(t *testing.T) { - const fn = "../files/StateTests/stSolidityTest.json" + fn := filepath.Join(stateTestDir, "stSolidityTest.json") RunVmTest(fn, t) } func TestWallet(t *testing.T) { - const fn = "../files/StateTests/stWalletTest.json" + fn := filepath.Join(stateTestDir, "stWalletTest.json") RunVmTest(fn, t) } func TestStateTestsRandom(t *testing.T) { - fns, _ := filepath.Glob("../files/StateTests/RandomTests/*") + fns, _ := filepath.Glob("./files/StateTests/RandomTests/*") for _, fn := range fns { RunVmTest(fn, t) } diff --git a/tests/transaction_test.go b/tests/transaction_test.go index 7ae1c8788..05942d3bf 100644 --- a/tests/transaction_test.go +++ b/tests/transaction_test.go @@ -1,9 +1,12 @@ package tests import ( + "path/filepath" "testing" ) +var transactionTestDir = filepath.Join(baseDir, "TransactionTests") + func TestTransactions(t *testing.T) { notWorking := make(map[string]bool, 100) @@ -17,7 +20,7 @@ func TestTransactions(t *testing.T) { } var err error - err = RunTransactionTests("./files/TransactionTests/ttTransactionTest.json", + err = RunTransactionTests(filepath.Join(transactionTestDir, "ttTransactionTest.json"), notWorking) if err != nil { t.Fatal(err) @@ -27,7 +30,7 @@ func TestTransactions(t *testing.T) { func TestWrongRLPTransactions(t *testing.T) { notWorking := make(map[string]bool, 100) var err error - err = RunTransactionTests("./files/TransactionTests/ttWrongRLPTransaction.json", + err = RunTransactionTests(filepath.Join(transactionTestDir, "ttWrongRLPTransaction.json"), notWorking) if err != nil { t.Fatal(err) @@ -37,7 +40,7 @@ func TestWrongRLPTransactions(t *testing.T) { func Test10MBtx(t *testing.T) { notWorking := make(map[string]bool, 100) var err error - err = RunTransactionTests("./files/TransactionTests/tt10mbDataField.json", + err = RunTransactionTests(filepath.Join(transactionTestDir, "tt10mbDataField.json"), notWorking) if err != nil { t.Fatal(err) diff --git a/tests/vm_test.go b/tests/vm_test.go index b42f83df8..faa3205bc 100644 --- a/tests/vm_test.go +++ b/tests/vm_test.go @@ -1,77 +1,80 @@ package tests import ( + "path/filepath" "testing" ) +var vmTestDir = filepath.Join(baseDir, "VMTests") + // I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail. func TestVMArithmetic(t *testing.T) { - const fn = "../files/VMTests/vmArithmeticTest.json" + fn := filepath.Join(vmTestDir, "vmArithmeticTest.json") RunVmTest(fn, t) } func TestBitwiseLogicOperation(t *testing.T) { - const fn = "../files/VMTests/vmBitwiseLogicOperationTest.json" + fn := filepath.Join(vmTestDir, "vmBitwiseLogicOperationTest.json") RunVmTest(fn, t) } func TestBlockInfo(t *testing.T) { - const fn = "../files/VMTests/vmBlockInfoTest.json" + fn := filepath.Join(vmTestDir, "vmBlockInfoTest.json") RunVmTest(fn, t) } func TestEnvironmentalInfo(t *testing.T) { - const fn = "../files/VMTests/vmEnvironmentalInfoTest.json" + fn := filepath.Join(vmTestDir, "vmEnvironmentalInfoTest.json") RunVmTest(fn, t) } func TestFlowOperation(t *testing.T) { - const fn = "../files/VMTests/vmIOandFlowOperationsTest.json" + fn := filepath.Join(vmTestDir, "vmIOandFlowOperationsTest.json") RunVmTest(fn, t) } func TestLogTest(t *testing.T) { - const fn = "../files/VMTests/vmLogTest.json" + fn := filepath.Join(vmTestDir, "vmLogTest.json") RunVmTest(fn, t) } func TestPerformance(t *testing.T) { - const fn = "../files/VMTests/vmPerformanceTest.json" + fn := filepath.Join(vmTestDir, "vmPerformanceTest.json") RunVmTest(fn, t) } func TestPushDupSwap(t *testing.T) { - const fn = "../files/VMTests/vmPushDupSwapTest.json" + fn := filepath.Join(vmTestDir, "vmPushDupSwapTest.json") RunVmTest(fn, t) } func TestVMSha3(t *testing.T) { - const fn = "../files/VMTests/vmSha3Test.json" + fn := filepath.Join(vmTestDir, "vmSha3Test.json") RunVmTest(fn, t) } func TestVm(t *testing.T) { - const fn = "../files/VMTests/vmtests.json" + fn := filepath.Join(vmTestDir, "vmtests.json") RunVmTest(fn, t) } func TestVmLog(t *testing.T) { - const fn = "../files/VMTests/vmLogTest.json" + fn := filepath.Join(vmTestDir, "vmLogTest.json") RunVmTest(fn, t) } func TestInputLimits(t *testing.T) { - const fn = "../files/VMTests/vmInputLimits.json" + fn := filepath.Join(vmTestDir, "vmInputLimits.json") RunVmTest(fn, t) } func TestInputLimitsLight(t *testing.T) { - const fn = "../files/VMTests/vmInputLimitsLight.json" + fn := filepath.Join(vmTestDir, "vmInputLimitsLight.json") RunVmTest(fn, t) } func TestVMRandom(t *testing.T) { - fns, _ := filepath.Glob("../files/VMTests/RandomTests/*") + fns, _ := filepath.Glob(filepath.Join(baseDir, "RandomTests", "*")) for _, fn := range fns { RunVmTest(fn, t) } From 1b26d4f220689dac18d560a4c1ecb3b29d99deb0 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 10 Jun 2015 13:00:54 -0400 Subject: [PATCH 05/24] Flatten helper directory --- tests/helper/common.go | 11 ---------- tests/helper/init.go | 16 -------------- tests/helper/trie.go | 31 ---------------------------- tests/{helper/readers.go => init.go} | 13 +++++++++++- tests/{helper => }/vm.go | 6 +++--- tests/vm_test_util.go | 15 +++++++------- 6 files changed, 22 insertions(+), 70 deletions(-) delete mode 100644 tests/helper/common.go delete mode 100644 tests/helper/init.go delete mode 100644 tests/helper/trie.go rename tests/{helper/readers.go => init.go} (69%) rename tests/{helper => }/vm.go (98%) diff --git a/tests/helper/common.go b/tests/helper/common.go deleted file mode 100644 index 21ea2261f..000000000 --- a/tests/helper/common.go +++ /dev/null @@ -1,11 +0,0 @@ -package helper - -import "github.com/ethereum/go-ethereum/common" - -func FromHex(h string) []byte { - if common.IsHex(h) { - h = h[2:] - } - - return common.Hex2Bytes(h) -} diff --git a/tests/helper/init.go b/tests/helper/init.go deleted file mode 100644 index 73d563e02..000000000 --- a/tests/helper/init.go +++ /dev/null @@ -1,16 +0,0 @@ -package helper - -import ( - "log" - "os" - - logpkg "github.com/ethereum/go-ethereum/logger" -) - -var Logger *logpkg.StdLogSystem -var Log = logpkg.NewLogger("TEST") - -func init() { - Logger = logpkg.NewStdLogSystem(os.Stdout, log.LstdFlags, logpkg.InfoLevel) - logpkg.AddLogSystem(Logger) -} diff --git a/tests/helper/trie.go b/tests/helper/trie.go deleted file mode 100644 index 9e666d333..000000000 --- a/tests/helper/trie.go +++ /dev/null @@ -1,31 +0,0 @@ -package helper - -import "github.com/ethereum/go-ethereum/trie" - -type MemDatabase struct { - db map[string][]byte -} - -func NewMemDatabase() (*MemDatabase, error) { - db := &MemDatabase{db: make(map[string][]byte)} - return db, nil -} -func (db *MemDatabase) Put(key []byte, value []byte) { - db.db[string(key)] = value -} -func (db *MemDatabase) Get(key []byte) ([]byte, error) { - return db.db[string(key)], nil -} -func (db *MemDatabase) Delete(key []byte) error { - delete(db.db, string(key)) - return nil -} -func (db *MemDatabase) Print() {} -func (db *MemDatabase) Close() {} -func (db *MemDatabase) LastKnownTD() []byte { return nil } - -func NewTrie() *trie.Trie { - db, _ := NewMemDatabase() - - return trie.New(nil, db) -} diff --git a/tests/helper/readers.go b/tests/init.go similarity index 69% rename from tests/helper/readers.go rename to tests/init.go index 03313aeda..b487f81c3 100644 --- a/tests/helper/readers.go +++ b/tests/init.go @@ -1,14 +1,25 @@ -package helper +package tests import ( "encoding/json" "io" "io/ioutil" + // "log" "net/http" "os" "testing" + + // logpkg "github.com/ethereum/go-ethereum/logger" ) +// var Logger *logpkg.StdLogSystem +// var Log = logpkg.NewLogger("TEST") + +// func init() { +// Logger = logpkg.NewStdLogSystem(os.Stdout, log.LstdFlags, logpkg.InfoLevel) +// logpkg.AddLogSystem(Logger) +// } + func readJSON(t *testing.T, reader io.Reader, value interface{}) { data, err := ioutil.ReadAll(reader) err = json.Unmarshal(data, &value) diff --git a/tests/helper/vm.go b/tests/vm.go similarity index 98% rename from tests/helper/vm.go rename to tests/vm.go index e29a2d8ee..52e498ccc 100644 --- a/tests/helper/vm.go +++ b/tests/vm.go @@ -1,4 +1,4 @@ -package helper +package tests import ( "errors" @@ -144,7 +144,7 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Log var ( to = common.HexToAddress(exec["address"]) from = common.HexToAddress(exec["caller"]) - data = FromHex(exec["data"]) + data = common.FromHex(exec["data"]) gas = common.Big(exec["gas"]) price = common.Big(exec["gasPrice"]) value = common.Big(exec["value"]) @@ -166,7 +166,7 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Log func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) { var ( keyPair, _ = crypto.NewKeyPairFromSec([]byte(common.Hex2Bytes(tx["secretKey"]))) - data = FromHex(tx["data"]) + data = common.FromHex(tx["data"]) gas = common.Big(tx["gasLimit"]) price = common.Big(tx["gasPrice"]) value = common.Big(tx["value"]) diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index f91070736..cf95db80f 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger" - "github.com/ethereum/go-ethereum/tests/helper" ) type Account struct { @@ -52,7 +51,7 @@ func StateObjectFromAccount(db common.Database, addr string, account Account) *s return obj } -type Env struct { +type VmEnv struct { CurrentCoinbase string CurrentDifficulty string CurrentGasLimit string @@ -64,7 +63,7 @@ type Env struct { type VmTest struct { Callcreates interface{} //Env map[string]string - Env Env + Env VmEnv Exec map[string]string Transaction map[string]string Logs []Log @@ -78,7 +77,7 @@ type VmTest struct { func RunVmTest(p string, t *testing.T) { tests := make(map[string]VmTest) - helper.CreateFileTests(t, p, &tests) + CreateFileTests(t, p, &tests) for name, test := range tests { /* @@ -121,9 +120,9 @@ func RunVmTest(p string, t *testing.T) { isVmTest := len(test.Exec) > 0 if isVmTest { - ret, logs, gas, err = helper.RunVm(statedb, env, test.Exec) + ret, logs, gas, err = RunVm(statedb, env, test.Exec) } else { - ret, logs, gas, err = helper.RunState(statedb, env, test.Transaction) + ret, logs, gas, err = RunState(statedb, env, test.Transaction) } switch name { @@ -131,7 +130,7 @@ func RunVmTest(p string, t *testing.T) { // on 19 May 2015 decided to skip these tests their output. case "mload32bitBound_return", "mload32bitBound_return2": default: - rexp := helper.FromHex(test.Out) + rexp := common.FromHex(test.Out) if bytes.Compare(rexp, ret) != 0 { t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) } @@ -192,7 +191,7 @@ func RunVmTest(p string, t *testing.T) { t.Errorf("'%s' log address expected %v got %x", name, log.AddressF, logs[i].Address) } - if !bytes.Equal(logs[i].Data, helper.FromHex(log.DataF)) { + if !bytes.Equal(logs[i].Data, common.FromHex(log.DataF)) { t.Errorf("'%s' log data expected %v got %x", name, log.DataF, logs[i].Data) } From 7c6ef0ddac91564f31ef852fd4ef1e821db17c2e Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 10 Jun 2015 14:38:39 -0400 Subject: [PATCH 06/24] Separate and identify tests runners --- tests/block_test_util.go | 3 +- tests/state_test.go | 34 ++--- tests/state_test_util.go | 181 +++++++++++++++++++++++++ tests/transaction_test_util.go | 2 +- tests/vm.go | 220 ------------------------------- tests/vm_test_util.go | 234 ++++++++++++++++++++++++++------- 6 files changed, 389 insertions(+), 285 deletions(-) create mode 100644 tests/state_test_util.go delete mode 100644 tests/vm.go diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 224c14283..e60607c0f 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -134,7 +134,8 @@ func runBlockTest(name string, test *BlockTest, t *testing.T) { if err = test.ValidatePostState(statedb); err != nil { t.Fatal("post state validation failed: %v", err) } - t.Log("Test passed: ", name) + fmt.Println("Block test passed: ", name) + // t.Log("Block test passed: ", name) } func testEthConfig() *eth.Config { diff --git a/tests/state_test.go b/tests/state_test.go index fa000ec53..dbef7bd0c 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -10,62 +10,62 @@ var stateTestDir = filepath.Join(baseDir, "StateTests") func TestStateSystemOperations(t *testing.T) { fn := filepath.Join(stateTestDir, "stSystemOperationsTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestStateExample(t *testing.T) { fn := filepath.Join(stateTestDir, "stExample.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestStatePreCompiledContracts(t *testing.T) { fn := filepath.Join(stateTestDir, "stPreCompiledContracts.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestStateRecursiveCreate(t *testing.T) { fn := filepath.Join(stateTestDir, "stRecursiveCreate.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestStateSpecial(t *testing.T) { fn := filepath.Join(stateTestDir, "stSpecialTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestStateRefund(t *testing.T) { fn := filepath.Join(stateTestDir, "stRefundTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestStateBlockHash(t *testing.T) { fn := filepath.Join(stateTestDir, "stBlockHashTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestStateInitCode(t *testing.T) { fn := filepath.Join(stateTestDir, "stInitCodeTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestStateLog(t *testing.T) { fn := filepath.Join(stateTestDir, "stLogTests.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestStateTransaction(t *testing.T) { fn := filepath.Join(stateTestDir, "stTransactionTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestCallCreateCallCode(t *testing.T) { fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestMemory(t *testing.T) { fn := filepath.Join(stateTestDir, "stMemoryTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestMemoryStress(t *testing.T) { @@ -73,7 +73,7 @@ func TestMemoryStress(t *testing.T) { t.Skip() } fn := filepath.Join(stateTestDir, "stMemoryStressTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestQuadraticComplexity(t *testing.T) { @@ -81,22 +81,22 @@ func TestQuadraticComplexity(t *testing.T) { t.Skip() } fn := filepath.Join(stateTestDir, "stQuadraticComplexityTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestSolidity(t *testing.T) { fn := filepath.Join(stateTestDir, "stSolidityTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestWallet(t *testing.T) { fn := filepath.Join(stateTestDir, "stWalletTest.json") - RunVmTest(fn, t) + RunStateTest(fn, t) } func TestStateTestsRandom(t *testing.T) { fns, _ := filepath.Glob("./files/StateTests/RandomTests/*") for _, fn := range fns { - RunVmTest(fn, t) + RunStateTest(fn, t) } } diff --git a/tests/state_test_util.go b/tests/state_test_util.go new file mode 100644 index 000000000..1f481147e --- /dev/null +++ b/tests/state_test_util.go @@ -0,0 +1,181 @@ +package tests + +import ( + "bytes" + // "errors" + "fmt" + "math/big" + "strconv" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" + // "github.com/ethereum/go-ethereum/logger" +) + +func RunStateTest(p string, t *testing.T) { + + tests := make(map[string]VmTest) + CreateFileTests(t, p, &tests) + + for name, test := range tests { + /* + vm.Debug = true + glog.SetV(4) + glog.SetToStderr(true) + if name != "Call50000_sha256" { + continue + } + */ + 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.NewValue(common.FromHex(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) + + switch name { + // the memory required for these tests (4294967297 bytes) would take too much time. + // on 19 May 2015 decided to skip these tests their output. + case "mload32bitBound_return", "mload32bitBound_return2": + default: + rexp := common.FromHex(test.Out) + if bytes.Compare(rexp, ret) != 0 { + t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) + } + } + + for addr, account := range test.Post { + obj := statedb.GetStateObject(common.HexToAddress(addr)) + if obj == nil { + continue + } + + // if len(test.Exec) == 0 { + if obj.Balance().Cmp(common.Big(account.Balance)) != 0 { + t.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() { + // t.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 { + t.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() { + t.Errorf("%s's : Post state root error. Expected %s, got %x", name, test.PostStateRoot, statedb.Root()) + } + + if len(test.Logs) > 0 { + if len(test.Logs) != len(logs) { + t.Errorf("log length mismatch. Expected %d, got %d", len(test.Logs), len(logs)) + } else { + for i, log := range test.Logs { + if common.HexToAddress(log.AddressF) != logs[i].Address { + t.Errorf("'%s' log address expected %v got %x", name, log.AddressF, logs[i].Address) + } + + if !bytes.Equal(logs[i].Data, common.FromHex(log.DataF)) { + t.Errorf("'%s' log data expected %v got %x", name, log.DataF, logs[i].Data) + } + + if len(log.TopicsF) != len(logs[i].Topics) { + t.Errorf("'%s' log topics length expected %d got %d", name, len(log.TopicsF), logs[i].Topics) + } else { + for j, topic := range log.TopicsF { + if common.HexToHash(topic) != logs[i].Topics[j] { + t.Errorf("'%s' log topic[%d] expected %v got %x", name, j, topic, logs[i].Topics[j]) + } + } + } + genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256) + + if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) { + t.Errorf("'%s' bloom mismatch", name) + } + } + } + } + + fmt.Println("State test passed: ", name) + //fmt.Println(string(statedb.Dump())) + } + // logger.Flush() +} + +func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) { + var ( + keyPair, _ = crypto.NewKeyPairFromSec([]byte(common.Hex2Bytes(tx["secretKey"]))) + data = common.FromHex(tx["data"]) + gas = common.Big(tx["gasLimit"]) + price = common.Big(tx["gasPrice"]) + value = common.Big(tx["value"]) + nonce = common.Big(tx["nonce"]).Uint64() + caddr = common.HexToAddress(env["currentCoinbase"]) + ) + + var to *common.Address + if len(tx["to"]) > 2 { + t := common.HexToAddress(tx["to"]) + to = &t + } + // Set pre compiled contracts + vm.Precompiled = vm.PrecompiledContracts() + + snapshot := statedb.Copy() + coinbase := statedb.GetOrNewStateObject(caddr) + coinbase.SetGasPool(common.Big(env["currentGasLimit"])) + + message := NewMessage(common.BytesToAddress(keyPair.Address()), to, data, value, gas, price, nonce) + vmenv := NewEnvFromMap(statedb, env, tx) + vmenv.origin = common.BytesToAddress(keyPair.Address()) + ret, _, err := core.ApplyMessage(vmenv, message, coinbase) + if core.IsNonceErr(err) || core.IsInvalidTxErr(err) { + statedb.Set(snapshot) + } + statedb.Update() + + return ret, vmenv.state.Logs(), vmenv.Gas, err +} diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index 82038c3e8..a6cea972a 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -42,7 +42,7 @@ func RunTransactionTests(file string, notWorking map[string]bool) error { if err = runTest(in); err != nil { return fmt.Errorf("bad test %s: %v", name, err) } - fmt.Println("Test passed:", name) + fmt.Println("Transaction test passed:", name) } } return nil diff --git a/tests/vm.go b/tests/vm.go deleted file mode 100644 index 52e498ccc..000000000 --- a/tests/vm.go +++ /dev/null @@ -1,220 +0,0 @@ -package tests - -import ( - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" -) - -type Env struct { - depth int - state *state.StateDB - skipTransfer bool - initial bool - Gas *big.Int - - origin common.Address - //parent common.Hash - coinbase common.Address - - number *big.Int - time int64 - difficulty *big.Int - gasLimit *big.Int - - vmTest bool - logs []vm.StructLog -} - -func NewEnv(state *state.StateDB) *Env { - return &Env{ - state: state, - } -} - -func (self *Env) StructLogs() []vm.StructLog { - return self.logs -} - -func (self *Env) AddStructLog(log vm.StructLog) { - self.logs = append(self.logs, log) -} - -func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env { - env := NewEnv(state) - - env.origin = common.HexToAddress(exeValues["caller"]) - //env.parent = common.Hex2Bytes(envValues["previousHash"]) - env.coinbase = common.HexToAddress(envValues["currentCoinbase"]) - env.number = common.Big(envValues["currentNumber"]) - env.time = common.Big(envValues["currentTimestamp"]).Int64() - env.difficulty = common.Big(envValues["currentDifficulty"]) - env.gasLimit = common.Big(envValues["currentGasLimit"]) - env.Gas = new(big.Int) - - return env -} - -func (self *Env) Origin() common.Address { return self.origin } -func (self *Env) BlockNumber() *big.Int { return self.number } - -//func (self *Env) PrevHash() []byte { return self.parent } -func (self *Env) Coinbase() common.Address { return self.coinbase } -func (self *Env) Time() int64 { return self.time } -func (self *Env) Difficulty() *big.Int { return self.difficulty } -func (self *Env) State() *state.StateDB { return self.state } -func (self *Env) GasLimit() *big.Int { return self.gasLimit } -func (self *Env) VmType() vm.Type { return vm.StdVmTy } -func (self *Env) GetHash(n uint64) common.Hash { - return common.BytesToHash(crypto.Sha3([]byte(big.NewInt(int64(n)).String()))) -} -func (self *Env) AddLog(log *state.Log) { - self.state.AddLog(log) -} -func (self *Env) Depth() int { return self.depth } -func (self *Env) SetDepth(i int) { self.depth = i } -func (self *Env) Transfer(from, to vm.Account, amount *big.Int) error { - if self.skipTransfer { - // ugly hack - if self.initial { - self.initial = false - return nil - } - - if from.Balance().Cmp(amount) < 0 { - return errors.New("Insufficient balance in account") - } - - return nil - } - return vm.Transfer(from, to, amount) -} - -func (self *Env) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *core.Execution { - exec := core.NewExecution(self, addr, data, gas, price, value) - - return exec -} - -func (self *Env) Call(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - if self.vmTest && self.depth > 0 { - caller.ReturnGas(gas, price) - - return nil, nil - } - exe := self.vm(&addr, data, gas, price, value) - ret, err := exe.Call(addr, caller) - self.Gas = exe.Gas - - return ret, err - -} -func (self *Env) CallCode(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - if self.vmTest && self.depth > 0 { - caller.ReturnGas(gas, price) - - return nil, nil - } - - caddr := caller.Address() - exe := self.vm(&caddr, data, gas, price, value) - return exe.Call(addr, caller) -} - -func (self *Env) Create(caller vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { - exe := self.vm(nil, data, gas, price, value) - if self.vmTest { - caller.ReturnGas(gas, price) - - nonce := self.state.GetNonce(caller.Address()) - obj := self.state.GetOrNewStateObject(crypto.CreateAddress(caller.Address(), nonce)) - - return nil, nil, obj - } else { - return exe.Create(caller) - } -} - -func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Logs, *big.Int, error) { - var ( - to = common.HexToAddress(exec["address"]) - from = common.HexToAddress(exec["caller"]) - data = common.FromHex(exec["data"]) - gas = common.Big(exec["gas"]) - price = common.Big(exec["gasPrice"]) - value = common.Big(exec["value"]) - ) - // Reset the pre-compiled contracts for VM tests. - vm.Precompiled = make(map[string]*vm.PrecompiledAccount) - - caller := state.GetOrNewStateObject(from) - - vmenv := NewEnvFromMap(state, env, exec) - vmenv.vmTest = true - vmenv.skipTransfer = true - vmenv.initial = true - ret, err := vmenv.Call(caller, to, data, gas, price, value) - - return ret, vmenv.state.Logs(), vmenv.Gas, err -} - -func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) { - var ( - keyPair, _ = crypto.NewKeyPairFromSec([]byte(common.Hex2Bytes(tx["secretKey"]))) - data = common.FromHex(tx["data"]) - gas = common.Big(tx["gasLimit"]) - price = common.Big(tx["gasPrice"]) - value = common.Big(tx["value"]) - nonce = common.Big(tx["nonce"]).Uint64() - caddr = common.HexToAddress(env["currentCoinbase"]) - ) - - var to *common.Address - if len(tx["to"]) > 2 { - t := common.HexToAddress(tx["to"]) - to = &t - } - // Set pre compiled contracts - vm.Precompiled = vm.PrecompiledContracts() - - snapshot := statedb.Copy() - coinbase := statedb.GetOrNewStateObject(caddr) - coinbase.SetGasPool(common.Big(env["currentGasLimit"])) - - message := NewMessage(common.BytesToAddress(keyPair.Address()), to, data, value, gas, price, nonce) - vmenv := NewEnvFromMap(statedb, env, tx) - vmenv.origin = common.BytesToAddress(keyPair.Address()) - ret, _, err := core.ApplyMessage(vmenv, message, coinbase) - if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || state.IsGasLimitErr(err) { - statedb.Set(snapshot) - } - statedb.Update() - - return ret, vmenv.state.Logs(), vmenv.Gas, err -} - -type Message struct { - from common.Address - to *common.Address - value, gas, price *big.Int - data []byte - nonce uint64 -} - -func NewMessage(from common.Address, to *common.Address, data []byte, value, gas, price *big.Int, nonce uint64) Message { - return Message{from, to, value, gas, price, data, nonce} -} - -func (self Message) Hash() []byte { return nil } -func (self Message) From() (common.Address, error) { return self.from, nil } -func (self Message) To() *common.Address { return self.to } -func (self Message) GasPrice() *big.Int { return self.price } -func (self Message) Gas() *big.Int { return self.gas } -func (self Message) Value() *big.Int { return self.value } -func (self Message) Nonce() uint64 { return self.nonce } -func (self Message) Data() []byte { return self.data } diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index cf95db80f..3852ba4bf 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -2,15 +2,20 @@ package tests import ( "bytes" + "errors" + "fmt" "math/big" "strconv" "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/logger" + // "github.com/ethereum/go-ethereum/logger" ) type Account struct { @@ -118,32 +123,19 @@ func RunVmTest(p string, t *testing.T) { logs state.Logs ) - isVmTest := len(test.Exec) > 0 - if isVmTest { - ret, logs, gas, err = RunVm(statedb, env, test.Exec) + ret, logs, gas, err = RunVm(statedb, env, test.Exec) + + rexp := common.FromHex(test.Out) + if bytes.Compare(rexp, ret) != 0 { + t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) + } + + if len(test.Gas) == 0 && err == nil { + t.Errorf("%s's gas unspecified, indicating an error. VM returned (incorrectly) successfull", name) } else { - ret, logs, gas, err = RunState(statedb, env, test.Transaction) - } - - switch name { - // the memory required for these tests (4294967297 bytes) would take too much time. - // on 19 May 2015 decided to skip these tests their output. - case "mload32bitBound_return", "mload32bitBound_return2": - default: - rexp := common.FromHex(test.Out) - if bytes.Compare(rexp, ret) != 0 { - t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) - } - } - - if isVmTest { - if len(test.Gas) == 0 && err == nil { - t.Errorf("%s's gas unspecified, indicating an error. VM returned (incorrectly) successfull", name) - } else { - gexp := common.Big(test.Gas) - if gexp.Cmp(gas) != 0 { - t.Errorf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas) - } + gexp := common.Big(test.Gas) + if gexp.Cmp(gas) != 0 { + t.Errorf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas) } } @@ -153,17 +145,6 @@ func RunVmTest(p string, t *testing.T) { continue } - if len(test.Exec) == 0 { - if obj.Balance().Cmp(common.Big(account.Balance)) != 0 { - t.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() { - t.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)) vexp := common.HexToHash(value) @@ -174,14 +155,6 @@ func RunVmTest(p string, t *testing.T) { } } - if !isVmTest { - statedb.Sync() - //if !bytes.Equal(common.Hex2Bytes(test.PostStateRoot), statedb.Root()) { - if common.HexToHash(test.PostStateRoot) != statedb.Root() { - t.Errorf("%s's : Post state root error. Expected %s, got %x", name, test.PostStateRoot, statedb.Root()) - } - } - if len(test.Logs) > 0 { if len(test.Logs) != len(logs) { t.Errorf("log length mismatch. Expected %d, got %d", len(test.Logs), len(logs)) @@ -212,7 +185,176 @@ func RunVmTest(p string, t *testing.T) { } } } + + fmt.Println("VM test passed: ", name) + //fmt.Println(string(statedb.Dump())) } - logger.Flush() + // logger.Flush() } + +type Env struct { + depth int + state *state.StateDB + skipTransfer bool + initial bool + Gas *big.Int + + origin common.Address + //parent common.Hash + coinbase common.Address + + number *big.Int + time int64 + difficulty *big.Int + gasLimit *big.Int + + logs state.Logs + + vmTest bool +} + +func NewEnv(state *state.StateDB) *Env { + return &Env{ + state: state, + } +} + +func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env { + env := NewEnv(state) + + env.origin = common.HexToAddress(exeValues["caller"]) + //env.parent = common.Hex2Bytes(envValues["previousHash"]) + env.coinbase = common.HexToAddress(envValues["currentCoinbase"]) + env.number = common.Big(envValues["currentNumber"]) + env.time = common.Big(envValues["currentTimestamp"]).Int64() + env.difficulty = common.Big(envValues["currentDifficulty"]) + env.gasLimit = common.Big(envValues["currentGasLimit"]) + env.Gas = new(big.Int) + + return env +} + +func (self *Env) Origin() common.Address { return self.origin } +func (self *Env) BlockNumber() *big.Int { return self.number } + +//func (self *Env) PrevHash() []byte { return self.parent } +func (self *Env) Coinbase() common.Address { return self.coinbase } +func (self *Env) Time() int64 { return self.time } +func (self *Env) Difficulty() *big.Int { return self.difficulty } +func (self *Env) State() *state.StateDB { return self.state } +func (self *Env) GasLimit() *big.Int { return self.gasLimit } +func (self *Env) VmType() vm.Type { return vm.StdVmTy } +func (self *Env) GetHash(n uint64) common.Hash { + return common.BytesToHash(crypto.Sha3([]byte(big.NewInt(int64(n)).String()))) +} +func (self *Env) AddLog(log *state.Log) { + self.state.AddLog(log) +} +func (self *Env) Depth() int { return self.depth } +func (self *Env) SetDepth(i int) { self.depth = i } +func (self *Env) Transfer(from, to vm.Account, amount *big.Int) error { + if self.skipTransfer { + // ugly hack + if self.initial { + self.initial = false + return nil + } + + if from.Balance().Cmp(amount) < 0 { + return errors.New("Insufficient balance in account") + } + + return nil + } + return vm.Transfer(from, to, amount) +} + +func (self *Env) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *core.Execution { + exec := core.NewExecution(self, addr, data, gas, price, value) + + return exec +} + +func (self *Env) Call(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { + if self.vmTest && self.depth > 0 { + caller.ReturnGas(gas, price) + + return nil, nil + } + exe := self.vm(&addr, data, gas, price, value) + ret, err := exe.Call(addr, caller) + self.Gas = exe.Gas + + return ret, err + +} +func (self *Env) CallCode(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { + if self.vmTest && self.depth > 0 { + caller.ReturnGas(gas, price) + + return nil, nil + } + + caddr := caller.Address() + exe := self.vm(&caddr, data, gas, price, value) + return exe.Call(addr, caller) +} + +func (self *Env) Create(caller vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { + exe := self.vm(nil, data, gas, price, value) + if self.vmTest { + caller.ReturnGas(gas, price) + + nonce := self.state.GetNonce(caller.Address()) + obj := self.state.GetOrNewStateObject(crypto.CreateAddress(caller.Address(), nonce)) + + return nil, nil, obj + } else { + return exe.Create(caller) + } +} + +func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Logs, *big.Int, error) { + var ( + to = common.HexToAddress(exec["address"]) + from = common.HexToAddress(exec["caller"]) + data = common.FromHex(exec["data"]) + gas = common.Big(exec["gas"]) + price = common.Big(exec["gasPrice"]) + value = common.Big(exec["value"]) + ) + // Reset the pre-compiled contracts for VM tests. + vm.Precompiled = make(map[string]*vm.PrecompiledAccount) + + caller := state.GetOrNewStateObject(from) + + vmenv := NewEnvFromMap(state, env, exec) + vmenv.vmTest = true + vmenv.skipTransfer = true + vmenv.initial = true + ret, err := vmenv.Call(caller, to, data, gas, price, value) + + return ret, vmenv.state.Logs(), vmenv.Gas, err +} + +type Message struct { + from common.Address + to *common.Address + value, gas, price *big.Int + data []byte + nonce uint64 +} + +func NewMessage(from common.Address, to *common.Address, data []byte, value, gas, price *big.Int, nonce uint64) Message { + return Message{from, to, value, gas, price, data, nonce} +} + +func (self Message) Hash() []byte { return nil } +func (self Message) From() (common.Address, error) { return self.from, nil } +func (self Message) To() *common.Address { return self.to } +func (self Message) GasPrice() *big.Int { return self.price } +func (self Message) Gas() *big.Int { return self.gas } +func (self Message) Value() *big.Int { return self.value } +func (self Message) Nonce() uint64 { return self.nonce } +func (self Message) Data() []byte { return self.data } From 24554629b162d20a1f945386a45e3221c58adc2b Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 10 Jun 2015 15:02:16 -0400 Subject: [PATCH 07/24] DRY log check --- tests/state_test_util.go | 74 ++++++++++++++++++++++------------------ tests/vm_test_util.go | 35 ++++--------------- 2 files changed, 47 insertions(+), 62 deletions(-) diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 1f481147e..91a8367e7 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -75,22 +75,20 @@ func RunStateTest(p string, t *testing.T) { } } + // check post state for addr, account := range test.Post { obj := statedb.GetStateObject(common.HexToAddress(addr)) if obj == nil { continue } - // if len(test.Exec) == 0 { if obj.Balance().Cmp(common.Big(account.Balance)) != 0 { t.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() { - // t.Errorf("%s's : (%x) nonce failed. Expected %v, got %v\n", name, obj.Address().Bytes()[:4], account.Nonce, obj.Nonce()) - // } - - // } + if obj.Nonce() != common.String2Big(account.Nonce).Uint64() { + t.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() @@ -108,34 +106,11 @@ func RunStateTest(p string, t *testing.T) { t.Errorf("%s's : Post state root error. Expected %s, got %x", name, test.PostStateRoot, statedb.Root()) } + // check logs if len(test.Logs) > 0 { - if len(test.Logs) != len(logs) { - t.Errorf("log length mismatch. Expected %d, got %d", len(test.Logs), len(logs)) - } else { - for i, log := range test.Logs { - if common.HexToAddress(log.AddressF) != logs[i].Address { - t.Errorf("'%s' log address expected %v got %x", name, log.AddressF, logs[i].Address) - } - - if !bytes.Equal(logs[i].Data, common.FromHex(log.DataF)) { - t.Errorf("'%s' log data expected %v got %x", name, log.DataF, logs[i].Data) - } - - if len(log.TopicsF) != len(logs[i].Topics) { - t.Errorf("'%s' log topics length expected %d got %d", name, len(log.TopicsF), logs[i].Topics) - } else { - for j, topic := range log.TopicsF { - if common.HexToHash(topic) != logs[i].Topics[j] { - t.Errorf("'%s' log topic[%d] expected %v got %x", name, j, topic, logs[i].Topics[j]) - } - } - } - genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256) - - if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) { - t.Errorf("'%s' bloom mismatch", name) - } - } + lerr := CheckLogs(test.Logs, logs, t) + if lerr != nil { + t.Errorf("'%s' ", name, lerr.Error()) } } @@ -145,6 +120,39 @@ func RunStateTest(p string, t *testing.T) { // logger.Flush() } +func CheckLogs(tlog []Log, logs state.Logs, t *testing.T) error { + + if len(tlog) != len(logs) { + return fmt.Errorf("log length mismatch. Expected %d, got %d", len(tlog), len(logs)) + } else { + for i, log := range tlog { + if common.HexToAddress(log.AddressF) != logs[i].Address { + return fmt.Errorf("log address expected %v got %x", log.AddressF, logs[i].Address) + } + + if !bytes.Equal(logs[i].Data, common.FromHex(log.DataF)) { + return fmt.Errorf("log data expected %v got %x", log.DataF, logs[i].Data) + } + + if len(log.TopicsF) != len(logs[i].Topics) { + return fmt.Errorf("log topics length expected %d got %d", len(log.TopicsF), logs[i].Topics) + } else { + for j, topic := range log.TopicsF { + if common.HexToHash(topic) != logs[i].Topics[j] { + return fmt.Errorf("log topic[%d] expected %v got %x", j, topic, logs[i].Topics[j]) + } + } + } + genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256) + + if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) { + return fmt.Errorf("bloom mismatch") + } + } + } + return nil +} + func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) { var ( keyPair, _ = crypto.NewKeyPairFromSec([]byte(common.Hex2Bytes(tx["secretKey"]))) diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 3852ba4bf..6743a0872 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -11,7 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" + // "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" @@ -125,11 +125,13 @@ func RunVmTest(p string, t *testing.T) { ret, logs, gas, err = RunVm(statedb, env, test.Exec) + // Compare expectedand actual return rexp := common.FromHex(test.Out) if bytes.Compare(rexp, ret) != 0 { t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) } + // Check gas usage if len(test.Gas) == 0 && err == nil { t.Errorf("%s's gas unspecified, indicating an error. VM returned (incorrectly) successfull", name) } else { @@ -139,6 +141,7 @@ func RunVmTest(p string, t *testing.T) { } } + // check post state for addr, account := range test.Post { obj := statedb.GetStateObject(common.HexToAddress(addr)) if obj == nil { @@ -155,35 +158,9 @@ func RunVmTest(p string, t *testing.T) { } } + // check logs if len(test.Logs) > 0 { - if len(test.Logs) != len(logs) { - t.Errorf("log length mismatch. Expected %d, got %d", len(test.Logs), len(logs)) - } else { - for i, log := range test.Logs { - if common.HexToAddress(log.AddressF) != logs[i].Address { - t.Errorf("'%s' log address expected %v got %x", name, log.AddressF, logs[i].Address) - } - - if !bytes.Equal(logs[i].Data, common.FromHex(log.DataF)) { - t.Errorf("'%s' log data expected %v got %x", name, log.DataF, logs[i].Data) - } - - if len(log.TopicsF) != len(logs[i].Topics) { - t.Errorf("'%s' log topics length expected %d got %d", name, len(log.TopicsF), logs[i].Topics) - } else { - for j, topic := range log.TopicsF { - if common.HexToHash(topic) != logs[i].Topics[j] { - t.Errorf("'%s' log topic[%d] expected %v got %x", name, j, topic, logs[i].Topics[j]) - } - } - } - genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256) - - if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) { - t.Errorf("'%s' bloom mismatch", name) - } - } - } + CheckLogs(test.Logs, logs, t) } fmt.Println("VM test passed: ", name) From c5d6fcbaba545d1078f5411dc67208d5d388222e Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 10 Jun 2015 16:10:33 -0400 Subject: [PATCH 08/24] Return error up stack instead of passing testing var down --- tests/block_test.go | 22 ++++++------- tests/block_test_util.go | 23 ++++++++------ tests/init.go | 33 +++++++++++-------- tests/state_test.go | 68 ++++++++++++++++++++++++++++++---------- tests/state_test_util.go | 23 +++++++------- tests/vm_test.go | 56 ++++++++++++++++++++++++--------- tests/vm_test_util.go | 18 ++++++----- 7 files changed, 159 insertions(+), 84 deletions(-) diff --git a/tests/block_test.go b/tests/block_test.go index 1f2e5a15b..33d4caec6 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -10,40 +10,38 @@ var blockTestDir = filepath.Join(baseDir, "BlockTests") // TODO: refactor test setup & execution to better align with vm and tx tests func TestBcValidBlockTests(t *testing.T) { - // SimpleTx3 genesis block does not validate against calculated state root - // as of 2015-06-09. unskip once working /Gustav - runBlockTestsInFile(filepath.Join(blockTestDir, "bcValidBlockTest.json"), []string{"SimpleTx3"}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcValidBlockTest.json"), []string{"SimpleTx3"}) } func TestBcUncleTests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcUncleTest.json"), []string{}, t) - runBlockTestsInFile(filepath.Join(blockTestDir, "bcBruncleTest.json"), []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcUncleTest.json"), []string{}) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcBruncleTest.json"), []string{}) } func TestBcUncleHeaderValidityTests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), []string{}) } func TestBcInvalidHeaderTests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), []string{}) } func TestBcInvalidRLPTests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), []string{}) } func TestBcRPCAPITests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcRPC_API_Test.json"), []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcRPC_API_Test.json"), []string{}) } func TestBcForkBlockTests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcForkBlockTest.json"), []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcForkBlockTest.json"), []string{}) } func TestBcTotalDifficulty(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), []string{}) } func TestBcWallet(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcWalletTest.json"), []string{}, t) + runBlockTestsInFile(filepath.Join(blockTestDir, "bcWalletTest.json"), []string{}) } diff --git a/tests/block_test_util.go b/tests/block_test_util.go index e60607c0f..ec532d178 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -11,7 +11,6 @@ import ( "runtime" "strconv" "strings" - "testing" "time" "github.com/ethereum/go-ethereum/accounts" @@ -87,10 +86,10 @@ type btTransaction struct { Value string } -func runBlockTestsInFile(filepath string, snafus []string, t *testing.T) { +func runBlockTestsInFile(filepath string, snafus []string) error { bt, err := LoadBlockTests(filepath) if err != nil { - t.Fatal(err) + return nil } notWorking := make(map[string]bool, 100) @@ -100,21 +99,24 @@ func runBlockTestsInFile(filepath string, snafus []string, t *testing.T) { for name, test := range bt { if !notWorking[name] { - runBlockTest(name, test, t) + if err := runBlockTest(name, test); err != nil { + return err + } } } + return nil } -func runBlockTest(name string, test *BlockTest, t *testing.T) { +func runBlockTest(name string, test *BlockTest) error { cfg := testEthConfig() ethereum, err := eth.New(cfg) if err != nil { - t.Fatalf("%v", err) + return err } err = ethereum.Start() if err != nil { - t.Fatalf("%v", err) + return err } // import the genesis block @@ -123,19 +125,20 @@ func runBlockTest(name string, test *BlockTest, t *testing.T) { // import pre accounts statedb, err := test.InsertPreState(ethereum) if err != nil { - t.Fatalf("InsertPreState: %v", err) + return fmt.Errorf("InsertPreState: %v", err) } err = test.TryBlocksInsert(ethereum.ChainManager()) if err != nil { - t.Fatal(err) + return err } if err = test.ValidatePostState(statedb); err != nil { - t.Fatal("post state validation failed: %v", err) + return fmt.Errorf("post state validation failed: %v", err) } fmt.Println("Block test passed: ", name) // t.Log("Block test passed: ", name) + return nil } func testEthConfig() *eth.Config { diff --git a/tests/init.go b/tests/init.go index b487f81c3..4a176698f 100644 --- a/tests/init.go +++ b/tests/init.go @@ -1,13 +1,14 @@ package tests import ( + "bytes" "encoding/json" + "fmt" "io" "io/ioutil" // "log" "net/http" "os" - "testing" // logpkg "github.com/ethereum/go-ethereum/logger" ) @@ -20,34 +21,40 @@ import ( // logpkg.AddLogSystem(Logger) // } -func readJSON(t *testing.T, reader io.Reader, value interface{}) { +func readJSON(reader io.Reader, value interface{}) error { data, err := ioutil.ReadAll(reader) err = json.Unmarshal(data, &value) if err != nil { - t.Error(err) + return err } + return nil } -func CreateHttpTests(t *testing.T, uri string, value interface{}) { +func CreateHttpTests(uri string, value interface{}) error { resp, err := http.Get(uri) if err != nil { - t.Error(err) - - return + return err } defer resp.Body.Close() - readJSON(t, resp.Body, value) + err = readJSON(resp.Body, value) + if err != nil { + return err + } + return nil } -func CreateFileTests(t *testing.T, fn string, value interface{}) { +func CreateFileTests(fn string, value interface{}) error { file, err := os.Open(fn) if err != nil { - t.Error(err) - - return + return err } defer file.Close() - readJSON(t, file, value) + err = readJSON(file, value) + if err != nil { + return err + } + return nil +} } diff --git a/tests/state_test.go b/tests/state_test.go index dbef7bd0c..5c16a3e91 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -10,62 +10,86 @@ var stateTestDir = filepath.Join(baseDir, "StateTests") func TestStateSystemOperations(t *testing.T) { fn := filepath.Join(stateTestDir, "stSystemOperationsTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestStateExample(t *testing.T) { fn := filepath.Join(stateTestDir, "stExample.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestStatePreCompiledContracts(t *testing.T) { fn := filepath.Join(stateTestDir, "stPreCompiledContracts.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestStateRecursiveCreate(t *testing.T) { fn := filepath.Join(stateTestDir, "stRecursiveCreate.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestStateSpecial(t *testing.T) { fn := filepath.Join(stateTestDir, "stSpecialTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestStateRefund(t *testing.T) { fn := filepath.Join(stateTestDir, "stRefundTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestStateBlockHash(t *testing.T) { fn := filepath.Join(stateTestDir, "stBlockHashTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestStateInitCode(t *testing.T) { fn := filepath.Join(stateTestDir, "stInitCodeTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestStateLog(t *testing.T) { fn := filepath.Join(stateTestDir, "stLogTests.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestStateTransaction(t *testing.T) { fn := filepath.Join(stateTestDir, "stTransactionTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestCallCreateCallCode(t *testing.T) { fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestMemory(t *testing.T) { fn := filepath.Join(stateTestDir, "stMemoryTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestMemoryStress(t *testing.T) { @@ -73,7 +97,9 @@ func TestMemoryStress(t *testing.T) { t.Skip() } fn := filepath.Join(stateTestDir, "stMemoryStressTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestQuadraticComplexity(t *testing.T) { @@ -81,22 +107,30 @@ func TestQuadraticComplexity(t *testing.T) { t.Skip() } fn := filepath.Join(stateTestDir, "stQuadraticComplexityTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestSolidity(t *testing.T) { fn := filepath.Join(stateTestDir, "stSolidityTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestWallet(t *testing.T) { fn := filepath.Join(stateTestDir, "stWalletTest.json") - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } func TestStateTestsRandom(t *testing.T) { fns, _ := filepath.Glob("./files/StateTests/RandomTests/*") for _, fn := range fns { - RunStateTest(fn, t) + if err := RunStateTest(fn); err != nil { + t.Error(err) + } } } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 91a8367e7..de4af6d82 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -6,22 +6,22 @@ import ( "fmt" "math/big" "strconv" - "testing" + // "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" + // "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" // "github.com/ethereum/go-ethereum/logger" ) -func RunStateTest(p string, t *testing.T) { +func RunStateTest(p string) error { tests := make(map[string]VmTest) - CreateFileTests(t, p, &tests) + CreateFileTests(p, &tests) for name, test := range tests { /* @@ -38,7 +38,7 @@ func RunStateTest(p string, t *testing.T) { obj := StateObjectFromAccount(db, addr, account) statedb.SetStateObject(obj) for a, v := range account.Storage { - obj.SetState(common.HexToHash(a), common.NewValue(common.FromHex(v))) + obj.SetState(common.HexToHash(a), common.HexToHash(s)) } } @@ -64,6 +64,7 @@ func RunStateTest(p string, t *testing.T) { ret, logs, _, _ = RunState(statedb, env, test.Transaction) + // Compare expected and actual return switch name { // the memory required for these tests (4294967297 bytes) would take too much time. // on 19 May 2015 decided to skip these tests their output. @@ -71,7 +72,7 @@ func RunStateTest(p string, t *testing.T) { default: rexp := common.FromHex(test.Out) if bytes.Compare(rexp, ret) != 0 { - t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) + return fmt.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) } } @@ -83,11 +84,11 @@ func RunStateTest(p string, t *testing.T) { } if obj.Balance().Cmp(common.Big(account.Balance)) != 0 { - t.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())) + 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() { - t.Errorf("%s's : (%x) nonce failed. Expected %v, got %v\n", name, obj.Address().Bytes()[:4], account.Nonce, obj.Nonce()) + 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 { @@ -95,7 +96,7 @@ func RunStateTest(p string, t *testing.T) { vexp := common.FromHex(value) if bytes.Compare(v, vexp) != 0 { - t.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)) + 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)) } } } @@ -103,14 +104,14 @@ func RunStateTest(p string, t *testing.T) { statedb.Sync() //if !bytes.Equal(common.Hex2Bytes(test.PostStateRoot), statedb.Root()) { if common.HexToHash(test.PostStateRoot) != statedb.Root() { - t.Errorf("%s's : Post state root error. Expected %s, got %x", name, 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, t) if lerr != nil { - t.Errorf("'%s' ", name, lerr.Error()) + return fmt.Errorf("'%s' ", name, lerr.Error()) } } diff --git a/tests/vm_test.go b/tests/vm_test.go index faa3205bc..194e7b6fa 100644 --- a/tests/vm_test.go +++ b/tests/vm_test.go @@ -10,72 +10,100 @@ var vmTestDir = filepath.Join(baseDir, "VMTests") // I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail. func TestVMArithmetic(t *testing.T) { fn := filepath.Join(vmTestDir, "vmArithmeticTest.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestBitwiseLogicOperation(t *testing.T) { fn := filepath.Join(vmTestDir, "vmBitwiseLogicOperationTest.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestBlockInfo(t *testing.T) { fn := filepath.Join(vmTestDir, "vmBlockInfoTest.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestEnvironmentalInfo(t *testing.T) { fn := filepath.Join(vmTestDir, "vmEnvironmentalInfoTest.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestFlowOperation(t *testing.T) { fn := filepath.Join(vmTestDir, "vmIOandFlowOperationsTest.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestLogTest(t *testing.T) { fn := filepath.Join(vmTestDir, "vmLogTest.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestPerformance(t *testing.T) { fn := filepath.Join(vmTestDir, "vmPerformanceTest.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestPushDupSwap(t *testing.T) { fn := filepath.Join(vmTestDir, "vmPushDupSwapTest.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestVMSha3(t *testing.T) { fn := filepath.Join(vmTestDir, "vmSha3Test.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestVm(t *testing.T) { fn := filepath.Join(vmTestDir, "vmtests.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestVmLog(t *testing.T) { fn := filepath.Join(vmTestDir, "vmLogTest.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestInputLimits(t *testing.T) { fn := filepath.Join(vmTestDir, "vmInputLimits.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestInputLimitsLight(t *testing.T) { fn := filepath.Join(vmTestDir, "vmInputLimitsLight.json") - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } func TestVMRandom(t *testing.T) { fns, _ := filepath.Glob(filepath.Join(baseDir, "RandomTests", "*")) for _, fn := range fns { - RunVmTest(fn, t) + if err := RunVmTest(fn); err != nil { + t.Error(err) + } } } diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 6743a0872..5d9635afd 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -6,7 +6,7 @@ import ( "fmt" "math/big" "strconv" - "testing" + // "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -79,10 +79,13 @@ type VmTest struct { PostStateRoot string } -func RunVmTest(p string, t *testing.T) { +func RunVmTest(p string) error { tests := make(map[string]VmTest) - CreateFileTests(t, p, &tests) + err := CreateFileTests(p, &tests) + if err != nil { + return err + } for name, test := range tests { /* @@ -128,16 +131,16 @@ func RunVmTest(p string, t *testing.T) { // Compare expectedand actual return rexp := common.FromHex(test.Out) if bytes.Compare(rexp, ret) != 0 { - t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) + 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 { - t.Errorf("%s's gas unspecified, indicating an error. VM returned (incorrectly) successfull", name) + 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 { - t.Errorf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas) + return fmt.Errorf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas) } } @@ -153,7 +156,7 @@ func RunVmTest(p string, t *testing.T) { vexp := common.HexToHash(value) if v != vexp { - 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()) + 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()) } } } @@ -168,6 +171,7 @@ func RunVmTest(p string, t *testing.T) { //fmt.Println(string(statedb.Dump())) } // logger.Flush() + return nil } type Env struct { From b6d40a931286b4c998f58ad074db0a692aeace6e Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 10 Jun 2015 16:29:42 -0400 Subject: [PATCH 09/24] Cleanup/reorg --- tests/block_test.go | 4 - tests/init.go | 21 ++-- tests/state_test.go | 2 - tests/state_test_util.go | 39 +----- tests/transaction_test.go | 2 - tests/util.go | 252 ++++++++++++++++++++++++++++++++++++++ tests/vm_test.go | 2 - tests/vm_test_util.go | 216 +------------------------------- 8 files changed, 265 insertions(+), 273 deletions(-) create mode 100644 tests/util.go diff --git a/tests/block_test.go b/tests/block_test.go index 33d4caec6..f1a92be49 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -5,10 +5,6 @@ import ( "testing" ) -var baseDir = filepath.Join(".", "files") -var blockTestDir = filepath.Join(baseDir, "BlockTests") - -// TODO: refactor test setup & execution to better align with vm and tx tests func TestBcValidBlockTests(t *testing.T) { runBlockTestsInFile(filepath.Join(blockTestDir, "bcValidBlockTest.json"), []string{"SimpleTx3"}) } diff --git a/tests/init.go b/tests/init.go index 4a176698f..e6644ae60 100644 --- a/tests/init.go +++ b/tests/init.go @@ -1,25 +1,21 @@ package tests import ( - "bytes" "encoding/json" - "fmt" "io" "io/ioutil" - // "log" "net/http" "os" - - // logpkg "github.com/ethereum/go-ethereum/logger" + "path/filepath" ) -// var Logger *logpkg.StdLogSystem -// var Log = logpkg.NewLogger("TEST") - -// func init() { -// Logger = logpkg.NewStdLogSystem(os.Stdout, log.LstdFlags, logpkg.InfoLevel) -// logpkg.AddLogSystem(Logger) -// } +var ( + baseDir = filepath.Join(".", "files") + blockTestDir = filepath.Join(baseDir, "BlockTests") + stateTestDir = filepath.Join(baseDir, "StateTests") + transactionTestDir = filepath.Join(baseDir, "TransactionTests") + vmTestDir = filepath.Join(baseDir, "VMTests") +) func readJSON(reader io.Reader, value interface{}) error { data, err := ioutil.ReadAll(reader) @@ -57,4 +53,3 @@ func CreateFileTests(fn string, value interface{}) error { } return nil } -} diff --git a/tests/state_test.go b/tests/state_test.go index 5c16a3e91..9c3d6f209 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -6,8 +6,6 @@ import ( "testing" ) -var stateTestDir = filepath.Join(baseDir, "StateTests") - func TestStateSystemOperations(t *testing.T) { fn := filepath.Join(stateTestDir, "stSystemOperationsTest.json") if err := RunStateTest(fn); err != nil { diff --git a/tests/state_test_util.go b/tests/state_test_util.go index de4af6d82..29d7cebe8 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -2,20 +2,16 @@ package tests import ( "bytes" - // "errors" "fmt" "math/big" "strconv" - // "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" - // "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - // "github.com/ethereum/go-ethereum/logger" ) func RunStateTest(p string) error { @@ -109,7 +105,7 @@ func RunStateTest(p string) error { // check logs if len(test.Logs) > 0 { - lerr := CheckLogs(test.Logs, logs, t) + lerr := checkLogs(test.Logs, logs) if lerr != nil { return fmt.Errorf("'%s' ", name, lerr.Error()) } @@ -118,39 +114,6 @@ func RunStateTest(p string) error { fmt.Println("State test passed: ", name) //fmt.Println(string(statedb.Dump())) } - // logger.Flush() -} - -func CheckLogs(tlog []Log, logs state.Logs, t *testing.T) error { - - if len(tlog) != len(logs) { - return fmt.Errorf("log length mismatch. Expected %d, got %d", len(tlog), len(logs)) - } else { - for i, log := range tlog { - if common.HexToAddress(log.AddressF) != logs[i].Address { - return fmt.Errorf("log address expected %v got %x", log.AddressF, logs[i].Address) - } - - if !bytes.Equal(logs[i].Data, common.FromHex(log.DataF)) { - return fmt.Errorf("log data expected %v got %x", log.DataF, logs[i].Data) - } - - if len(log.TopicsF) != len(logs[i].Topics) { - return fmt.Errorf("log topics length expected %d got %d", len(log.TopicsF), logs[i].Topics) - } else { - for j, topic := range log.TopicsF { - if common.HexToHash(topic) != logs[i].Topics[j] { - return fmt.Errorf("log topic[%d] expected %v got %x", j, topic, logs[i].Topics[j]) - } - } - } - genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256) - - if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) { - return fmt.Errorf("bloom mismatch") - } - } - } return nil } diff --git a/tests/transaction_test.go b/tests/transaction_test.go index 05942d3bf..e1237dee2 100644 --- a/tests/transaction_test.go +++ b/tests/transaction_test.go @@ -5,8 +5,6 @@ import ( "testing" ) -var transactionTestDir = filepath.Join(baseDir, "TransactionTests") - func TestTransactions(t *testing.T) { notWorking := make(map[string]bool, 100) diff --git a/tests/util.go b/tests/util.go new file mode 100644 index 000000000..6554c4b94 --- /dev/null +++ b/tests/util.go @@ -0,0 +1,252 @@ +package tests + +import ( + "bytes" + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" +) + +func checkLogs(tlog []Log, logs state.Logs) error { + + if len(tlog) != len(logs) { + return fmt.Errorf("log length mismatch. Expected %d, got %d", len(tlog), len(logs)) + } else { + for i, log := range tlog { + if common.HexToAddress(log.AddressF) != logs[i].Address { + return fmt.Errorf("log address expected %v got %x", log.AddressF, logs[i].Address) + } + + if !bytes.Equal(logs[i].Data, common.FromHex(log.DataF)) { + return fmt.Errorf("log data expected %v got %x", log.DataF, logs[i].Data) + } + + if len(log.TopicsF) != len(logs[i].Topics) { + return fmt.Errorf("log topics length expected %d got %d", len(log.TopicsF), logs[i].Topics) + } else { + for j, topic := range log.TopicsF { + if common.HexToHash(topic) != logs[i].Topics[j] { + return fmt.Errorf("log topic[%d] expected %v got %x", j, topic, logs[i].Topics[j]) + } + } + } + genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256) + + if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) { + return fmt.Errorf("bloom mismatch") + } + } + } + return nil +} + +type Account struct { + Balance string + Code string + Nonce string + Storage map[string]string +} + +type Log struct { + AddressF string `json:"address"` + DataF string `json:"data"` + TopicsF []string `json:"topics"` + BloomF string `json:"bloom"` +} + +func (self Log) Address() []byte { return common.Hex2Bytes(self.AddressF) } +func (self Log) Data() []byte { return common.Hex2Bytes(self.DataF) } +func (self Log) RlpData() interface{} { return nil } +func (self Log) Topics() [][]byte { + t := make([][]byte, len(self.TopicsF)) + for i, topic := range self.TopicsF { + t[i] = common.Hex2Bytes(topic) + } + return t +} + +func StateObjectFromAccount(db common.Database, addr string, account Account) *state.StateObject { + obj := state.NewStateObject(common.HexToAddress(addr), db) + obj.SetBalance(common.Big(account.Balance)) + + if common.IsHex(account.Code) { + account.Code = account.Code[2:] + } + obj.SetCode(common.Hex2Bytes(account.Code)) + obj.SetNonce(common.Big(account.Nonce).Uint64()) + + return obj +} + +type VmEnv struct { + CurrentCoinbase string + CurrentDifficulty string + CurrentGasLimit string + CurrentNumber string + CurrentTimestamp interface{} + PreviousHash string +} + +type VmTest struct { + Callcreates interface{} + //Env map[string]string + Env VmEnv + Exec map[string]string + Transaction map[string]string + Logs []Log + Gas string + Out string + Post map[string]Account + Pre map[string]Account + PostStateRoot string +} + +type Env struct { + depth int + state *state.StateDB + skipTransfer bool + initial bool + Gas *big.Int + + origin common.Address + //parent common.Hash + coinbase common.Address + + number *big.Int + time int64 + difficulty *big.Int + gasLimit *big.Int + + logs state.Logs + + vmTest bool +} + +func NewEnv(state *state.StateDB) *Env { + return &Env{ + state: state, + } +} + +func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env { + env := NewEnv(state) + + env.origin = common.HexToAddress(exeValues["caller"]) + //env.parent = common.Hex2Bytes(envValues["previousHash"]) + env.coinbase = common.HexToAddress(envValues["currentCoinbase"]) + env.number = common.Big(envValues["currentNumber"]) + env.time = common.Big(envValues["currentTimestamp"]).Int64() + env.difficulty = common.Big(envValues["currentDifficulty"]) + env.gasLimit = common.Big(envValues["currentGasLimit"]) + env.Gas = new(big.Int) + + return env +} + +func (self *Env) Origin() common.Address { return self.origin } +func (self *Env) BlockNumber() *big.Int { return self.number } + +//func (self *Env) PrevHash() []byte { return self.parent } +func (self *Env) Coinbase() common.Address { return self.coinbase } +func (self *Env) Time() int64 { return self.time } +func (self *Env) Difficulty() *big.Int { return self.difficulty } +func (self *Env) State() *state.StateDB { return self.state } +func (self *Env) GasLimit() *big.Int { return self.gasLimit } +func (self *Env) VmType() vm.Type { return vm.StdVmTy } +func (self *Env) GetHash(n uint64) common.Hash { + return common.BytesToHash(crypto.Sha3([]byte(big.NewInt(int64(n)).String()))) +} +func (self *Env) AddLog(log *state.Log) { + self.state.AddLog(log) +} +func (self *Env) Depth() int { return self.depth } +func (self *Env) SetDepth(i int) { self.depth = i } +func (self *Env) Transfer(from, to vm.Account, amount *big.Int) error { + if self.skipTransfer { + // ugly hack + if self.initial { + self.initial = false + return nil + } + + if from.Balance().Cmp(amount) < 0 { + return errors.New("Insufficient balance in account") + } + + return nil + } + return vm.Transfer(from, to, amount) +} + +func (self *Env) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *core.Execution { + exec := core.NewExecution(self, addr, data, gas, price, value) + + return exec +} + +func (self *Env) Call(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { + if self.vmTest && self.depth > 0 { + caller.ReturnGas(gas, price) + + return nil, nil + } + exe := self.vm(&addr, data, gas, price, value) + ret, err := exe.Call(addr, caller) + self.Gas = exe.Gas + + return ret, err + +} +func (self *Env) CallCode(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { + if self.vmTest && self.depth > 0 { + caller.ReturnGas(gas, price) + + return nil, nil + } + + caddr := caller.Address() + exe := self.vm(&caddr, data, gas, price, value) + return exe.Call(addr, caller) +} + +func (self *Env) Create(caller vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { + exe := self.vm(nil, data, gas, price, value) + if self.vmTest { + caller.ReturnGas(gas, price) + + nonce := self.state.GetNonce(caller.Address()) + obj := self.state.GetOrNewStateObject(crypto.CreateAddress(caller.Address(), nonce)) + + return nil, nil, obj + } else { + return exe.Create(caller) + } +} + +type Message struct { + from common.Address + to *common.Address + value, gas, price *big.Int + data []byte + nonce uint64 +} + +func NewMessage(from common.Address, to *common.Address, data []byte, value, gas, price *big.Int, nonce uint64) Message { + return Message{from, to, value, gas, price, data, nonce} +} + +func (self Message) Hash() []byte { return nil } +func (self Message) From() (common.Address, error) { return self.from, nil } +func (self Message) To() *common.Address { return self.to } +func (self Message) GasPrice() *big.Int { return self.price } +func (self Message) Gas() *big.Int { return self.gas } +func (self Message) Value() *big.Int { return self.value } +func (self Message) Nonce() uint64 { return self.nonce } +func (self Message) Data() []byte { return self.data } diff --git a/tests/vm_test.go b/tests/vm_test.go index 194e7b6fa..d16d65aac 100644 --- a/tests/vm_test.go +++ b/tests/vm_test.go @@ -5,8 +5,6 @@ import ( "testing" ) -var vmTestDir = filepath.Join(baseDir, "VMTests") - // I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail. func TestVMArithmetic(t *testing.T) { fn := filepath.Join(vmTestDir, "vmArithmeticTest.json") diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 5d9635afd..066217620 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -2,83 +2,16 @@ package tests import ( "bytes" - "errors" "fmt" "math/big" "strconv" - // "testing" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" - // "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - // "github.com/ethereum/go-ethereum/logger" ) -type Account struct { - Balance string - Code string - Nonce string - Storage map[string]string -} - -type Log struct { - AddressF string `json:"address"` - DataF string `json:"data"` - TopicsF []string `json:"topics"` - BloomF string `json:"bloom"` -} - -func (self Log) Address() []byte { return common.Hex2Bytes(self.AddressF) } -func (self Log) Data() []byte { return common.Hex2Bytes(self.DataF) } -func (self Log) RlpData() interface{} { return nil } -func (self Log) Topics() [][]byte { - t := make([][]byte, len(self.TopicsF)) - for i, topic := range self.TopicsF { - t[i] = common.Hex2Bytes(topic) - } - return t -} - -func StateObjectFromAccount(db common.Database, addr string, account Account) *state.StateObject { - obj := state.NewStateObject(common.HexToAddress(addr), db) - obj.SetBalance(common.Big(account.Balance)) - - if common.IsHex(account.Code) { - account.Code = account.Code[2:] - } - obj.SetCode(common.Hex2Bytes(account.Code)) - obj.SetNonce(common.Big(account.Nonce).Uint64()) - - return obj -} - -type VmEnv struct { - CurrentCoinbase string - CurrentDifficulty string - CurrentGasLimit string - CurrentNumber string - CurrentTimestamp interface{} - PreviousHash string -} - -type VmTest struct { - Callcreates interface{} - //Env map[string]string - Env VmEnv - Exec map[string]string - Transaction map[string]string - Logs []Log - Gas string - Out string - Post map[string]Account - Pre map[string]Account - PostStateRoot string -} - func RunVmTest(p string) error { tests := make(map[string]VmTest) @@ -163,139 +96,19 @@ func RunVmTest(p string) error { // check logs if len(test.Logs) > 0 { - CheckLogs(test.Logs, logs, t) + lerr := checkLogs(test.Logs, logs) + if lerr != nil { + return fmt.Errorf("'%s' ", name, lerr.Error()) + } } fmt.Println("VM test passed: ", name) //fmt.Println(string(statedb.Dump())) } - // logger.Flush() return nil } -type Env struct { - depth int - state *state.StateDB - skipTransfer bool - initial bool - Gas *big.Int - - origin common.Address - //parent common.Hash - coinbase common.Address - - number *big.Int - time int64 - difficulty *big.Int - gasLimit *big.Int - - logs state.Logs - - vmTest bool -} - -func NewEnv(state *state.StateDB) *Env { - return &Env{ - state: state, - } -} - -func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env { - env := NewEnv(state) - - env.origin = common.HexToAddress(exeValues["caller"]) - //env.parent = common.Hex2Bytes(envValues["previousHash"]) - env.coinbase = common.HexToAddress(envValues["currentCoinbase"]) - env.number = common.Big(envValues["currentNumber"]) - env.time = common.Big(envValues["currentTimestamp"]).Int64() - env.difficulty = common.Big(envValues["currentDifficulty"]) - env.gasLimit = common.Big(envValues["currentGasLimit"]) - env.Gas = new(big.Int) - - return env -} - -func (self *Env) Origin() common.Address { return self.origin } -func (self *Env) BlockNumber() *big.Int { return self.number } - -//func (self *Env) PrevHash() []byte { return self.parent } -func (self *Env) Coinbase() common.Address { return self.coinbase } -func (self *Env) Time() int64 { return self.time } -func (self *Env) Difficulty() *big.Int { return self.difficulty } -func (self *Env) State() *state.StateDB { return self.state } -func (self *Env) GasLimit() *big.Int { return self.gasLimit } -func (self *Env) VmType() vm.Type { return vm.StdVmTy } -func (self *Env) GetHash(n uint64) common.Hash { - return common.BytesToHash(crypto.Sha3([]byte(big.NewInt(int64(n)).String()))) -} -func (self *Env) AddLog(log *state.Log) { - self.state.AddLog(log) -} -func (self *Env) Depth() int { return self.depth } -func (self *Env) SetDepth(i int) { self.depth = i } -func (self *Env) Transfer(from, to vm.Account, amount *big.Int) error { - if self.skipTransfer { - // ugly hack - if self.initial { - self.initial = false - return nil - } - - if from.Balance().Cmp(amount) < 0 { - return errors.New("Insufficient balance in account") - } - - return nil - } - return vm.Transfer(from, to, amount) -} - -func (self *Env) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *core.Execution { - exec := core.NewExecution(self, addr, data, gas, price, value) - - return exec -} - -func (self *Env) Call(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - if self.vmTest && self.depth > 0 { - caller.ReturnGas(gas, price) - - return nil, nil - } - exe := self.vm(&addr, data, gas, price, value) - ret, err := exe.Call(addr, caller) - self.Gas = exe.Gas - - return ret, err - -} -func (self *Env) CallCode(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - if self.vmTest && self.depth > 0 { - caller.ReturnGas(gas, price) - - return nil, nil - } - - caddr := caller.Address() - exe := self.vm(&caddr, data, gas, price, value) - return exe.Call(addr, caller) -} - -func (self *Env) Create(caller vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { - exe := self.vm(nil, data, gas, price, value) - if self.vmTest { - caller.ReturnGas(gas, price) - - nonce := self.state.GetNonce(caller.Address()) - obj := self.state.GetOrNewStateObject(crypto.CreateAddress(caller.Address(), nonce)) - - return nil, nil, obj - } else { - return exe.Create(caller) - } -} - func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Logs, *big.Int, error) { var ( to = common.HexToAddress(exec["address"]) @@ -318,24 +131,3 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Log return ret, vmenv.state.Logs(), vmenv.Gas, err } - -type Message struct { - from common.Address - to *common.Address - value, gas, price *big.Int - data []byte - nonce uint64 -} - -func NewMessage(from common.Address, to *common.Address, data []byte, value, gas, price *big.Int, nonce uint64) Message { - return Message{from, to, value, gas, price, data, nonce} -} - -func (self Message) Hash() []byte { return nil } -func (self Message) From() (common.Address, error) { return self.from, nil } -func (self Message) To() *common.Address { return self.to } -func (self Message) GasPrice() *big.Int { return self.price } -func (self Message) Gas() *big.Int { return self.gas } -func (self Message) Value() *big.Int { return self.value } -func (self Message) Nonce() uint64 { return self.nonce } -func (self Message) Data() []byte { return self.data } From ac0637c41332de1f49fb0955f4fbe0fb908a77d5 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 10 Jun 2015 17:04:06 -0400 Subject: [PATCH 10/24] More consistent test interfaces + test skipping --- tests/block_test.go | 50 +++++++++++++++++++++++++++------- tests/block_test_util.go | 27 ++++++++++-------- tests/init.go | 5 ++++ tests/state_test_util.go | 36 ++++++++++++------------ tests/transaction_test.go | 25 ++--------------- tests/transaction_test_util.go | 27 ++++++++++++------ tests/vm_test_util.go | 16 +++++------ 7 files changed, 108 insertions(+), 78 deletions(-) diff --git a/tests/block_test.go b/tests/block_test.go index f1a92be49..9d21ba28d 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -6,38 +6,68 @@ import ( ) func TestBcValidBlockTests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcValidBlockTest.json"), []string{"SimpleTx3"}) + err := RunBlockTest(filepath.Join(blockTestDir, "bcValidBlockTest.json")) + if err != nil { + t.Fatal(err) + } } func TestBcUncleTests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcUncleTest.json"), []string{}) - runBlockTestsInFile(filepath.Join(blockTestDir, "bcBruncleTest.json"), []string{}) + err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleTest.json")) + if err != nil { + t.Fatal(err) + } + err = RunBlockTest(filepath.Join(blockTestDir, "bcBruncleTest.json")) + if err != nil { + t.Fatal(err) + } } func TestBcUncleHeaderValidityTests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), []string{}) + err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json")) + if err != nil { + t.Fatal(err) + } } func TestBcInvalidHeaderTests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), []string{}) + err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json")) + if err != nil { + t.Fatal(err) + } } func TestBcInvalidRLPTests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), []string{}) + err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidRLPTest.json")) + if err != nil { + t.Fatal(err) + } } func TestBcRPCAPITests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcRPC_API_Test.json"), []string{}) + err := RunBlockTest(filepath.Join(blockTestDir, "bcRPC_API_Test.json")) + if err != nil { + t.Fatal(err) + } } func TestBcForkBlockTests(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcForkBlockTest.json"), []string{}) + err := RunBlockTest(filepath.Join(blockTestDir, "bcForkBlockTest.json")) + if err != nil { + t.Fatal(err) + } } func TestBcTotalDifficulty(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), []string{}) + err := RunBlockTest(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json")) + if err != nil { + t.Fatal(err) + } } func TestBcWallet(t *testing.T) { - runBlockTestsInFile(filepath.Join(blockTestDir, "bcWalletTest.json"), []string{}) + err := RunBlockTest(filepath.Join(blockTestDir, "bcWalletTest.json")) + if err != nil { + t.Fatal(err) + } } diff --git a/tests/block_test_util.go b/tests/block_test_util.go index ec532d178..a04019111 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -86,28 +86,35 @@ type btTransaction struct { Value string } -func runBlockTestsInFile(filepath string, snafus []string) error { +func RunBlockTest(filepath string) error { bt, err := LoadBlockTests(filepath) if err != nil { return nil } - notWorking := make(map[string]bool, 100) - for _, name := range snafus { - notWorking[name] = true + // map skipped tests to boolean set + skipTest := make(map[string]bool, len(blockSkipTests)) + for _, name := range blockSkipTests { + skipTest[name] = true } for name, test := range bt { - if !notWorking[name] { - if err := runBlockTest(name, test); err != nil { - return err - } + // if the test should be skipped, return + if skipTest[name] { + fmt.Println("Skipping state test", name) + return nil } + // test the block + if err := testBlock(test); err != nil { + return err + } + fmt.Println("Block test passed: ", name) + } return nil } -func runBlockTest(name string, test *BlockTest) error { +func testBlock(test *BlockTest) error { cfg := testEthConfig() ethereum, err := eth.New(cfg) if err != nil { @@ -136,8 +143,6 @@ func runBlockTest(name string, test *BlockTest) error { if err = test.ValidatePostState(statedb); err != nil { return fmt.Errorf("post state validation failed: %v", err) } - fmt.Println("Block test passed: ", name) - // t.Log("Block test passed: ", name) return nil } diff --git a/tests/init.go b/tests/init.go index e6644ae60..74d9499f1 100644 --- a/tests/init.go +++ b/tests/init.go @@ -15,6 +15,11 @@ var ( stateTestDir = filepath.Join(baseDir, "StateTests") transactionTestDir = filepath.Join(baseDir, "TransactionTests") vmTestDir = filepath.Join(baseDir, "VMTests") + + blockSkipTests = []string{} + transSkipTests = []string{"TransactionWithHihghNonce256"} + stateSkipTests = []string{"mload32bitBound_return", "mload32bitBound_return2"} + vmSkipTests = []string{} ) func readJSON(reader io.Reader, value interface{}) error { diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 29d7cebe8..b507de47f 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -15,19 +15,19 @@ import ( ) func RunStateTest(p string) error { + skipTest := make(map[string]bool, len(stateSkipTests)) + for _, name := range stateSkipTests { + skipTest[name] = true + } tests := make(map[string]VmTest) CreateFileTests(p, &tests) for name, test := range tests { - /* - vm.Debug = true - glog.SetV(4) - glog.SetToStderr(true) - if name != "Call50000_sha256" { - continue - } - */ + if skipTest[name] { + fmt.Println("Skipping state test", name) + return nil + } db, _ := ethdb.NewMemDatabase() statedb := state.New(common.Hash{}, db) for addr, account := range test.Pre { @@ -60,17 +60,17 @@ func RunStateTest(p string) error { ret, logs, _, _ = RunState(statedb, env, test.Transaction) - // Compare expected and actual return - switch name { - // the memory required for these tests (4294967297 bytes) would take too much time. - // on 19 May 2015 decided to skip these tests their output. - case "mload32bitBound_return", "mload32bitBound_return2": - default: - 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) - } + // // Compare expected and actual return + // switch name { + // // the memory required for these tests (4294967297 bytes) would take too much time. + // // on 19 May 2015 decided to skip these tests their output. + // case "mload32bitBound_return", "mload32bitBound_return2": + // default: + 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 { diff --git a/tests/transaction_test.go b/tests/transaction_test.go index e1237dee2..41a20a1bb 100644 --- a/tests/transaction_test.go +++ b/tests/transaction_test.go @@ -6,40 +6,21 @@ import ( ) func TestTransactions(t *testing.T) { - notWorking := make(map[string]bool, 100) - - // TODO: all these tests should work! remove them from the array when they work - snafus := []string{ - "TransactionWithHihghNonce256", // fails due to testing upper bound of 256 bit nonce - } - - for _, name := range snafus { - notWorking[name] = true - } - - var err error - err = RunTransactionTests(filepath.Join(transactionTestDir, "ttTransactionTest.json"), - notWorking) + err := RunTransactionTests(filepath.Join(transactionTestDir, "ttTransactionTest.json")) if err != nil { t.Fatal(err) } } func TestWrongRLPTransactions(t *testing.T) { - notWorking := make(map[string]bool, 100) - var err error - err = RunTransactionTests(filepath.Join(transactionTestDir, "ttWrongRLPTransaction.json"), - notWorking) + err := RunTransactionTests(filepath.Join(transactionTestDir, "ttWrongRLPTransaction.json")) if err != nil { t.Fatal(err) } } func Test10MBtx(t *testing.T) { - notWorking := make(map[string]bool, 100) - var err error - err = RunTransactionTests(filepath.Join(transactionTestDir, "tt10mbDataField.json"), - notWorking) + err := RunTransactionTests(filepath.Join(transactionTestDir, "tt10mbDataField.json")) if err != nil { t.Fatal(err) } diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index a6cea972a..65e2c7591 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -30,20 +30,29 @@ type TransactionTest struct { Transaction TtTransaction } -func RunTransactionTests(file string, notWorking map[string]bool) 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 := LoadJSON(file, &bt); err != nil { return err } - for name, in := range bt { - var err error - // TODO: remove this, we currently ignore some tests which are broken - if !notWorking[name] { - if err = runTest(in); err != nil { - return fmt.Errorf("bad test %s: %v", name, err) - } - fmt.Println("Transaction test passed:", name) + + for name, test := range bt { + // if the test should be skipped, return + if skipTest[name] { + fmt.Println("Skipping state test", name) + return nil } + // test the block + if err := runTest(test); err != nil { + return err + } + fmt.Println("Transaction test passed: ", name) + } return nil } diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 066217620..55036ed82 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -13,6 +13,10 @@ import ( ) func RunVmTest(p string) error { + skipTest := make(map[string]bool, len(vmSkipTests)) + for _, name := range vmSkipTests { + skipTest[name] = true + } tests := make(map[string]VmTest) err := CreateFileTests(p, &tests) @@ -21,14 +25,10 @@ func RunVmTest(p string) error { } for name, test := range tests { - /* - vm.Debug = true - glog.SetV(4) - glog.SetToStderr(true) - if name != "Call50000_sha256" { - continue - } - */ + if skipTest[name] { + fmt.Println("Skipping state test", name) + return nil + } db, _ := ethdb.NewMemDatabase() statedb := state.New(common.Hash{}, db) for addr, account := range test.Pre { From 6ff956394a26fe13c774797284220b8231ebf809 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 10 Jun 2015 18:11:30 -0400 Subject: [PATCH 11/24] DRY file loading --- tests/block_test_util.go | 56 ++++++++-------------------------- tests/init.go | 32 ++++++++++++++++--- tests/state_test_util.go | 8 +---- tests/transaction_test_util.go | 2 +- tests/vm_test_util.go | 2 +- 5 files changed, 42 insertions(+), 58 deletions(-) diff --git a/tests/block_test_util.go b/tests/block_test_util.go index a04019111..7db47566b 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -3,9 +3,7 @@ package tests import ( "bytes" "encoding/hex" - "encoding/json" "fmt" - "io/ioutil" "math/big" "path/filepath" "runtime" @@ -87,9 +85,9 @@ type btTransaction struct { } func RunBlockTest(filepath string) error { - bt, err := LoadBlockTests(filepath) + bt, err := loadBlockTests(filepath) if err != nil { - return nil + return err } // map skipped tests to boolean set @@ -158,22 +156,6 @@ func testEthConfig() *eth.Config { } } -// LoadBlockTests loads a block test JSON file. -func LoadBlockTests(file string) (map[string]*BlockTest, error) { - bt := make(map[string]*btJSON) - if err := LoadJSON(file, &bt); 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 -} - // InsertPreState populates the given database with the genesis // accounts defined by the test. func (t *BlockTest) InsertPreState(ethereum *eth.Ethereum) (*state.StateDB, error) { @@ -467,34 +449,20 @@ func mustConvertUint(in string, base int) uint64 { return out } -// LoadJSON reads the given file and unmarshals its content. -func LoadJSON(file string, val interface{}) error { - content, err := ioutil.ReadFile(file) - if err != nil { - return err +func loadBlockTests(file string) (map[string]*BlockTest, error) { + bt := make(map[string]*btJSON) + if err := readTestFile(file, &bt); err != nil { + return nil, err } - if err := json.Unmarshal(content, val); err != nil { - if syntaxerr, ok := err.(*json.SyntaxError); ok { - line := findLine(content, syntaxerr.Offset) - return fmt.Errorf("JSON syntax error at %v:%v: %v", file, line, err) - } - return fmt.Errorf("JSON unmarshal error in %v: %v", file, err) - } - 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++ + 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 + return out, nil } // Nothing to see here, please move along... diff --git a/tests/init.go b/tests/init.go index 74d9499f1..aec06396b 100644 --- a/tests/init.go +++ b/tests/init.go @@ -2,6 +2,7 @@ package tests import ( "encoding/json" + "fmt" "io" "io/ioutil" "net/http" @@ -24,14 +25,35 @@ var ( func readJSON(reader io.Reader, value interface{}) error { data, err := ioutil.ReadAll(reader) - err = json.Unmarshal(data, &value) if err != nil { - return err + return fmt.Errorf("Error reading JSON file", err.Error()) + } + + if err = json.Unmarshal(data, &value); err != nil { + if syntaxerr, ok := err.(*json.SyntaxError); ok { + line := findLine(data, syntaxerr.Offset) + return fmt.Errorf("JSON syntax error at line %v: %v", line, err) + } + return fmt.Errorf("JSON unmarshal error: %v", err) } return nil } -func CreateHttpTests(uri string, value interface{}) error { +// 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 { resp, err := http.Get(uri) if err != nil { return err @@ -45,7 +67,7 @@ func CreateHttpTests(uri string, value interface{}) error { return nil } -func CreateFileTests(fn string, value interface{}) error { +func readTestFile(fn string, value interface{}) error { file, err := os.Open(fn) if err != nil { return err @@ -54,7 +76,7 @@ func CreateFileTests(fn string, value interface{}) error { err = readJSON(file, value) if err != nil { - return err + return fmt.Errorf("%s in file %s", err.Error(), fn) } return nil } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index b507de47f..cd87ee75e 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -21,7 +21,7 @@ func RunStateTest(p string) error { } tests := make(map[string]VmTest) - CreateFileTests(p, &tests) + readTestFile(p, &tests) for name, test := range tests { if skipTest[name] { @@ -61,16 +61,10 @@ func RunStateTest(p string) error { ret, logs, _, _ = RunState(statedb, env, test.Transaction) // // Compare expected and actual return - // switch name { - // // the memory required for these tests (4294967297 bytes) would take too much time. - // // on 19 May 2015 decided to skip these tests their output. - // case "mload32bitBound_return", "mload32bitBound_return2": - // default: 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 { diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index 65e2c7591..2864257b7 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -37,7 +37,7 @@ func RunTransactionTests(file string) error { } bt := make(map[string]TransactionTest) - if err := LoadJSON(file, &bt); err != nil { + if err := readTestFile(file, &bt); err != nil { return err } diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 55036ed82..28e0c3f40 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -19,7 +19,7 @@ func RunVmTest(p string) error { } tests := make(map[string]VmTest) - err := CreateFileTests(p, &tests) + err := readTestFile(p, &tests) if err != nil { return err } From 6931267324a4cb00d1edf0b8e85333b744882c2d Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 10 Jun 2015 18:14:04 -0400 Subject: [PATCH 12/24] Wire ethtest to new tests structure --- cmd/ethtest/main.go | 235 ++++++-------------------------------------- 1 file changed, 32 insertions(+), 203 deletions(-) diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go index c33db45d2..d89271a0c 100644 --- a/cmd/ethtest/main.go +++ b/cmd/ethtest/main.go @@ -22,208 +22,15 @@ package main import ( - "bytes" - "encoding/json" - "io" - "io/ioutil" - "log" - "math/big" "os" - "strconv" - "strings" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" - "github.com/ethereum/go-ethereum/tests/helper" + "github.com/ethereum/go-ethereum/tests" ) -type Log struct { - AddressF string `json:"address"` - DataF string `json:"data"` - TopicsF []string `json:"topics"` - BloomF string `json:"bloom"` -} - -func (self Log) Address() []byte { return common.Hex2Bytes(self.AddressF) } -func (self Log) Data() []byte { return common.Hex2Bytes(self.DataF) } -func (self Log) RlpData() interface{} { return nil } -func (self Log) Topics() [][]byte { - t := make([][]byte, len(self.TopicsF)) - for i, topic := range self.TopicsF { - t[i] = common.Hex2Bytes(topic) - } - return t -} - -type Account struct { - Balance string - Code string - Nonce string - Storage map[string]string -} - -func StateObjectFromAccount(db common.Database, addr string, account Account) *state.StateObject { - obj := state.NewStateObject(common.HexToAddress(addr), db) - obj.SetBalance(common.Big(account.Balance)) - - if common.IsHex(account.Code) { - account.Code = account.Code[2:] - } - obj.SetCode(common.Hex2Bytes(account.Code)) - obj.SetNonce(common.Big(account.Nonce).Uint64()) - - return obj -} - -type VmTest struct { - Callcreates interface{} - Env Env - Exec map[string]string - Transaction map[string]string - Logs []Log - Gas string - Out string - Post map[string]Account - Pre map[string]Account - PostStateRoot string -} - -type Env struct { - CurrentCoinbase string - CurrentDifficulty string - CurrentGasLimit string - CurrentNumber string - CurrentTimestamp interface{} - PreviousHash string -} - -func RunVmTest(r io.Reader) (failed int) { - tests := make(map[string]VmTest) - - data, _ := ioutil.ReadAll(r) - err := json.Unmarshal(data, &tests) - if err != nil { - log.Fatalln(err) - } - - vm.Debug = true - glog.SetV(4) - glog.SetToStderr(true) - for name, test := range tests { - db, _ := ethdb.NewMemDatabase() - statedb := state.New(common.Hash{}, db) - for addr, account := range test.Pre { - obj := StateObjectFromAccount(db, addr, account) - statedb.SetStateObject(obj) - } - - 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, _, _ := helper.RunState(statedb, env, test.Transaction) - statedb.Sync() - - rexp := helper.FromHex(test.Out) - if bytes.Compare(rexp, ret) != 0 { - glog.V(logger.Info).Infof("%s's return failed. Expected %x, got %x\n", name, rexp, ret) - failed = 1 - } - - for addr, account := range test.Post { - obj := statedb.GetStateObject(common.HexToAddress(addr)) - if obj == nil { - continue - } - - if len(test.Exec) == 0 { - if obj.Balance().Cmp(common.Big(account.Balance)) != 0 { - glog.V(logger.Info).Infof("%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())) - failed = 1 - } - } - - for addr, value := range account.Storage { - v := obj.GetState(common.HexToHash(addr)).Bytes() - vexp := helper.FromHex(value) - - if bytes.Compare(v, vexp) != 0 { - glog.V(logger.Info).Infof("%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)) - failed = 1 - } - } - } - - statedb.Sync() - //if !bytes.Equal(common.Hex2Bytes(test.PostStateRoot), statedb.Root()) { - if common.HexToHash(test.PostStateRoot) != statedb.Root() { - glog.V(logger.Info).Infof("%s's : Post state root failed. Expected %s, got %x", name, test.PostStateRoot, statedb.Root()) - failed = 1 - } - - if len(test.Logs) > 0 { - if len(test.Logs) != len(logs) { - glog.V(logger.Info).Infof("log length failed. Expected %d, got %d", len(test.Logs), len(logs)) - failed = 1 - } else { - for i, log := range test.Logs { - if common.HexToAddress(log.AddressF) != logs[i].Address { - glog.V(logger.Info).Infof("'%s' log address failed. Expected %v got %x", name, log.AddressF, logs[i].Address) - failed = 1 - } - - if !bytes.Equal(logs[i].Data, helper.FromHex(log.DataF)) { - glog.V(logger.Info).Infof("'%s' log data failed. Expected %v got %x", name, log.DataF, logs[i].Data) - failed = 1 - } - - if len(log.TopicsF) != len(logs[i].Topics) { - glog.V(logger.Info).Infof("'%s' log topics length failed. Expected %d got %d", name, len(log.TopicsF), logs[i].Topics) - failed = 1 - } else { - for j, topic := range log.TopicsF { - if common.HexToHash(topic) != logs[i].Topics[j] { - glog.V(logger.Info).Infof("'%s' log topic[%d] failed. Expected %v got %x", name, j, topic, logs[i].Topics[j]) - failed = 1 - } - } - } - genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256) - - if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) { - glog.V(logger.Info).Infof("'%s' bloom failed.", name) - failed = 1 - } - } - } - } - - if failed == 1 { - glog.V(logger.Info).Infoln(string(statedb.Dump())) - } - - logger.Flush() - } - - return -} - func main() { - helper.Logger.SetLogLevel(5) - vm.Debug = true + // helper.Logger.SetLogLevel(5) + // vm.Debug = true if len(os.Args) < 2 { glog.Exit("Must specify test type") @@ -231,23 +38,45 @@ func main() { test := os.Args[1] - var code int + // var code int switch test { case "vm", "VMTests": - glog.Exit("VMTests not yet implemented") + if len(os.Args) > 2 { + if err := tests.RunVmTest(os.Args[2]); err != nil { + glog.Errorln(err) + } + } else { + glog.Exit("Must supply file argument") + } case "state", "StateTest": if len(os.Args) > 2 { - code = RunVmTest(strings.NewReader(os.Args[2])) + if err := tests.RunStateTest(os.Args[2]); err != nil { + glog.Errorln(err) + } + // code = RunVmTest(strings.NewReader(os.Args[2])) } else { - code = RunVmTest(os.Stdin) + glog.Exit("Must supply file argument") + // code = RunVmTest(os.Stdin) } case "tx", "TransactionTests": - glog.Exit("TransactionTests not yet implemented") + if len(os.Args) > 2 { + if err := tests.RunTransactionTests(os.Args[2]); err != nil { + glog.Errorln(err) + } + } else { + glog.Exit("Must supply file argument") + } case "bc", "BlockChainTest": - glog.Exit("BlockChainTest not yet implemented") + if len(os.Args) > 2 { + if err := tests.RunBlockTest(os.Args[2]); err != nil { + glog.Errorln(err) + } + } else { + glog.Exit("Must supply file argument") + } default: glog.Exit("Invalid test type specified") } - os.Exit(code) + // os.Exit(code) } From 8507c867b9cca2b1d59182baea90ab2844d494a0 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 11 Jun 2015 12:20:30 -0400 Subject: [PATCH 13/24] Fix geth blocktest command --- cmd/geth/blocktestcmd.go | 1 + tests/block_test_util.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/geth/blocktestcmd.go b/cmd/geth/blocktestcmd.go index ffea4400e..116eec2b3 100644 --- a/cmd/geth/blocktestcmd.go +++ b/cmd/geth/blocktestcmd.go @@ -86,6 +86,7 @@ func runBlockTest(ctx *cli.Context) { } func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) { + // TODO remove in favor of logic contained in tests package cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx) cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() } cfg.MaxPeers = 0 // disable network diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 7db47566b..787056b89 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -85,7 +85,7 @@ type btTransaction struct { } func RunBlockTest(filepath string) error { - bt, err := loadBlockTests(filepath) + bt, err := LoadBlockTests(filepath) if err != nil { return err } @@ -449,7 +449,7 @@ func mustConvertUint(in string, base int) uint64 { return out } -func loadBlockTests(file string) (map[string]*BlockTest, error) { +func LoadBlockTests(file string) (map[string]*BlockTest, error) { bt := make(map[string]*btJSON) if err := readTestFile(file, &bt); err != nil { return nil, err From c941a39b756783d95526a74374dd2aa4283474fa Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 11 Jun 2015 13:06:56 -0400 Subject: [PATCH 14/24] Cleanup logging --- cmd/ethtest/main.go | 3 ++- tests/block_test_util.go | 6 +++--- tests/init.go | 2 +- tests/state_test_util.go | 5 +++-- tests/transaction_test_util.go | 5 +++-- tests/vm_test_util.go | 6 +++--- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go index d89271a0c..07554c89f 100644 --- a/cmd/ethtest/main.go +++ b/cmd/ethtest/main.go @@ -29,7 +29,8 @@ import ( ) func main() { - // helper.Logger.SetLogLevel(5) + glog.SetToStderr(true) + // vm.Debug = true if len(os.Args) < 2 { diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 787056b89..21fd07db6 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -19,6 +19,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/rlp" ) @@ -99,15 +100,14 @@ func RunBlockTest(filepath string) error { for name, test := range bt { // if the test should be skipped, return if skipTest[name] { - fmt.Println("Skipping state test", name) + glog.Infoln("Skipping block test", name) return nil } // test the block if err := testBlock(test); err != nil { return err } - fmt.Println("Block test passed: ", name) - + glog.Infoln("Block test passed: ", name) } return nil } diff --git a/tests/init.go b/tests/init.go index aec06396b..164924ab8 100644 --- a/tests/init.go +++ b/tests/init.go @@ -17,7 +17,7 @@ var ( transactionTestDir = filepath.Join(baseDir, "TransactionTests") vmTestDir = filepath.Join(baseDir, "VMTests") - blockSkipTests = []string{} + blockSkipTests = []string{"SimpleTx3"} transSkipTests = []string{"TransactionWithHihghNonce256"} stateSkipTests = []string{"mload32bitBound_return", "mload32bitBound_return2"} vmSkipTests = []string{} diff --git a/tests/state_test_util.go b/tests/state_test_util.go index cd87ee75e..ad14168c7 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/logger/glog" ) func RunStateTest(p string) error { @@ -25,7 +26,7 @@ func RunStateTest(p string) error { for name, test := range tests { if skipTest[name] { - fmt.Println("Skipping state test", name) + glog.Infoln("Skipping state test", name) return nil } db, _ := ethdb.NewMemDatabase() @@ -105,7 +106,7 @@ func RunStateTest(p string) error { } } - fmt.Println("State test passed: ", name) + glog.Infoln("State test passed: ", name) //fmt.Println(string(statedb.Dump())) } return nil diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index 2864257b7..ef133a99d 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/rlp" ) @@ -44,14 +45,14 @@ func RunTransactionTests(file string) error { for name, test := range bt { // if the test should be skipped, return if skipTest[name] { - fmt.Println("Skipping state test", name) + glog.Infoln("Skipping transaction test", name) return nil } // test the block if err := runTest(test); err != nil { return err } - fmt.Println("Transaction test passed: ", name) + glog.Infoln("Transaction test passed: ", name) } return nil diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 28e0c3f40..4145d1ebf 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/logger/glog" ) func RunVmTest(p string) error { @@ -26,7 +27,7 @@ func RunVmTest(p string) error { for name, test := range tests { if skipTest[name] { - fmt.Println("Skipping state test", name) + glog.Infoln("Skipping VM test", name) return nil } db, _ := ethdb.NewMemDatabase() @@ -102,8 +103,7 @@ func RunVmTest(p string) error { } } - fmt.Println("VM test passed: ", name) - + glog.Infoln("VM test passed: ", name) //fmt.Println(string(statedb.Dump())) } return nil From 30444db02068210d41060a69b2c591107d9c94b3 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 11 Jun 2015 13:33:58 -0400 Subject: [PATCH 15/24] Add lost rebase changes --- tests/util.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/util.go b/tests/util.go index 6554c4b94..67650c188 100644 --- a/tests/util.go +++ b/tests/util.go @@ -124,7 +124,7 @@ type Env struct { difficulty *big.Int gasLimit *big.Int - logs state.Logs + logs []vm.StructLog vmTest bool } @@ -135,6 +135,14 @@ func NewEnv(state *state.StateDB) *Env { } } +func (self *Env) StructLogs() []vm.StructLog { + return self.logs +} + +func (self *Env) AddStructLog(log vm.StructLog) { + self.logs = append(self.logs, log) +} + func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env { env := NewEnv(state) From 516362bcadf7aee1ed132fecfeff1d91805abaaa Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 11 Jun 2015 15:23:49 -0400 Subject: [PATCH 16/24] Allow specifying single depth directory --- cmd/ethtest/main.go | 114 ++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 42 deletions(-) diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go index 07554c89f..844c15e32 100644 --- a/cmd/ethtest/main.go +++ b/cmd/ethtest/main.go @@ -22,62 +22,92 @@ package main import ( + "io/ioutil" "os" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/tests" ) +func getFiles(path string) ([]string, error) { + var files []string + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + fi, err := f.Stat() + if err != nil { + return nil, err + } + + switch mode := fi.Mode(); { + case mode.IsDir(): + fi, _ := ioutil.ReadDir(path) + files = make([]string, len(fi)) + for i, v := range fi { + // only go 1 depth and leave directory entires blank + if !v.IsDir() { + files[i] = path + v.Name() + } + } + case mode.IsRegular(): + files = make([]string, 1) + files[0] = path + } + + return files, nil +} + func main() { glog.SetToStderr(true) - + var continueOnError bool = false // vm.Debug = true if len(os.Args) < 2 { glog.Exit("Must specify test type") } - test := os.Args[1] - - // var code int - switch test { - case "vm", "VMTests": - if len(os.Args) > 2 { - if err := tests.RunVmTest(os.Args[2]); err != nil { - glog.Errorln(err) - } - } else { - glog.Exit("Must supply file argument") - } - case "state", "StateTest": - if len(os.Args) > 2 { - if err := tests.RunStateTest(os.Args[2]); err != nil { - glog.Errorln(err) - } - // code = RunVmTest(strings.NewReader(os.Args[2])) - } else { - glog.Exit("Must supply file argument") - // code = RunVmTest(os.Stdin) - } - case "tx", "TransactionTests": - if len(os.Args) > 2 { - if err := tests.RunTransactionTests(os.Args[2]); err != nil { - glog.Errorln(err) - } - } else { - glog.Exit("Must supply file argument") - } - case "bc", "BlockChainTest": - if len(os.Args) > 2 { - if err := tests.RunBlockTest(os.Args[2]); err != nil { - glog.Errorln(err) - } - } else { - glog.Exit("Must supply file argument") - } - default: - glog.Exit("Invalid test type specified") + testtype := os.Args[1] + var pattern string + if len(os.Args) > 2 { + pattern = os.Args[2] } - // os.Exit(code) + files, err := getFiles(pattern) + if err != nil { + glog.Fatal(err) + } + + for _, testfile := range files { + // Skip blank entries + if len(testfile) == 0 { + continue + } + // TODO allow io.Reader to be passed so Stdin can be piped + // RunVmTest(strings.NewReader(os.Args[2])) + // RunVmTest(os.Stdin) + var err error + switch testtype { + case "vm", "VMTests": + err = tests.RunVmTest(testfile) + case "state", "StateTest": + err = tests.RunStateTest(testfile) + case "tx", "TransactionTests": + err = tests.RunTransactionTests(testfile) + case "bc", "BlockChainTest": + err = tests.RunBlockTest(testfile) + default: + glog.Fatalln("Invalid test type specified") + } + + if err != nil { + if continueOnError { + glog.Errorln(err) + } else { + glog.Fatalln(err) + } + } + } } From 49336675f3aeff478022ca6dc56ad39dca25ff47 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 11 Jun 2015 23:08:44 -0400 Subject: [PATCH 17/24] Expand CLI options to allow running all tests --- cmd/ethtest/main.go | 154 +++++++++++++++++++++++++++++++------------- 1 file changed, 111 insertions(+), 43 deletions(-) diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go index 844c15e32..7103a074a 100644 --- a/cmd/ethtest/main.go +++ b/cmd/ethtest/main.go @@ -22,14 +22,60 @@ package main import ( + "fmt" "io/ioutil" "os" + "path/filepath" + "github.com/codegangsta/cli" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/tests" ) +var ( + continueOnError = false + testExtension = ".json" + defaultTest = "all" + defaultDir = "." + allTests = []string{"BlockTests", "StateTests", "TransactionTests", "VMTests"} + + TestFlag = cli.StringFlag{ + Name: "test", + Usage: "Test type (string): VMTests, TransactionTests, StateTests, BlockTests", + Value: defaultTest, + } + FileFlag = cli.StringFlag{ + Name: "file", + Usage: "Test file or directory. Directories are searched for .json files 1 level deep", + Value: defaultDir, + EnvVar: "ETHEREUM_TEST_PATH", + } + ContinueOnErrorFlag = cli.BoolFlag{ + Name: "continue", + Usage: "Continue running tests on error (true) or exit immediately (false)", + } +) + +func runTest(test, file string) error { + // glog.Infoln("runTest", test, file) + var err error + switch test { + case "bc", "BlockTest", "BlockTests", "BlockChainTest": + err = tests.RunBlockTest(file) + case "st", "state", "StateTest", "StateTests": + err = tests.RunStateTest(file) + case "tx", "TransactionTest", "TransactionTests": + err = tests.RunTransactionTests(file) + case "vm", "VMTest", "VMTests": + err = tests.RunVmTest(file) + default: + err = fmt.Errorf("Invalid test type specified:", test) + } + return err +} + func getFiles(path string) ([]string, error) { + // glog.Infoln("getFiles ", path) var files []string f, err := os.Open(path) if err != nil { @@ -48,8 +94,9 @@ func getFiles(path string) ([]string, error) { files = make([]string, len(fi)) for i, v := range fi { // only go 1 depth and leave directory entires blank - if !v.IsDir() { - files[i] = path + v.Name() + if !v.IsDir() && v.Name()[len(v.Name())-len(testExtension):len(v.Name())] == testExtension { + files[i] = filepath.Join(path, v.Name()) + // glog.Infoln(files[i]) } } case mode.IsRegular(): @@ -60,54 +107,75 @@ func getFiles(path string) ([]string, error) { return files, nil } -func main() { - glog.SetToStderr(true) - var continueOnError bool = false - // vm.Debug = true +func runSuite(c *cli.Context) { + flagTest := c.GlobalString(TestFlag.Name) + flagFile := c.GlobalString(FileFlag.Name) + continueOnError = c.GlobalBool(ContinueOnErrorFlag.Name) - if len(os.Args) < 2 { - glog.Exit("Must specify test type") + var tests []string + + if flagTest == defaultTest { + tests = allTests + } else { + tests = []string{flagTest} } - testtype := os.Args[1] - var pattern string - if len(os.Args) > 2 { - pattern = os.Args[2] - } - - files, err := getFiles(pattern) - if err != nil { - glog.Fatal(err) - } - - for _, testfile := range files { - // Skip blank entries - if len(testfile) == 0 { - continue - } - // TODO allow io.Reader to be passed so Stdin can be piped - // RunVmTest(strings.NewReader(os.Args[2])) - // RunVmTest(os.Stdin) + for _, curTest := range tests { + // glog.Infoln("runSuite", curTest, flagFile) var err error - switch testtype { - case "vm", "VMTests": - err = tests.RunVmTest(testfile) - case "state", "StateTest": - err = tests.RunStateTest(testfile) - case "tx", "TransactionTests": - err = tests.RunTransactionTests(testfile) - case "bc", "BlockChainTest": - err = tests.RunBlockTest(testfile) - default: - glog.Fatalln("Invalid test type specified") + var files []string + if flagTest == defaultTest { + files, err = getFiles(filepath.Join(flagFile, curTest)) + + } else { + files, err = getFiles(flagFile) + } + if err != nil { + glog.Fatalln(err) } - if err != nil { - if continueOnError { - glog.Errorln(err) - } else { - glog.Fatalln(err) + if len(files) == 0 { + glog.Warningln("No files matched path") + } + for _, testfile := range files { + // Skip blank entries + if len(testfile) == 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) + if err != nil { + if continueOnError { + glog.Errorln(err) + } else { + glog.Fatalln(err) + } + } + } } } + +func main() { + glog.SetToStderr(true) + + // vm.Debug = true + + app := cli.NewApp() + app.Name = "ethtest" + app.Usage = "go-ethereum test interface" + app.Action = runSuite + app.Flags = []cli.Flag{ + TestFlag, + FileFlag, + ContinueOnErrorFlag, + } + + if err := app.Run(os.Args); err != nil { + glog.Fatalln(err) + } + +} From a86452d22c2206fd05cfa72b547e7014a0859c7c Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Fri, 12 Jun 2015 09:13:39 -0400 Subject: [PATCH 18/24] Minor cleanup --- cmd/ethtest/main.go | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go index 7103a074a..a78111797 100644 --- a/cmd/ethtest/main.go +++ b/cmd/ethtest/main.go @@ -17,6 +17,7 @@ /** * @authors: * Jeffrey Wilcke + * Taylor Gerring */ package main @@ -52,7 +53,7 @@ var ( } ContinueOnErrorFlag = cli.BoolFlag{ Name: "continue", - Usage: "Continue running tests on error (true) or exit immediately (false)", + Usage: "Continue running tests on error (true) or [default] exit immediately (false)", } ) @@ -75,7 +76,7 @@ func runTest(test, file string) error { } 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 { @@ -96,7 +97,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(files[i]) + // glog.Infoln("Found file", files[i]) } } case mode.IsRegular(): @@ -107,28 +108,24 @@ func getFiles(path string) ([]string, error) { return files, nil } -func runSuite(c *cli.Context) { - flagTest := c.GlobalString(TestFlag.Name) - flagFile := c.GlobalString(FileFlag.Name) - continueOnError = c.GlobalBool(ContinueOnErrorFlag.Name) - +func runSuite(test, file string) { var tests []string - if flagTest == defaultTest { + if test == defaultTest { tests = allTests } else { - tests = []string{flagTest} + tests = []string{test} } for _, curTest := range tests { - // glog.Infoln("runSuite", curTest, flagFile) + // glog.Infoln("runSuite", curTest, file) var err error var files []string - if flagTest == defaultTest { - files, err = getFiles(filepath.Join(flagFile, curTest)) + if test == defaultTest { + files, err = getFiles(filepath.Join(file, curTest)) } else { - files, err = getFiles(flagFile) + files, err = getFiles(file) } if err != nil { glog.Fatalln(err) @@ -159,15 +156,24 @@ func runSuite(c *cli.Context) { } } +func setupApp(c *cli.Context) { + flagTest := c.GlobalString(TestFlag.Name) + flagFile := c.GlobalString(FileFlag.Name) + continueOnError = c.GlobalBool(ContinueOnErrorFlag.Name) + + runSuite(flagTest, flagFile) +} + func main() { glog.SetToStderr(true) - // vm.Debug = true - app := cli.NewApp() app.Name = "ethtest" app.Usage = "go-ethereum test interface" - app.Action = runSuite + app.Action = setupApp + app.Version = "0.2.0" + app.Author = "go-ethereum team" + app.Flags = []cli.Flag{ TestFlag, FileFlag, From 01ec4dbb1251751b8bbf62ddb3b3a02dc50d29fc Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Sun, 14 Jun 2015 17:55:03 -0400 Subject: [PATCH 19/24] Add stdin option --- cmd/ethtest/main.go | 60 +++++++---- tests/block_test_util.go | 80 ++++++++++---- tests/init.go | 95 ++++++++++------ tests/state_test_util.go | 192 +++++++++++++++++++-------------- tests/transaction_test_util.go | 41 +++++-- tests/vm_test_util.go | 191 +++++++++++++++++++------------- 6 files changed, 422 insertions(+), 237 deletions(-) diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go index a78111797..93bf3ce65 100644 --- a/cmd/ethtest/main.go +++ b/cmd/ethtest/main.go @@ -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 { 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,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 -} 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,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) { 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,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) 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,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"]) From baea8e87e5dfdcfb7b2fdcef48fa6038d60a6f9c Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 18 Jun 2015 22:27:44 +0200 Subject: [PATCH 20/24] Rebase cleanup --- tests/init.go | 29 ----------------------------- tests/vm_test_util.go | 2 +- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/tests/init.go b/tests/init.go index 326387341..9fe98a0d1 100644 --- a/tests/init.go +++ b/tests/init.go @@ -8,8 +8,6 @@ import ( "net/http" "os" "path/filepath" - - // "github.com/ethereum/go-ethereum/logger/glog" ) var ( @@ -25,33 +23,6 @@ var ( VmSkipTests = []string{} ) -// 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 { diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index f7f1198ec..9fccafd8e 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -130,7 +130,7 @@ func runVmTest(test VmTest) error { 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)) + 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()) } } } From 8d3faf69d00420b80d4d737e618b2c7791c10ae9 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 18 Jun 2015 22:38:17 +0200 Subject: [PATCH 21/24] Build error fixes --- build/test-global-coverage.sh | 2 +- tests/state_test_util.go | 9 ++++----- tests/vm_test_util.go | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/build/test-global-coverage.sh b/build/test-global-coverage.sh index 417c829f4..5bb233a31 100755 --- a/build/test-global-coverage.sh +++ b/build/test-global-coverage.sh @@ -16,7 +16,7 @@ for pkg in $(go list ./...); do # drop the namespace prefix. dir=${pkg##github.com/ethereum/go-ethereum/} - if [[ $dir != "tests/vm" ]]; then + if [[ $dir != "tests" ]]; then go test -covermode=count -coverprofile=$dir/profile.tmp $pkg fi if [[ -f $dir/profile.tmp ]]; then diff --git a/tests/state_test_util.go b/tests/state_test_util.go index ad3aeea6c..835ba44f4 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -121,17 +121,16 @@ func runStateTest(test VmTest) error { } for addr, value := range account.Storage { - v := obj.GetState(common.HexToHash(addr)).Bytes() - vexp := common.FromHex(value) + v := obj.GetState(common.HexToHash(addr)) + vexp := common.HexToHash(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)) + 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.Big(), v.Big()) } } } 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()) } diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 9fccafd8e..afeedda2a 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -102,7 +102,7 @@ func runVmTest(test VmTest) error { ret, logs, gas, err = RunVm(statedb, env, test.Exec) - // Compare expectedand actual return + // 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) From a9659e6dcf1f1584e155825d4422eb005ff38c21 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 18 Jun 2015 23:46:42 +0200 Subject: [PATCH 22/24] recover test logic --- tests/state_test_util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 835ba44f4..577935dfa 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -172,7 +172,7 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state. vmenv := NewEnvFromMap(statedb, env, tx) vmenv.origin = common.BytesToAddress(keyPair.Address()) ret, _, err := core.ApplyMessage(vmenv, message, coinbase) - if core.IsNonceErr(err) || core.IsInvalidTxErr(err) { + if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || state.IsGasLimitErr(err) { statedb.Set(snapshot) } statedb.Update() From 0743243dce05c38c1f4949e44467d20a22a1f743 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Fri, 19 Jun 2015 11:38:23 +0200 Subject: [PATCH 23/24] Add --skip option to CLI Disassociates hardcoded tests to skip when running via CLI. Tests still skipped when running `go test` --- cmd/ethtest/main.go | 16 ++++++++++++---- tests/block_test.go | 20 ++++++++++---------- tests/block_test_util.go | 14 +++++++------- tests/state_test.go | 34 +++++++++++++++++----------------- tests/state_test_util.go | 14 +++++++------- tests/transaction_test.go | 6 +++--- tests/transaction_test_util.go | 31 +++++++++++++++++++------------ tests/vm_test.go | 28 ++++++++++++++-------------- tests/vm_test_util.go | 14 +++++++------- 9 files changed, 96 insertions(+), 81 deletions(-) diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go index 93bf3ce65..c6073ce98 100644 --- a/cmd/ethtest/main.go +++ b/cmd/ethtest/main.go @@ -28,6 +28,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "github.com/codegangsta/cli" "github.com/ethereum/go-ethereum/logger/glog" @@ -40,6 +41,7 @@ var ( defaultTest = "all" defaultDir = "." allTests = []string{"BlockTests", "StateTests", "TransactionTests", "VMTests"} + skipTests = []string{} TestFlag = cli.StringFlag{ Name: "test", @@ -60,6 +62,10 @@ var ( Name: "stdin", Usage: "Accept input from stdin instead of reading from file", } + SkipTestsFlag = cli.StringFlag{ + Name: "skip", + Usage: "Tests names to skip", + } ) func runTestWithReader(test string, r io.Reader) error { @@ -67,13 +73,13 @@ func runTestWithReader(test string, r io.Reader) error { var err error switch test { case "bt", "BlockTest", "BlockTests", "BlockChainTest": - err = tests.RunBlockTestWithReader(r) + err = tests.RunBlockTestWithReader(r, skipTests) case "st", "state", "StateTest", "StateTests": - err = tests.RunStateTestWithReader(r) + err = tests.RunStateTestWithReader(r, skipTests) case "tx", "TransactionTest", "TransactionTests": - err = tests.RunTransactionTestsWithReader(r) + err = tests.RunTransactionTestsWithReader(r, skipTests) case "vm", "VMTest", "VMTests": - err = tests.RunVmTestWithReader(r) + err = tests.RunVmTestWithReader(r, skipTests) default: err = fmt.Errorf("Invalid test type specified: %v", test) } @@ -174,6 +180,7 @@ func setupApp(c *cli.Context) { flagFile := c.GlobalString(FileFlag.Name) continueOnError = c.GlobalBool(ContinueOnErrorFlag.Name) useStdIn := c.GlobalBool(ReadStdInFlag.Name) + skipTests = strings.Split(c.GlobalString(SkipTestsFlag.Name), " ") if !useStdIn { runSuite(flagTest, flagFile) @@ -200,6 +207,7 @@ func main() { FileFlag, ContinueOnErrorFlag, ReadStdInFlag, + SkipTestsFlag, } if err := app.Run(os.Args); err != nil { diff --git a/tests/block_test.go b/tests/block_test.go index 9d21ba28d..bdf983786 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -6,67 +6,67 @@ import ( ) func TestBcValidBlockTests(t *testing.T) { - err := RunBlockTest(filepath.Join(blockTestDir, "bcValidBlockTest.json")) + err := RunBlockTest(filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests) if err != nil { t.Fatal(err) } } func TestBcUncleTests(t *testing.T) { - err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleTest.json")) + err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests) if err != nil { t.Fatal(err) } - err = RunBlockTest(filepath.Join(blockTestDir, "bcBruncleTest.json")) + err = RunBlockTest(filepath.Join(blockTestDir, "bcBruncleTest.json"), BlockSkipTests) if err != nil { t.Fatal(err) } } func TestBcUncleHeaderValidityTests(t *testing.T) { - err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json")) + err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests) if err != nil { t.Fatal(err) } } func TestBcInvalidHeaderTests(t *testing.T) { - err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json")) + err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests) if err != nil { t.Fatal(err) } } func TestBcInvalidRLPTests(t *testing.T) { - err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidRLPTest.json")) + err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests) if err != nil { t.Fatal(err) } } func TestBcRPCAPITests(t *testing.T) { - err := RunBlockTest(filepath.Join(blockTestDir, "bcRPC_API_Test.json")) + err := RunBlockTest(filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests) if err != nil { t.Fatal(err) } } func TestBcForkBlockTests(t *testing.T) { - err := RunBlockTest(filepath.Join(blockTestDir, "bcForkBlockTest.json")) + err := RunBlockTest(filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests) if err != nil { t.Fatal(err) } } func TestBcTotalDifficulty(t *testing.T) { - err := RunBlockTest(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json")) + err := RunBlockTest(filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests) if err != nil { t.Fatal(err) } } func TestBcWallet(t *testing.T) { - err := RunBlockTest(filepath.Join(blockTestDir, "bcWalletTest.json")) + err := RunBlockTest(filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests) if err != nil { t.Fatal(err) } diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 5222b214b..5fdc6402e 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -86,7 +86,7 @@ type btTransaction struct { Value string } -func RunBlockTestWithReader(r io.Reader) error { +func RunBlockTestWithReader(r io.Reader, skipTests []string) error { btjs := make(map[string]*btJSON) if err := readJson(r, &btjs); err != nil { return err @@ -97,13 +97,13 @@ func RunBlockTestWithReader(r io.Reader) error { return err } - if err := runBlockTests(bt); err != nil { + if err := runBlockTests(bt, skipTests); err != nil { return err } return nil } -func RunBlockTest(file string) error { +func RunBlockTest(file string, skipTests []string) error { btjs := make(map[string]*btJSON) if err := readJsonFile(file, &btjs); err != nil { return err @@ -113,15 +113,15 @@ func RunBlockTest(file string) error { if err != nil { return err } - if err := runBlockTests(bt); err != nil { + if err := runBlockTests(bt, skipTests); err != nil { return err } return nil } -func runBlockTests(bt map[string]*BlockTest) error { - skipTest := make(map[string]bool, len(BlockSkipTests)) - for _, name := range BlockSkipTests { +func runBlockTests(bt map[string]*BlockTest, skipTests []string) error { + skipTest := make(map[string]bool, len(skipTests)) + for _, name := range skipTests { skipTest[name] = true } diff --git a/tests/state_test.go b/tests/state_test.go index 9c3d6f209..e58f588f4 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -8,84 +8,84 @@ import ( func TestStateSystemOperations(t *testing.T) { fn := filepath.Join(stateTestDir, "stSystemOperationsTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestStateExample(t *testing.T) { fn := filepath.Join(stateTestDir, "stExample.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestStatePreCompiledContracts(t *testing.T) { fn := filepath.Join(stateTestDir, "stPreCompiledContracts.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestStateRecursiveCreate(t *testing.T) { fn := filepath.Join(stateTestDir, "stRecursiveCreate.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestStateSpecial(t *testing.T) { fn := filepath.Join(stateTestDir, "stSpecialTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestStateRefund(t *testing.T) { fn := filepath.Join(stateTestDir, "stRefundTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestStateBlockHash(t *testing.T) { fn := filepath.Join(stateTestDir, "stBlockHashTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestStateInitCode(t *testing.T) { fn := filepath.Join(stateTestDir, "stInitCodeTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestStateLog(t *testing.T) { fn := filepath.Join(stateTestDir, "stLogTests.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestStateTransaction(t *testing.T) { fn := filepath.Join(stateTestDir, "stTransactionTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestCallCreateCallCode(t *testing.T) { fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestMemory(t *testing.T) { fn := filepath.Join(stateTestDir, "stMemoryTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } @@ -95,7 +95,7 @@ func TestMemoryStress(t *testing.T) { t.Skip() } fn := filepath.Join(stateTestDir, "stMemoryStressTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } @@ -105,21 +105,21 @@ func TestQuadraticComplexity(t *testing.T) { t.Skip() } fn := filepath.Join(stateTestDir, "stQuadraticComplexityTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestSolidity(t *testing.T) { fn := filepath.Join(stateTestDir, "stSolidityTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } func TestWallet(t *testing.T) { fn := filepath.Join(stateTestDir, "stWalletTest.json") - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } @@ -127,7 +127,7 @@ func TestWallet(t *testing.T) { func TestStateTestsRandom(t *testing.T) { fns, _ := filepath.Glob("./files/StateTests/RandomTests/*") for _, fn := range fns { - if err := RunStateTest(fn); err != nil { + if err := RunStateTest(fn, StateSkipTests); err != nil { t.Error(err) } } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 577935dfa..e9abad788 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -16,26 +16,26 @@ import ( "github.com/ethereum/go-ethereum/logger/glog" ) -func RunStateTestWithReader(r io.Reader) error { +func RunStateTestWithReader(r io.Reader, skipTests []string) error { tests := make(map[string]VmTest) if err := readJson(r, &tests); err != nil { return err } - if err := runStateTests(tests); err != nil { + if err := runStateTests(tests, skipTests); err != nil { return err } return nil } -func RunStateTest(p string) error { +func RunStateTest(p string, skipTests []string) error { tests := make(map[string]VmTest) if err := readJsonFile(p, &tests); err != nil { return err } - if err := runStateTests(tests); err != nil { + if err := runStateTests(tests, skipTests); err != nil { return err } @@ -43,9 +43,9 @@ func RunStateTest(p string) error { } -func runStateTests(tests map[string]VmTest) error { - skipTest := make(map[string]bool, len(StateSkipTests)) - for _, name := range StateSkipTests { +func runStateTests(tests map[string]VmTest, skipTests []string) error { + skipTest := make(map[string]bool, len(skipTests)) + for _, name := range skipTests { skipTest[name] = true } diff --git a/tests/transaction_test.go b/tests/transaction_test.go index 41a20a1bb..70aa65cdd 100644 --- a/tests/transaction_test.go +++ b/tests/transaction_test.go @@ -6,21 +6,21 @@ import ( ) func TestTransactions(t *testing.T) { - err := RunTransactionTests(filepath.Join(transactionTestDir, "ttTransactionTest.json")) + err := RunTransactionTests(filepath.Join(transactionTestDir, "ttTransactionTest.json"), TransSkipTests) if err != nil { t.Fatal(err) } } func TestWrongRLPTransactions(t *testing.T) { - err := RunTransactionTests(filepath.Join(transactionTestDir, "ttWrongRLPTransaction.json")) + err := RunTransactionTests(filepath.Join(transactionTestDir, "ttWrongRLPTransaction.json"), TransSkipTests) if err != nil { t.Fatal(err) } } func Test10MBtx(t *testing.T) { - err := RunTransactionTests(filepath.Join(transactionTestDir, "tt10mbDataField.json")) + err := RunTransactionTests(filepath.Join(transactionTestDir, "tt10mbDataField.json"), TransSkipTests) if err != nil { t.Fatal(err) } diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index af33f2c58..45caf26fd 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -32,9 +32,9 @@ type TransactionTest struct { Transaction TtTransaction } -func RunTransactionTestsWithReader(r io.Reader) error { - skipTest := make(map[string]bool, len(TransSkipTests)) - for _, name := range TransSkipTests { +func RunTransactionTestsWithReader(r io.Reader, skipTests []string) error { + skipTest := make(map[string]bool, len(skipTests)) + for _, name := range skipTests { skipTest[name] = true } @@ -59,18 +59,25 @@ func RunTransactionTestsWithReader(r io.Reader) error { return nil } -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 { +func RunTransactionTests(file string, skipTests []string) error { + tests := make(map[string]TransactionTest) + if err := readJsonFile(file, &tests); err != nil { return err } - for name, test := range bt { + if err := runTransactionTests(tests, skipTests); err != nil { + return err + } + return nil +} + +func runTransactionTests(tests map[string]TransactionTest, skipTests []string) error { + skipTest := make(map[string]bool, len(skipTests)) + for _, name := range skipTests { + skipTest[name] = true + } + + for name, test := range tests { // if the test should be skipped, return if skipTest[name] { glog.Infoln("Skipping transaction test", name) diff --git a/tests/vm_test.go b/tests/vm_test.go index d16d65aac..4e417da5a 100644 --- a/tests/vm_test.go +++ b/tests/vm_test.go @@ -8,91 +8,91 @@ import ( // I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail. func TestVMArithmetic(t *testing.T) { fn := filepath.Join(vmTestDir, "vmArithmeticTest.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestBitwiseLogicOperation(t *testing.T) { fn := filepath.Join(vmTestDir, "vmBitwiseLogicOperationTest.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestBlockInfo(t *testing.T) { fn := filepath.Join(vmTestDir, "vmBlockInfoTest.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestEnvironmentalInfo(t *testing.T) { fn := filepath.Join(vmTestDir, "vmEnvironmentalInfoTest.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestFlowOperation(t *testing.T) { fn := filepath.Join(vmTestDir, "vmIOandFlowOperationsTest.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestLogTest(t *testing.T) { fn := filepath.Join(vmTestDir, "vmLogTest.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestPerformance(t *testing.T) { fn := filepath.Join(vmTestDir, "vmPerformanceTest.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestPushDupSwap(t *testing.T) { fn := filepath.Join(vmTestDir, "vmPushDupSwapTest.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestVMSha3(t *testing.T) { fn := filepath.Join(vmTestDir, "vmSha3Test.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestVm(t *testing.T) { fn := filepath.Join(vmTestDir, "vmtests.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestVmLog(t *testing.T) { fn := filepath.Join(vmTestDir, "vmLogTest.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestInputLimits(t *testing.T) { fn := filepath.Join(vmTestDir, "vmInputLimits.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } func TestInputLimitsLight(t *testing.T) { fn := filepath.Join(vmTestDir, "vmInputLimitsLight.json") - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } @@ -100,7 +100,7 @@ func TestInputLimitsLight(t *testing.T) { func TestVMRandom(t *testing.T) { fns, _ := filepath.Glob(filepath.Join(baseDir, "RandomTests", "*")) for _, fn := range fns { - if err := RunVmTest(fn); err != nil { + if err := RunVmTest(fn, VmSkipTests); err != nil { t.Error(err) } } diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index afeedda2a..286991764 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -14,7 +14,7 @@ import ( "github.com/ethereum/go-ethereum/logger/glog" ) -func RunVmTestWithReader(r io.Reader) error { +func RunVmTestWithReader(r io.Reader, skipTests []string) error { tests := make(map[string]VmTest) err := readJson(r, &tests) if err != nil { @@ -25,14 +25,14 @@ func RunVmTestWithReader(r io.Reader) error { return err } - if err := runVmTests(tests); err != nil { + if err := runVmTests(tests, skipTests); err != nil { return err } return nil } -func RunVmTest(p string) error { +func RunVmTest(p string, skipTests []string) error { tests := make(map[string]VmTest) err := readJsonFile(p, &tests) @@ -40,16 +40,16 @@ func RunVmTest(p string) error { return err } - if err := runVmTests(tests); err != nil { + if err := runVmTests(tests, skipTests); err != nil { return err } return nil } -func runVmTests(tests map[string]VmTest) error { - skipTest := make(map[string]bool, len(VmSkipTests)) - for _, name := range VmSkipTests { +func runVmTests(tests map[string]VmTest, skipTests []string) error { + skipTest := make(map[string]bool, len(skipTests)) + for _, name := range skipTests { skipTest[name] = true } From d1e589289c56140144241a245e1756dbdc7280a0 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Fri, 19 Jun 2015 15:08:53 +0200 Subject: [PATCH 24/24] Expand --test switch --- cmd/ethtest/main.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go index c6073ce98..278d2133f 100644 --- a/cmd/ethtest/main.go +++ b/cmd/ethtest/main.go @@ -71,14 +71,14 @@ var ( func runTestWithReader(test string, r io.Reader) error { glog.Infoln("runTest", test) var err error - switch test { - case "bt", "BlockTest", "BlockTests", "BlockChainTest": + switch strings.ToLower(test) { + case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests": err = tests.RunBlockTestWithReader(r, skipTests) - case "st", "state", "StateTest", "StateTests": + case "st", "state", "statetest", "statetests": err = tests.RunStateTestWithReader(r, skipTests) - case "tx", "TransactionTest", "TransactionTests": + case "tx", "transactiontest", "transactiontests": err = tests.RunTransactionTestsWithReader(r, skipTests) - case "vm", "VMTest", "VMTests": + case "vm", "vmtest", "vmtests": err = tests.RunVmTestWithReader(r, skipTests) default: err = fmt.Errorf("Invalid test type specified: %v", test)