From 1208ac83d5a93214f23bf3f9236e29869ee62407 Mon Sep 17 00:00:00 2001 From: zelig Date: Sun, 5 Jul 2015 19:19:42 +0100 Subject: [PATCH] fix natspec test * registar url string retrieval chop leading zeros now * rewrite test using test mining * remove temporary applyTxs from xeth --- cmd/geth/js_test.go | 2 +- common/docserver/docserver.go | 11 +-- common/docserver/docserver_test.go | 2 +- common/natspec/natspec_e2e_test.go | 122 +++++++++++++++++++++-------- common/registrar/registrar.go | 15 +--- xeth/xeth.go | 28 ------- 6 files changed, 99 insertions(+), 81 deletions(-) diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go index 791218997a..eaab3acaa3 100644 --- a/cmd/geth/js_test.go +++ b/cmd/geth/js_test.go @@ -254,7 +254,7 @@ func TestSignature(t *testing.T) { } func TestContract(t *testing.T) { - // t.Skip("contract testing is implemented with mining in ethash test mode. This takes about 7seconds to run. Unskip and run on demand") + t.Skip("contract testing is implemented with mining in ethash test mode. This takes about 7seconds to run. Unskip and run on demand") coinbase := common.HexToAddress(testAddress) tmp, repl, ethereum := testREPL(t, func(conf *eth.Config) { conf.Etherbase = testAddress diff --git a/common/docserver/docserver.go b/common/docserver/docserver.go index c890cd3f56..6b0cd31308 100644 --- a/common/docserver/docserver.go +++ b/common/docserver/docserver.go @@ -22,6 +22,7 @@ func New(docRoot string) (self *DocServer) { DocRoot: docRoot, schemes: []string{"file"}, } + self.DocRoot = "/tmp/" self.RegisterProtocol("file", http.NewFileTransport(http.Dir(self.DocRoot))) return } @@ -52,20 +53,16 @@ func (self *DocServer) HasScheme(scheme string) bool { func (self *DocServer) GetAuthContent(uri string, hash common.Hash) (content []byte, err error) { // retrieve content - url := uri - fmt.Printf("uri: %v\n", url) - content, err = self.Get(url, "") + content, err = self.Get(uri, "") if err != nil { return } // check hash to authenticate content - hashbytes := crypto.Sha3(content) - var chash common.Hash - copy(chash[:], hashbytes) + chash := crypto.Sha3Hash(content) if chash != hash { content = nil - err = fmt.Errorf("content hash mismatch") + err = fmt.Errorf("content hash mismatch %x != %x (exp)", hash[:], chash[:]) } return diff --git a/common/docserver/docserver_test.go b/common/docserver/docserver_test.go index 09b16864a7..ca126071c7 100644 --- a/common/docserver/docserver_test.go +++ b/common/docserver/docserver_test.go @@ -27,7 +27,7 @@ func TestGetAuthContent(t *testing.T) { hash = common.Hash{} content, err = ds.GetAuthContent("file:///test.content", hash) - expected := "content hash mismatch" + expected := "content hash mismatch 0000000000000000000000000000000000000000000000000000000000000000 != 9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658 (exp)" if err == nil { t.Errorf("expected error, got nothing") } else { diff --git a/common/natspec/natspec_e2e_test.go b/common/natspec/natspec_e2e_test.go index a941acbba1..c66304e315 100644 --- a/common/natspec/natspec_e2e_test.go +++ b/common/natspec/natspec_e2e_test.go @@ -3,16 +3,18 @@ package natspec import ( "fmt" "io/ioutil" + "math/big" "os" + "runtime" "strings" "testing" + "time" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/docserver" "github.com/ethereum/go-ethereum/common/registrar" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth" xe "github.com/ethereum/go-ethereum/xeth" @@ -76,9 +78,7 @@ type testFrontend struct { t *testing.T ethereum *eth.Ethereum xeth *xe.XEth - coinbase common.Address - stateDb *state.StateDB - txc uint64 + wait chan *big.Int lastConfirm string wantNatSpec bool } @@ -124,6 +124,8 @@ func testEth(t *testing.T) (ethereum *eth.Ethereum, err error) { DataDir: "/tmp/eth-natspec", AccountManager: am, MaxPeers: 0, + PowTest: true, + Etherbase: testAddress, }) if err != nil { @@ -149,13 +151,16 @@ func testInit(t *testing.T) (self *testFrontend) { // mock frontend self = &testFrontend{t: t, ethereum: ethereum} self.xeth = xe.New(ethereum, self) - - addr, _ := ethereum.Etherbase() - self.coinbase = addr - self.stateDb = self.ethereum.ChainManager().State().Copy() + self.wait = self.xeth.UpdateState() + addr, _ := self.ethereum.Etherbase() // initialise the registry contracts reg := registrar.New(self.xeth) + err = reg.SetGlobalRegistrar("", addr) + if err != nil { + t.Errorf("error creating GlobalRegistrar: %v", err) + } + err = reg.SetHashReg("", addr) if err != nil { t.Errorf("error creating HashReg: %v", err) @@ -164,84 +169,75 @@ func testInit(t *testing.T) (self *testFrontend) { if err != nil { t.Errorf("error creating UrlHint: %v", err) } - self.applyTxs() + if !processTxs(self, t, 7) { + t.Errorf("error mining txs") + } return } -// this is needed for transaction to be applied to the state in testing -// the heavy lifing is done in XEth.ApplyTestTxs -// this is fragile, -// and does process leaking since xeth loops cannot quit safely -// should be replaced by proper mining with testDAG for easy full integration tests -func (self *testFrontend) applyTxs() { - self.txc, self.xeth = self.xeth.ApplyTestTxs(self.stateDb, self.coinbase, self.txc) - return -} - // end to end test func TestNatspecE2E(t *testing.T) { - t.Skip() - tf := testInit(t) defer tf.ethereum.Stop() + addr, _ := tf.ethereum.Etherbase() // create a contractInfo file (mock cloud-deployed contract metadocs) // incidentally this is the info for the registry contract itself ioutil.WriteFile("/tmp/"+testFileName, []byte(testContractInfo), os.ModePerm) - dochash := common.BytesToHash(crypto.Sha3([]byte(testContractInfo))) + dochash := crypto.Sha3Hash([]byte(testContractInfo)) // take the codehash for the contract we wanna test - // codehex := tf.xeth.CodeAt(registar.HashRegAddr) codeb := tf.xeth.CodeAtBytes(registrar.HashRegAddr) - codehash := common.BytesToHash(crypto.Sha3(codeb)) + codehash := crypto.Sha3Hash(codeb) // use resolver to register codehash->dochash->url // test if globalregistry works // registrar.HashRefAddr = "0x0" // registrar.UrlHintAddr = "0x0" reg := registrar.New(tf.xeth) - _, err := reg.SetHashToHash(tf.coinbase, codehash, dochash) + _, err := reg.SetHashToHash(addr, codehash, dochash) if err != nil { t.Errorf("error registering: %v", err) } - _, err = reg.SetUrlToHash(tf.coinbase, dochash, "file:///"+testFileName) + _, err = reg.SetUrlToHash(addr, dochash, "file:///"+testFileName) if err != nil { t.Errorf("error registering: %v", err) } - // apply txs to the state - tf.applyTxs() + if !processTxs(tf, t, 5) { + return + } // NatSpec info for register method of HashReg contract installed // now using the same transactions to check confirm messages tf.wantNatSpec = true // this is set so now the backend uses natspec confirmation - _, err = reg.SetHashToHash(tf.coinbase, codehash, dochash) + _, err = reg.SetHashToHash(addr, codehash, dochash) if err != nil { t.Errorf("error calling contract registry: %v", err) } fmt.Printf("GlobalRegistrar: %v, HashReg: %v, UrlHint: %v\n", registrar.GlobalRegistrarAddr, registrar.HashRegAddr, registrar.UrlHintAddr) if tf.lastConfirm != testExpNotice { - t.Errorf("Wrong confirm message. expected '%v', got '%v'", testExpNotice, tf.lastConfirm) + t.Errorf("Wrong confirm message. expected\n'%v', got\n'%v'", testExpNotice, tf.lastConfirm) } // test unknown method exp := fmt.Sprintf(testExpNotice2, registrar.HashRegAddr) - _, err = reg.SetOwner(tf.coinbase) + _, err = reg.SetOwner(addr) if err != nil { t.Errorf("error setting owner: %v", err) } if tf.lastConfirm != exp { - t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm) + t.Errorf("Wrong confirm message, expected\n'%v', got\n'%v'", exp, tf.lastConfirm) } // test unknown contract exp = fmt.Sprintf(testExpNotice3, registrar.UrlHintAddr) - _, err = reg.SetUrlToHash(tf.coinbase, dochash, "file:///test.content") + _, err = reg.SetUrlToHash(addr, dochash, "file:///test.content") if err != nil { t.Errorf("error registering: %v", err) } @@ -251,3 +247,63 @@ func TestNatspecE2E(t *testing.T) { } } + +func pendingTransactions(repl *testFrontend, t *testing.T) (txc int64, err error) { + txs := repl.ethereum.TxPool().GetTransactions() + return int64(len(txs)), nil +} + +func processTxs(repl *testFrontend, t *testing.T, expTxc int) bool { + var txc int64 + var err error + for i := 0; i < 50; i++ { + txc, err = pendingTransactions(repl, t) + if err != nil { + t.Errorf("unexpected error checking pending transactions: %v", err) + return false + } + if expTxc < int(txc) { + t.Errorf("too many pending transactions: expected %v, got %v", expTxc, txc) + return false + } else if expTxc == int(txc) { + break + } + time.Sleep(100 * time.Millisecond) + } + if int(txc) != expTxc { + t.Errorf("incorrect number of pending transactions, expected %v, got %v", expTxc, txc) + return false + } + + err = repl.ethereum.StartMining(runtime.NumCPU()) + if err != nil { + t.Errorf("unexpected error mining: %v", err) + return false + } + defer repl.ethereum.StopMining() + + timer := time.NewTimer(100 * time.Second) + height := new(big.Int).Add(repl.xeth.CurrentBlock().Number(), big.NewInt(1)) + repl.wait <- height + select { + case <-timer.C: + // if times out make sure the xeth loop does not block + go func() { + select { + case repl.wait <- nil: + case <-repl.wait: + } + }() + case <-repl.wait: + } + txc, err = pendingTransactions(repl, t) + if err != nil { + t.Errorf("unexpected error checking pending transactions: %v", err) + return false + } + if txc != 0 { + t.Errorf("%d trasactions were not mined", txc) + return false + } + return true +} diff --git a/common/registrar/registrar.go b/common/registrar/registrar.go index 457dd68942..2622317628 100644 --- a/common/registrar/registrar.go +++ b/common/registrar/registrar.go @@ -339,22 +339,15 @@ func (self *Registrar) HashToUrl(chash common.Hash) (uri string, err error) { key := storageAddress(storageFixedArray(mapaddr, storageIdx2Addr(idx))) hex := self.backend.StorageAt(UrlHintAddr[2:], key) str = string(common.Hex2Bytes(hex[2:])) - l := len(str) - for (l > 0) && (str[l-1] == 0) { - l-- + l := 0 + for (l < len(str)) && (str[l] == 0) { + l++ } - str = str[:l] + str = str[l:] uri = uri + str idx++ } - - l := 0 - for (l < len(uri)) && (uri[l] == 0) { - l++ - } - uri = uri[l:] - if len(uri) == 0 { err = fmt.Errorf("GetURLhint: URL hint not found for '%v'", chash.Hex()) } diff --git a/xeth/xeth.go b/xeth/xeth.go index f2295e6e15..a3923436af 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -203,34 +203,6 @@ func (self *XEth) AtStateNum(num int64) *XEth { return self.WithState(st) } -// applies queued transactions originating from address onto the latest state -// and creates a block -// only used in tests -// - could be removed in favour of mining on testdag (natspec e2e + networking) -// + filters -func (self *XEth) ApplyTestTxs(statedb *state.StateDB, address common.Address, txc uint64) (uint64, *XEth) { - chain := self.backend.ChainManager() - header := chain.CurrentBlock().Header() - coinbase := statedb.GetStateObject(address) - coinbase.SetGasLimit(big.NewInt(10000000)) - txs := self.backend.TxPool().GetQueuedTransactions() - - for i := 0; i < len(txs); i++ { - for _, tx := range txs { - if tx.Nonce() == txc { - _, _, err := core.ApplyMessage(core.NewEnv(statedb, self.backend.ChainManager(), tx, header), tx, coinbase) - if err != nil { - panic(err) - } - txc++ - } - } - } - - xeth := self.WithState(statedb) - return txc, xeth -} - func (self *XEth) WithState(statedb *state.StateDB) *XEth { xeth := &XEth{ backend: self.backend,