diff --git a/cmd/geth/consolecmd_test.go b/cmd/geth/consolecmd_test.go index 4360451195..33c83b7ede 100644 --- a/cmd/geth/consolecmd_test.go +++ b/cmd/geth/consolecmd_test.go @@ -87,7 +87,7 @@ func TestIPCAttachWelcome(t *testing.T) { "--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--etherbase", coinbase, "--shh", "--ipcpath", ipc) - time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open + waitForEndpoint(t, ipc, 3*time.Second) testAttachWelcome(t, geth, "ipc:"+ipc, ipcAPIs) geth.Interrupt() @@ -101,8 +101,9 @@ func TestHTTPAttachWelcome(t *testing.T) { "--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--etherbase", coinbase, "--rpc", "--rpcport", port) - time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open - testAttachWelcome(t, geth, "http://localhost:"+port, httpAPIs) + endpoint := "http://127.0.0.1:" + port + waitForEndpoint(t, endpoint, 3*time.Second) + testAttachWelcome(t, geth, endpoint, httpAPIs) geth.Interrupt() geth.ExpectExit() @@ -116,8 +117,9 @@ func TestWSAttachWelcome(t *testing.T) { "--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--etherbase", coinbase, "--ws", "--wsport", port) - time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open - testAttachWelcome(t, geth, "ws://localhost:"+port, httpAPIs) + endpoint := "ws://127.0.0.1:" + port + waitForEndpoint(t, endpoint, 3*time.Second) + testAttachWelcome(t, geth, endpoint, httpAPIs) geth.Interrupt() geth.ExpectExit() diff --git a/cmd/geth/run_test.go b/cmd/geth/run_test.go index da82facac3..f7b735b84c 100644 --- a/cmd/geth/run_test.go +++ b/cmd/geth/run_test.go @@ -17,13 +17,16 @@ package main import ( + "context" "fmt" "io/ioutil" "os" "testing" + "time" "github.com/docker/docker/pkg/reexec" "github.com/ethereum/go-ethereum/internal/cmdtest" + "github.com/ethereum/go-ethereum/rpc" ) func tmpdir(t *testing.T) string { @@ -96,3 +99,28 @@ func runGeth(t *testing.T, args ...string) *testgeth { return tt } + +// waitForEndpoint attempts to connect to an RPC endpoint until it succeeds. +func waitForEndpoint(t *testing.T, endpoint string, timeout time.Duration) { + probe := func() bool { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + c, err := rpc.DialContext(ctx, endpoint) + if c != nil { + _, err = c.SupportedModules() + c.Close() + } + return err == nil + } + + start := time.Now() + for { + if probe() { + return + } + if time.Since(start) > timeout { + t.Fatal("endpoint", endpoint, "did not open within", timeout) + } + time.Sleep(200 * time.Millisecond) + } +}