Skip to content

Commit

Permalink
cmd/geth: improve the JS tests
Browse files Browse the repository at this point in the history
These changes ensure that the JS tests run without networking
and fixes the block chain export and its associated test.
  • Loading branch information
fjl committed Apr 22, 2015
1 parent 635b66a commit e1f616f
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 209 deletions.
25 changes: 3 additions & 22 deletions cmd/geth/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"errors"
"fmt"
"os"
"time"

"github.com/ethereum/go-ethereum/cmd/utils"
Expand Down Expand Up @@ -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 {
Expand All @@ -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()
}

Expand Down
255 changes: 68 additions & 187 deletions cmd/geth/js_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
if err != nil {
t.Errorf("%v", err)
return
}
err = os.MkdirAll("/tmp/eth/data", 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)
}
// 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)

This comment has been minimized.

Copy link
@zelig

zelig Apr 29, 2015

Contributor

@fjl wow this was NASTY. 2hours to find out. we should defer until test finishes...no tthe init setup ... obvious

This comment has been minimized.

Copy link
@fjl

fjl Apr 29, 2015

Author Contributor

sorry


port++
ethereum, err = eth.New(&eth.Config{
DataDir: "/tmp/eth",
ks := crypto.NewKeyStorePlain(filepath.Join(tmp, "keys"))
ethereum, err := eth.New(&eth.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")
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)
}
checkEvalJSON(t, repl, `eth.accounts`, `[]`)
checkEvalJSON(t, repl, `eth.coinbase`, `"0x"`)

val, err = repl.re.Run(`admin.newAccount("password")`)
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 == [<default>, <new>], 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)
}
if _, err = os.Stat(fn); err != nil {
t.Errorf("expected no error on file, got %v", err)
t.Fatal(err)
}
defer os.RemoveAll(tmp)
tmpfile := filepath.Join(tmp, "export.chain")
tmpfileq := strconv.Quote(tmpfile)

_, err = repl.re.Run("admin.import(\"" + fn + "\")")
if err != nil {
t.Errorf("expected no error, got %v", err)
checkEvalJSON(t, repl, `admin.export(` + tmpfileq + `)`, `true`)
if _, err := os.Stat(tmpfile); err != nil {
t.Fatal(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)
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)
}
success, _ := val.ToBoolean()
if !success {
t.Errorf("expected true (started), got false")
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
}

0 comments on commit e1f616f

Please sign in to comment.