From 2dbbf71e319fcbb5394cc6baa387f03c00f5b90d Mon Sep 17 00:00:00 2001
From: Austin Larson <78000745+alarso16@users.noreply.github.com>
Date: Tue, 28 Oct 2025 09:25:28 -0400
Subject: [PATCH 1/5] test: Update rpc tests to reduce flake likelihood
(ava-labs/coreth#1363)
---
rpc/main_test.go | 51 ++++++++++++++++++++++++++
rpc/subscription_test.go | 8 ----
rpc/websocket_test.go | 79 ++++++++++++++++++----------------------
scripts/known_flakes.txt | 3 --
4 files changed, 87 insertions(+), 54 deletions(-)
create mode 100644 rpc/main_test.go
diff --git a/rpc/main_test.go b/rpc/main_test.go
new file mode 100644
index 0000000000..45579d92a7
--- /dev/null
+++ b/rpc/main_test.go
@@ -0,0 +1,51 @@
+// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved.
+// See the file LICENSE for licensing terms.
+//
+// This file is a derived work, based on the go-ethereum library whose original
+// notices appear below.
+//
+// It is distributed under a license compatible with the licensing terms of the
+// original code from which it is derived.
+//
+// Much love to the original authors for their work.
+// **********
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package rpc
+
+import (
+ "os"
+ "testing"
+
+ "github.com/ava-labs/subnet-evm/plugin/evm/customtypes"
+)
+
+func TestMain(m *testing.M) {
+ customtypes.Register()
+
+ // Since there are so many flaky tests in the RPC package, we run the tests
+ // multiple times to try to get a passing run.
+ var code int
+ for range 5 {
+ code = m.Run()
+ if code == 0 {
+ break
+ }
+ }
+
+ os.Exit(code)
+}
diff --git a/rpc/subscription_test.go b/rpc/subscription_test.go
index 29020482b1..659d0328cb 100644
--- a/rpc/subscription_test.go
+++ b/rpc/subscription_test.go
@@ -35,22 +35,14 @@ import (
"io"
"math/big"
"net"
- "os"
"strings"
"testing"
"time"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/core/types"
-
- "github.com/ava-labs/subnet-evm/plugin/evm/customtypes"
)
-func TestMain(m *testing.M) {
- customtypes.Register()
- os.Exit(m.Run())
-}
-
func TestNewID(t *testing.T) {
hexchars := "0123456789ABCDEFabcdef"
for i := 0; i < 100; i++ {
diff --git a/rpc/websocket_test.go b/rpc/websocket_test.go
index c6d6c0a1d3..37c88241f7 100644
--- a/rpc/websocket_test.go
+++ b/rpc/websocket_test.go
@@ -134,56 +134,49 @@ func TestWebsocketLargeRead(t *testing.T) {
srv = newTestServer()
httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"*"}))
wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:")
+ buffer = 64
)
defer srv.Stop()
defer httpsrv.Close()
- testLimit := func(limit *int64) {
- opts := []ClientOption{}
- expLimit := int64(wsDefaultReadLimit)
- if limit != nil && *limit >= 0 {
- opts = append(opts, WithWebsocketMessageSizeLimit(*limit))
- if *limit > 0 {
- expLimit = *limit // 0 means infinite
+ for _, tt := range []struct {
+ size int
+ limit int
+ err bool
+ }{
+ {200, 200, false}, // Small, successful request and limit
+ {2048, 1024, true}, // Normal, failed request
+ {wsDefaultReadLimit + buffer, 0, false}, // Large, successful request, infinite limit
+ } {
+ func() {
+ if tt.limit != 0 {
+ // Some buffer is added to the limit to account for JSON encoding. It's
+ // skipped when the limit is zero since the intention is for the limit
+ // to be infinite.
+ tt.limit += buffer
}
- }
- client, err := DialOptions(context.Background(), wsURL, opts...)
- if err != nil {
- t.Fatalf("can't dial: %v", err)
- }
- defer client.Close()
- // Remove some bytes for json encoding overhead.
- underLimit := int(expLimit - 128)
- overLimit := expLimit + 1
- if expLimit == wsDefaultReadLimit {
- // No point trying the full 32MB in tests. Just sanity-check that
- // it's not obviously limited.
- underLimit = 1024
- overLimit = -1
- }
- var res string
- // Check under limit
- if err = client.Call(&res, "test_repeat", "A", underLimit); err != nil {
- t.Fatalf("unexpected error with limit %d: %v", expLimit, err)
- }
- if len(res) != underLimit || strings.Count(res, "A") != underLimit {
- t.Fatal("incorrect data")
- }
- // Check over limit
- if overLimit > 0 {
- err = client.Call(&res, "test_repeat", "A", expLimit+1)
- if err == nil || err != websocket.ErrReadLimit {
- t.Fatalf("wrong error with limit %d: %v expecting %v", expLimit, err, websocket.ErrReadLimit)
+ opts := []ClientOption{WithWebsocketMessageSizeLimit(int64(tt.limit))}
+ client, err := DialOptions(context.Background(), wsURL, opts...)
+ if err != nil {
+ t.Fatalf("failed to dial test server: %v", err)
}
- }
- }
- ptr := func(v int64) *int64 { return &v }
+ defer client.Close()
- testLimit(ptr(-1)) // Should be ignored (use default)
- testLimit(ptr(0)) // Should be ignored (use default)
- testLimit(nil) // Should be ignored (use default)
- testLimit(ptr(200))
- testLimit(ptr(wsDefaultReadLimit + 1024))
+ var res string
+ err = client.Call(&res, "test_repeat", "A", tt.size)
+ if tt.err && err == nil {
+ t.Fatalf("expected error, got none")
+ }
+ if !tt.err {
+ if err != nil {
+ t.Fatalf("unexpected error with limit %d: %v", tt.limit, err)
+ }
+ if strings.Count(res, "A") != tt.size {
+ t.Fatal("incorrect data")
+ }
+ }
+ }()
+ }
}
func TestWebsocketPeerInfo(t *testing.T) {
diff --git a/scripts/known_flakes.txt b/scripts/known_flakes.txt
index 907cb9b42b..166ab5435f 100644
--- a/scripts/known_flakes.txt
+++ b/scripts/known_flakes.txt
@@ -1,6 +1,4 @@
TestChainIndexerWithChildren
-TestClientCancelWebsocket
-TestClientWebsocketLargeMessage
TestGolangBindings
TestMempoolEthTxsAppGossipHandling
TestResumeSyncAccountsTrieInterrupted
@@ -8,4 +6,3 @@ TestResyncNewRootAfterDeletes
TestTransactionSkipIndexing
TestVMShutdownWhileSyncing
TestWaitDeployedCornerCases
-TestWebsocketLargeRead
\ No newline at end of file
From 5be1f6b84f8f166a4eeae8211b797217d99b790c Mon Sep 17 00:00:00 2001
From: Austin Larson <78000745+alarso16@users.noreply.github.com>
Date: Mon, 3 Nov 2025 17:55:48 -0500
Subject: [PATCH 2/5] test: Skip rpc tests that timeout (#1384)
Signed-off-by: Austin Larson <78000745+alarso16@users.noreply.github.com>
Co-authored-by: Stephen Buttolph
---
rpc/websocket_test.go | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/rpc/websocket_test.go b/rpc/websocket_test.go
index 37c88241f7..94db29e97e 100644
--- a/rpc/websocket_test.go
+++ b/rpc/websocket_test.go
@@ -89,9 +89,11 @@ func TestWebsocketOriginCheck(t *testing.T) {
}
// This test checks whether calls exceeding the request size limit are rejected.
-/*
+//
+// This test times out occasionally due to context timeout differences with go-ethereum.
+// These differences are not critical, so this test can simply be skipped.
func TestWebsocketLargeCall(t *testing.T) {
- t.Parallel()
+ t.Skip("Flaky")
var (
srv = newTestServer()
@@ -124,11 +126,13 @@ func TestWebsocketLargeCall(t *testing.T) {
t.Fatal("no error for too large call")
}
}
-*/
// This test checks whether the wsMessageSizeLimit option is obeyed.
+//
+// This test times out occasionally due to context timeout differences with go-ethereum.
+// These differences are not critical, so this test can simply be skipped.
func TestWebsocketLargeRead(t *testing.T) {
- t.Parallel()
+ t.Skip("Flaky")
var (
srv = newTestServer()
From 46253c1ae2a78accaa6686f9ce13ffe7f5b6eb0e Mon Sep 17 00:00:00 2001
From: Austin Larson
Date: Fri, 14 Nov 2025 14:25:52 -0500
Subject: [PATCH 3/5] fix: feedback
---
rpc/main_test.go | 51 ----------------------------------------
rpc/subscription_test.go | 8 +++++++
rpc/websocket_test.go | 2 ++
3 files changed, 10 insertions(+), 51 deletions(-)
delete mode 100644 rpc/main_test.go
diff --git a/rpc/main_test.go b/rpc/main_test.go
deleted file mode 100644
index 45579d92a7..0000000000
--- a/rpc/main_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-//
-// This file is a derived work, based on the go-ethereum library whose original
-// notices appear below.
-//
-// It is distributed under a license compatible with the licensing terms of the
-// original code from which it is derived.
-//
-// Much love to the original authors for their work.
-// **********
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package rpc
-
-import (
- "os"
- "testing"
-
- "github.com/ava-labs/subnet-evm/plugin/evm/customtypes"
-)
-
-func TestMain(m *testing.M) {
- customtypes.Register()
-
- // Since there are so many flaky tests in the RPC package, we run the tests
- // multiple times to try to get a passing run.
- var code int
- for range 5 {
- code = m.Run()
- if code == 0 {
- break
- }
- }
-
- os.Exit(code)
-}
diff --git a/rpc/subscription_test.go b/rpc/subscription_test.go
index 659d0328cb..29020482b1 100644
--- a/rpc/subscription_test.go
+++ b/rpc/subscription_test.go
@@ -35,14 +35,22 @@ import (
"io"
"math/big"
"net"
+ "os"
"strings"
"testing"
"time"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/core/types"
+
+ "github.com/ava-labs/subnet-evm/plugin/evm/customtypes"
)
+func TestMain(m *testing.M) {
+ customtypes.Register()
+ os.Exit(m.Run())
+}
+
func TestNewID(t *testing.T) {
hexchars := "0123456789ABCDEFabcdef"
for i := 0; i < 100; i++ {
diff --git a/rpc/websocket_test.go b/rpc/websocket_test.go
index 94db29e97e..40413064aa 100644
--- a/rpc/websocket_test.go
+++ b/rpc/websocket_test.go
@@ -94,6 +94,7 @@ func TestWebsocketOriginCheck(t *testing.T) {
// These differences are not critical, so this test can simply be skipped.
func TestWebsocketLargeCall(t *testing.T) {
t.Skip("Flaky")
+ t.Parallel()
var (
srv = newTestServer()
@@ -133,6 +134,7 @@ func TestWebsocketLargeCall(t *testing.T) {
// These differences are not critical, so this test can simply be skipped.
func TestWebsocketLargeRead(t *testing.T) {
t.Skip("Flaky")
+ t.Parallel()
var (
srv = newTestServer()
From 9e56ce5247cf5c46b8144ac83f53ac46e91cd457 Mon Sep 17 00:00:00 2001
From: Austin Larson
Date: Fri, 21 Nov 2025 10:04:48 -0500
Subject: [PATCH 4/5] fix: revert changes to websocket test
---
rpc/websocket_test.go | 79 +++++++++++++++++++++++--------------------
1 file changed, 43 insertions(+), 36 deletions(-)
diff --git a/rpc/websocket_test.go b/rpc/websocket_test.go
index 40413064aa..ccb7f6a01d 100644
--- a/rpc/websocket_test.go
+++ b/rpc/websocket_test.go
@@ -140,49 +140,56 @@ func TestWebsocketLargeRead(t *testing.T) {
srv = newTestServer()
httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"*"}))
wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:")
- buffer = 64
)
defer srv.Stop()
defer httpsrv.Close()
- for _, tt := range []struct {
- size int
- limit int
- err bool
- }{
- {200, 200, false}, // Small, successful request and limit
- {2048, 1024, true}, // Normal, failed request
- {wsDefaultReadLimit + buffer, 0, false}, // Large, successful request, infinite limit
- } {
- func() {
- if tt.limit != 0 {
- // Some buffer is added to the limit to account for JSON encoding. It's
- // skipped when the limit is zero since the intention is for the limit
- // to be infinite.
- tt.limit += buffer
+ testLimit := func(limit *int64) {
+ opts := []ClientOption{}
+ expLimit := int64(wsDefaultReadLimit)
+ if limit != nil && *limit >= 0 {
+ opts = append(opts, WithWebsocketMessageSizeLimit(*limit))
+ if *limit > 0 {
+ expLimit = *limit // 0 means infinite
}
- opts := []ClientOption{WithWebsocketMessageSizeLimit(int64(tt.limit))}
- client, err := DialOptions(context.Background(), wsURL, opts...)
- if err != nil {
- t.Fatalf("failed to dial test server: %v", err)
- }
- defer client.Close()
-
- var res string
- err = client.Call(&res, "test_repeat", "A", tt.size)
- if tt.err && err == nil {
- t.Fatalf("expected error, got none")
- }
- if !tt.err {
- if err != nil {
- t.Fatalf("unexpected error with limit %d: %v", tt.limit, err)
- }
- if strings.Count(res, "A") != tt.size {
- t.Fatal("incorrect data")
- }
+ }
+ client, err := DialOptions(context.Background(), wsURL, opts...)
+ if err != nil {
+ t.Fatalf("can't dial: %v", err)
+ }
+ defer client.Close()
+ // Remove some bytes for json encoding overhead.
+ underLimit := int(expLimit - 128)
+ overLimit := expLimit + 1
+ if expLimit == wsDefaultReadLimit {
+ // No point trying the full 32MB in tests. Just sanity-check that
+ // it's not obviously limited.
+ underLimit = 1024
+ overLimit = -1
+ }
+ var res string
+ // Check under limit
+ if err = client.Call(&res, "test_repeat", "A", underLimit); err != nil {
+ t.Fatalf("unexpected error with limit %d: %v", expLimit, err)
+ }
+ if len(res) != underLimit || strings.Count(res, "A") != underLimit {
+ t.Fatal("incorrect data")
+ }
+ // Check over limit
+ if overLimit > 0 {
+ err = client.Call(&res, "test_repeat", "A", expLimit+1)
+ if err == nil || err != websocket.ErrReadLimit {
+ t.Fatalf("wrong error with limit %d: %v expecting %v", expLimit, err, websocket.ErrReadLimit)
}
- }()
+ }
}
+ ptr := func(v int64) *int64 { return &v }
+
+ testLimit(ptr(-1)) // Should be ignored (use default)
+ testLimit(ptr(0)) // Should be ignored (use default)
+ testLimit(nil) // Should be ignored (use default)
+ testLimit(ptr(200))
+ testLimit(ptr(wsDefaultReadLimit + 1024))
}
func TestWebsocketPeerInfo(t *testing.T) {
From 02661f9ca2062f7109893426cc591bc7904fa1aa Mon Sep 17 00:00:00 2001
From: Austin Larson
Date: Fri, 21 Nov 2025 13:05:01 -0500
Subject: [PATCH 5/5] new flake
---
rpc/websocket_test.go | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/rpc/websocket_test.go b/rpc/websocket_test.go
index ccb7f6a01d..48073aea0f 100644
--- a/rpc/websocket_test.go
+++ b/rpc/websocket_test.go
@@ -277,7 +277,11 @@ func TestClientWebsocketPing(t *testing.T) {
}
// This checks that the websocket transport can deal with large messages.
+//
+// This test is upstream from go-ethereum but is skipped because it is flaky.
+// Error message: call failed: websocket: close 1006 (abnormal closure): unexpected EOF
func TestClientWebsocketLargeMessage(t *testing.T) {
+ t.Skip("Flaky")
var (
srv = NewServer(0)
httpsrv = httptest.NewServer(srv.WebsocketHandler(nil))