pytests: fix flakes in grpc tests by waiting for the channel to be ready first
What changed, and why it matters
This commit fixes flaky automated tests for the gRPC interface. It makes the test framework wait until the gRPC connection is fully ready before using it, preventing random timeouts. There is no security issue here—just a test reliability improvement.
No security action needed. Treat as a normal test-infrastructure fix.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change adds grpc.channel_ready_future(channel).result(timeout=10) inside LightningNode.grpc property initialization so the TLS handshake completes eagerly rather than lazily on the first RPC. Several gRPC tests now also explicitly call wait_for_grpc_start(l1). This eliminates race conditions where streaming RPCs (SubscribeCustomMsg, SubscribeConnect, SubscribeBlockAdded) were started before the channel was ready, causing intermittent test timeouts. No production code behavior is changed.
Changed components
contrib/pyln-testing/pyln/testing/utils.pytests/test_cln_rs.pyInspect captured patch +13 / −0
diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py
index e484b11f..30639034 100644
--- a/contrib/pyln-testing/pyln/testing/utils.py
+++ b/contrib/pyln-testing/pyln/testing/utils.py
@@ -1074,6 +1074,11 @@ class LightningNode(object):
creds,
options=(('grpc.ssl_target_name_override', 'cln'),)
)
+
+ # Force the connect+handshake to finish now, instead of lazily on
+ # the first RPC the caller happens to make.
+ grpc.channel_ready_future(channel).result(timeout=10)
+
from pyln import grpc as clnpb
return clnpb.NodeStub(channel)
diff --git a/tests/test_cln_rs.py b/tests/test_cln_rs.py
index ea76002c..fab0d98a 100644
--- a/tests/test_cln_rs.py
+++ b/tests/test_cln_rs.py
@@ -370,6 +370,8 @@ def test_grpc_listpeerchannels(bitcoind, node_factory):
announce_channels=True, # Do not enforce scid-alias
)
+ wait_for_grpc_start(l1)
+
stub = l1.grpc
res = stub.ListPeerChannels(clnpb.ListpeerchannelsRequest(id=None))
@@ -419,6 +421,8 @@ def test_rust_plugin_subscribe_wildcard(node_factory):
def test_grpc_block_added_notifications(node_factory, bitcoind):
l1 = node_factory.get_node()
+ wait_for_grpc_start(l1)
+
# Test the block_added notification
# Start listening to block added events over grpc
block_added_stream = l1.grpc.SubscribeBlockAdded(clnpb.StreamBlockAddedRequest())
@@ -435,6 +439,8 @@ def test_grpc_block_added_notifications(node_factory, bitcoind):
def test_grpc_connect_notification(node_factory):
l1, l2 = node_factory.get_nodes(2)
+ wait_for_grpc_start(l1)
+
# Test the connect notification
connect_stream = l1.grpc.SubscribeConnect(clnpb.StreamConnectRequest())
@@ -451,6 +457,8 @@ def test_grpc_connect_notification(node_factory):
def test_grpc_custommsg_notification(node_factory):
l1, l2 = node_factory.get_nodes(2)
+ wait_for_grpc_start(l1)
+
# Test the connect notification
custommsg_stream = l1.grpc.SubscribeCustomMsg(clnpb.StreamCustomMsgRequest())
l2.connect(l1)
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.