tests: fix flaky test_bwatch_listwatch
What changed, and why it matters
This commit fixes a flaky automated test. It does not change production code or fix a security bug. The test was sometimes failing because it counted all 'watches' in a list, but the wallet also registers its own watches in the background, causing the total count to vary on slow machines. The fix makes the test count only the specific watches it creates, so it no longer races with background activity.
No security action needed; this is a test-only reliability fix.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change is confined to tests/test_plugin.py in test_bwatch_listwatch. It removes an initial baseline count of all watches and replaces total-count assertions with filtered counts that include only watches created by the test (identified by distinctive outpoints/scriptpubkey). This eliminates a race between the test’s assertions and asynchronous wallet scriptpubkey watch registration at node startup. No RPC behavior, watch logic, or production code is modified.
Changed components
tests/test_plugin.py::test_bwatch_listwatchInspect captured patch +13 / −7
diff --git a/tests/test_plugin.py b/tests/test_plugin.py
index ae74e172..911088b2 100644
--- a/tests/test_plugin.py
+++ b/tests/test_plugin.py
@@ -5848,9 +5848,6 @@ def test_bwatch_listwatch(node_factory, bitcoind):
"""Test that listwatch RPC returns all active watches"""
l1 = node_factory.get_node(options=BWATCH_OPTS)
- # Record the baseline — the wallet registers scriptpubkey watches on startup.
- initial_count = len(l1.rpc.listwatch()['watches'])
-
# Add an outpoint watch — clearly not a real UTXO.
test_outpoint_a_txid = "a" * 64
test_outpoint_a = f"{test_outpoint_a_txid}:0"
@@ -5868,11 +5865,20 @@ def test_bwatch_listwatch(node_factory, bitcoind):
# Add a second owner to the first outpoint watch
l1.rpc.addoutpointwatch(owner='wallet/p2tr/0', outpoint=test_outpoint_a, start_block=50)
+ # The wallet registers its own scriptpubkey watches at startup, and on a
+ # slow machine that registration can land at any point during the test,
+ # so a total-count baseline races it. Count only this test's watches,
+ # which no background registration can perturb.
+ def our_watches(watches):
+ return [w for w in watches
+ if w.get('outpoint') in (test_outpoint_a, test_outpoint_c)
+ or w.get('scriptpubkey') == test_scriptpubkey]
+
result = l1.rpc.listwatch()
watches = result['watches']
- # 3 new unique watches added on top of the wallet's initial set
- assert len(watches) == initial_count + 3
+ # 3 unique watches: the two adds for the same outpoint merged into one
+ assert len(our_watches(watches)) == 3
# Find each test watch by its unique identifier
outpoint_a_watch = next((w for w in watches if w.get('outpoint') == test_outpoint_a), None)
@@ -5902,7 +5908,7 @@ def test_bwatch_listwatch(node_factory, bitcoind):
l1.rpc.deloutpointwatch(owner='wallet/p2wpkh/0', outpoint=test_outpoint_a)
watches = l1.rpc.listwatch()['watches']
- assert len(watches) == initial_count + 3
+ assert len(our_watches(watches)) == 3
outpoint_a_watch = next(w for w in watches if w.get('outpoint') == test_outpoint_a)
assert len(outpoint_a_watch['owners']) == 1
assert outpoint_a_watch['owners'][0] == 'wallet/p2tr/0'
@@ -5911,7 +5917,7 @@ def test_bwatch_listwatch(node_factory, bitcoind):
l1.rpc.deloutpointwatch(owner='wallet/p2tr/0', outpoint=test_outpoint_a)
watches = l1.rpc.listwatch()['watches']
- assert len(watches) == initial_count + 2
+ assert len(our_watches(watches)) == 2
assert not any(w.get('outpoint') == test_outpoint_a for w in watches)
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.