From e1f616fadf4fe20030d518d0c3f2a3f05186ab68 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 22 Apr 2015 10:59:27 +0200 Subject: [PATCH] cmd/geth: improve the JS tests These changes ensure that the JS tests run without networking and fixes the block chain export and its associated test. --- cmd/geth/admin.go | 25 +---- cmd/geth/js_test.go | 263 ++++++++++++-------------------------------- 2 files changed, 75 insertions(+), 213 deletions(-) diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go index bd09291bf..e75ff047a 100644 --- a/cmd/geth/admin.go +++ b/cmd/geth/admin.go @@ -3,7 +3,6 @@ package main import ( "errors" "fmt" - "os" "time" "github.com/ethereum/go-ethereum/cmd/utils" @@ -318,7 +317,7 @@ func (js *jsre) newAccount(call otto.FunctionCall) otto.Value { fmt.Printf("Could not create the account: %v", err) return otto.UndefinedValue() } - return js.re.ToVal(common.Bytes2Hex(acct.Address)) + return js.re.ToVal("0x" + common.Bytes2Hex(acct.Address)) } func (js *jsre) nodeInfo(call otto.FunctionCall) otto.Value { @@ -334,33 +333,15 @@ func (js *jsre) importChain(call otto.FunctionCall) otto.Value { fmt.Println("err: require file name") return otto.FalseValue() } - fn, err := call.Argument(0).ToString() if err != nil { fmt.Println(err) return otto.FalseValue() } - - var fh *os.File - fh, err = os.OpenFile(fn, os.O_RDONLY, os.ModePerm) - if err != nil { - fmt.Println(err) + if err := utils.ImportChain(js.ethereum.ChainManager(), fn); err != nil { + fmt.Println("Import error: ", err) return otto.FalseValue() } - defer fh.Close() - - var blocks types.Blocks - if err = rlp.Decode(fh, &blocks); err != nil { - fmt.Println(err) - return otto.FalseValue() - } - - js.ethereum.ChainManager().Reset() - if err = js.ethereum.ChainManager().InsertChain(blocks); err != nil { - fmt.Println(err) - return otto.FalseValue() - } - return otto.TrueValue() } diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go index 4421b1d68..521039121 100644 --- a/cmd/geth/js_test.go +++ b/cmd/geth/js_test.go @@ -3,260 +3,141 @@ package main import ( "fmt" "io/ioutil" + "path/filepath" "os" "path" "testing" - "github.com/robertkrimen/otto" - "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth" + "runtime" + "regexp" + "strconv" ) var port = 30300 -func testJEthRE(t *testing.T) (repl *jsre, ethereum *eth.Ethereum, err error) { - os.RemoveAll("/tmp/eth/") - err = os.MkdirAll("/tmp/eth/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/", os.ModePerm) +func testJEthRE(t *testing.T) (*jsre, *eth.Ethereum) { + tmp, err := ioutil.TempDir("", "geth-test") if err != nil { - t.Errorf("%v", err) - return + t.Fatal(err) } - err = os.MkdirAll("/tmp/eth/data", os.ModePerm) - if err != nil { - t.Errorf("%v", err) - return - } - // FIXME: this does not work ATM - ks := crypto.NewKeyStorePlain("/tmp/eth/keys") - ioutil.WriteFile("/tmp/eth/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/e273f01c99144c438695e10f24926dc1f9fbf62d", - []byte(`{"Id":"RhRXD+fNRKS4jx+7ZfEsNA==","Address":"4nPwHJkUTEOGleEPJJJtwfn79i0=","PrivateKey":"h4ACVpe74uIvi5Cg/2tX/Yrm2xdr3J7QoMbMtNX2CNc="}`), os.ModePerm) + defer os.RemoveAll(tmp) - port++ - ethereum, err = eth.New(ð.Config{ - DataDir: "/tmp/eth", + ks := crypto.NewKeyStorePlain(filepath.Join(tmp, "keys")) + ethereum, err := eth.New(ð.Config{ + DataDir: tmp, AccountManager: accounts.NewManager(ks), - Port: fmt.Sprintf("%d", port), - MaxPeers: 10, + MaxPeers: 0, Name: "test", }) - if err != nil { - t.Errorf("%v", err) - return + t.Fatal("%v", err) } assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext") - repl = newJSRE(ethereum, assetPath, false) - return + repl := newJSRE(ethereum, assetPath, false) + return repl, ethereum } func TestNodeInfo(t *testing.T) { - repl, ethereum, err := testJEthRE(t) - if err != nil { - t.Errorf("error creating jsre, got %v", err) - return - } - err = ethereum.Start() - if err != nil { - t.Errorf("error starting ethereum: %v", err) - return + repl, ethereum := testJEthRE(t) + if err := ethereum.Start(); err != nil { + t.Fatalf("error starting ethereum: %v", err) } defer ethereum.Stop() - val, err := repl.re.Run("admin.nodeInfo()") - if err != nil { - t.Errorf("expected no error, got %v", err) - } - exp, err := val.Export() - if err != nil { - t.Errorf("expected no error, got %v", err) - } - nodeInfo, ok := exp.(*eth.NodeInfo) - if !ok { - t.Errorf("expected nodeInfo, got %v", err) - } - exp = "test" - got := nodeInfo.Name - if exp != got { - t.Errorf("expected %v, got %v", exp, got) - } - exp = 30301 - port := nodeInfo.DiscPort - if exp != port { - t.Errorf("expected %v, got %v", exp, port) - } - exp = 30301 - port = nodeInfo.TCPPort - if exp != port { - t.Errorf("expected %v, got %v", exp, port) - } + want := `{"DiscPort":0,"IP":"0.0.0.0","ListenAddr":"","Name":"test","NodeID":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","NodeUrl":"enode://00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000@0.0.0.0:0","TCPPort":0,"Td":"0"}` + checkEvalJSON(t, repl, `admin.nodeInfo()`, want) } func TestAccounts(t *testing.T) { - repl, ethereum, err := testJEthRE(t) - if err != nil { - t.Errorf("error creating jsre, got %v", err) - return - } - err = ethereum.Start() - if err != nil { - t.Errorf("error starting ethereum: %v", err) - return + repl, ethereum := testJEthRE(t) + if err := ethereum.Start(); err != nil { + t.Fatalf("error starting ethereum: %v", err) } defer ethereum.Stop() - val, err := repl.re.Run("eth.coinbase") + checkEvalJSON(t, repl, `eth.accounts`, `[]`) + checkEvalJSON(t, repl, `eth.coinbase`, `"0x"`) + + val, err := repl.re.Run(`admin.newAccount("password")`) if err != nil { t.Errorf("expected no error, got %v", err) } - - pp, err := repl.re.PrettyPrint(val) - if err != nil { - t.Errorf("%v", err) - } - - if !val.IsString() { - t.Errorf("incorrect type, expected string, got %v: %v", val, pp) - } - strVal, _ := val.ToString() - expected := "0xe273f01c99144c438695e10f24926dc1f9fbf62d" - if strVal != expected { - t.Errorf("incorrect result, expected %s, got %v", expected, strVal) - } - - val, err = repl.re.Run(`admin.newAccount("password")`) - if err != nil { - t.Errorf("expected no error, got %v", err) - } - addr, err := val.ToString() - if err != nil { - t.Errorf("expected string, got %v", err) - } - - val, err = repl.re.Run("eth.accounts") - if err != nil { - t.Errorf("expected no error, got %v", err) - } - exp, err := val.Export() - if err != nil { - t.Errorf("expected no error, got %v", err) - } - interfaceAddr, ok := exp.([]interface{}) - if !ok { - t.Errorf("expected []string, got %T", exp) - } - - addrs := make([]string, len(interfaceAddr)) - for i, addr := range interfaceAddr { - var ok bool - if addrs[i], ok = addr.(string); !ok { - t.Errorf("expected addrs[%d] to be string. Got %T instead", i, addr) - } - } - - if len(addrs) != 2 || (addr != addrs[0][2:] && addr != addrs[1][2:]) { - t.Errorf("expected addrs == [, ], got %v (%v)", addrs, addr) + addr := val.String() + if !regexp.MustCompile(`0x[0-9a-f]{40}`).MatchString(addr) { + t.Errorf("address not hex: %q", addr) } + checkEvalJSON(t, repl, `eth.accounts`, `["` + addr + `"]`) + checkEvalJSON(t, repl, `eth.coinbase`, `"` + addr + `"`) } func TestBlockChain(t *testing.T) { - repl, ethereum, err := testJEthRE(t) - if err != nil { - t.Errorf("error creating jsre, got %v", err) - return - } - err = ethereum.Start() - if err != nil { - t.Errorf("error starting ethereum: %v", err) - return + repl, ethereum := testJEthRE(t) + if err := ethereum.Start(); err != nil { + t.Fatalf("error starting ethereum: %v", err) } defer ethereum.Stop() - // should get current block - val0, err := repl.re.Run("admin.debug.dumpBlock()") + // get current block dump before export/import. + val, err := repl.re.Run("JSON.stringify(admin.debug.dumpBlock())") if err != nil { t.Errorf("expected no error, got %v", err) } + beforeExport := val.String() - fn := "/tmp/eth/data/blockchain.0" - _, err = repl.re.Run("admin.export(\"" + fn + "\")") + // do the export + tmp, err := ioutil.TempDir("", "geth-test-export") if err != nil { - t.Errorf("expected no error, got %v", err) + t.Fatal(err) } - if _, err = os.Stat(fn); err != nil { - t.Errorf("expected no error on file, got %v", err) + defer os.RemoveAll(tmp) + tmpfile := filepath.Join(tmp, "export.chain") + tmpfileq := strconv.Quote(tmpfile) + + checkEvalJSON(t, repl, `admin.export(` + tmpfileq + `)`, `true`) + if _, err := os.Stat(tmpfile); err != nil { + t.Fatal(err) } - _, err = repl.re.Run("admin.import(\"" + fn + "\")") - if err != nil { - t.Errorf("expected no error, got %v", err) - } - - var val1 otto.Value - - // should get current block - val1, err = repl.re.Run("admin.debug.dumpBlock()") - if err != nil { - t.Errorf("expected no error, got %v", err) - } - - // FIXME: neither != , nor reflect.DeepEqual works, doing string comparison - v0 := fmt.Sprintf("%v", val0) - v1 := fmt.Sprintf("%v", val1) - if v0 != v1 { - t.Errorf("expected same head after export-import, got %v (!=%v)", v1, v0) - } + // check import, verify that dumpBlock gives the same result. + checkEvalJSON(t, repl, `admin.import(` + tmpfileq + `)`, `true`) + checkEvalJSON(t, repl, `admin.debug.dumpBlock()`, beforeExport) } func TestMining(t *testing.T) { - repl, ethereum, err := testJEthRE(t) - if err != nil { - t.Errorf("error creating jsre, got %v", err) - return - } - err = ethereum.Start() - if err != nil { - t.Errorf("error starting ethereum: %v", err) - return + repl, ethereum := testJEthRE(t) + if err := ethereum.Start(); err != nil { + t.Fatalf("error starting ethereum: %v", err) } defer ethereum.Stop() - val, err := repl.re.Run("eth.mining") - if err != nil { - t.Errorf("expected no error, got %v", err) - } - var mining bool - mining, err = val.ToBoolean() - if err != nil { - t.Errorf("expected boolean, got %v", err) - } - if mining { - t.Errorf("expected false (not mining), got true") - } - + checkEvalJSON(t, repl, `eth.mining`, `false`) } func TestRPC(t *testing.T) { - repl, ethereum, err := testJEthRE(t) - if err != nil { - t.Errorf("error creating jsre, got %v", err) - return - } - err = ethereum.Start() - if err != nil { + repl, ethereum := testJEthRE(t) + if err := ethereum.Start(); err != nil { t.Errorf("error starting ethereum: %v", err) return } defer ethereum.Stop() - val, err := repl.re.Run(`admin.startRPC("127.0.0.1", 5004)`) - if err != nil { - t.Errorf("expected no error, got %v", err) - } - success, _ := val.ToBoolean() - if !success { - t.Errorf("expected true (started), got false") - } + checkEvalJSON(t, repl, `admin.startRPC("127.0.0.1", 5004)`, `true`) +} + +func checkEvalJSON(t *testing.T, re *jsre, expr, want string) error { + val, err := re.re.Run("JSON.stringify("+ expr + ")") + if err == nil && val.String() != want { + err = fmt.Errorf("Output mismatch for `%s`:\ngot: %s\nwant: %s", expr, val.String(), want) + } + if err != nil { + _, file, line, _ := runtime.Caller(1) + file = path.Base(file) + fmt.Printf("\t%s:%d: %v\n", file, line, err) + t.Fail() + } + return err }