From 69e2555b2ca394155a8c3870d091d47acb4ea1a3 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Mon, 26 Oct 2026 09:54:34 +0000 Subject: [PATCH 1/3] test: retry TestWasm when Chrome does not start in time chromedp gives Chrome 20s to print its DevTools address, and wasmbrowsertest has no option to raise that limit. On 20 fresh GitHub runners the first Chrome start took 5.2s to 27.4s, so TestWasm sometimes failed with "websocket url timeout reached" before any wasm test ran. Later starts on the same runners took at most 1.2s, so one retry is enough in practice. --- conn_test.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/conn_test.go b/conn_test.go index 01af8cd4..c57a1218 100644 --- a/conn_test.go +++ b/conn_test.go @@ -459,14 +459,28 @@ func TestWasm(t *testing.T) { })) defer s.Close() - ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) defer cancel() - cmd := exec.CommandContext(ctx, "go", "test", "-exec=wasmbrowsertest", ".", "-v") - cmd.Env = append(cleanEnv(os.Environ()), "GOOS=js", "GOARCH=wasm", fmt.Sprintf("WS_ECHO_SERVER_URL=%v", s.URL)) - - b, err := cmd.CombinedOutput() - if err != nil { + // wasmbrowsertest fails with this message when Chrome does not print its + // DevTools address within chromedp's 20s limit, which it gives no option + // to raise. On a fresh CI runner the first Chrome start can take over 20s; + // later starts take about a second. No wasm test has run at that point, so + // a retry cannot hide a library failure. + const chromeStartTimeout = "websocket url timeout reached" + const attempts = 3 + for attempt := 1; ; attempt++ { + cmd := exec.CommandContext(ctx, "go", "test", "-exec=wasmbrowsertest", ".", "-v") + cmd.Env = append(cleanEnv(os.Environ()), "GOOS=js", "GOARCH=wasm", fmt.Sprintf("WS_ECHO_SERVER_URL=%v", s.URL)) + + b, err := cmd.CombinedOutput() + if err == nil { + return + } + if attempt < attempts && ctx.Err() == nil && bytes.Contains(b, []byte(chromeStartTimeout)) { + t.Logf("attempt %d/%d: Chrome did not start in time, retrying", attempt, attempts) + continue + } t.Fatalf("wasm test binary failed: %v:\n%s", err, b) } } From 4788aa0d62a3d08645bda5c5b6f78e087b454cf0 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Mon, 26 Oct 2026 14:26:16 +0000 Subject: [PATCH 2/3] test: bound the TestWasm retry loop in its header --- conn_test.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/conn_test.go b/conn_test.go index c57a1218..14cb6356 100644 --- a/conn_test.go +++ b/conn_test.go @@ -469,7 +469,7 @@ func TestWasm(t *testing.T) { // a retry cannot hide a library failure. const chromeStartTimeout = "websocket url timeout reached" const attempts = 3 - for attempt := 1; ; attempt++ { + for attempt := 1; attempt <= attempts; attempt++ { cmd := exec.CommandContext(ctx, "go", "test", "-exec=wasmbrowsertest", ".", "-v") cmd.Env = append(cleanEnv(os.Environ()), "GOOS=js", "GOARCH=wasm", fmt.Sprintf("WS_ECHO_SERVER_URL=%v", s.URL)) @@ -477,11 +477,10 @@ func TestWasm(t *testing.T) { if err == nil { return } - if attempt < attempts && ctx.Err() == nil && bytes.Contains(b, []byte(chromeStartTimeout)) { - t.Logf("attempt %d/%d: Chrome did not start in time, retrying", attempt, attempts) - continue + if attempt == attempts || ctx.Err() != nil || !bytes.Contains(b, []byte(chromeStartTimeout)) { + t.Fatalf("wasm test binary failed: %v:\n%s", err, b) } - t.Fatalf("wasm test binary failed: %v:\n%s", err, b) + t.Logf("attempt %d/%d: Chrome did not start in time, retrying", attempt, attempts) } } From 895dff9077036b7a39e3dfd75150345cfdbb9667 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Mon, 26 Oct 2026 14:29:32 +0000 Subject: [PATCH 3/3] test: shorten the TestWasm retry comment --- conn_test.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/conn_test.go b/conn_test.go index 14cb6356..22208520 100644 --- a/conn_test.go +++ b/conn_test.go @@ -462,11 +462,8 @@ func TestWasm(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) defer cancel() - // wasmbrowsertest fails with this message when Chrome does not print its - // DevTools address within chromedp's 20s limit, which it gives no option - // to raise. On a fresh CI runner the first Chrome start can take over 20s; - // later starts take about a second. No wasm test has run at that point, so - // a retry cannot hide a library failure. + // Chrome's first start on a fresh CI runner can exceed the 20s that + // wasmbrowsertest allows. No wasm test has run by then, so retrying is safe. const chromeStartTimeout = "websocket url timeout reached" const attempts = 3 for attempt := 1; attempt <= attempts; attempt++ {