Skip to content

tests: lnpeer: fix flaky test "hold_invoice_set_doesnt_get_expired"#10590

Merged
ecdsa merged 1 commit into
spesmilo:masterfrom
SomberNight:202604_test_lnpeer_flaky_hold_invoice_set
Apr 21, 2026
Merged

tests: lnpeer: fix flaky test "hold_invoice_set_doesnt_get_expired"#10590
ecdsa merged 1 commit into
spesmilo:masterfrom
SomberNight:202604_test_lnpeer_flaky_hold_invoice_set

Conversation

@SomberNight
Copy link
Copy Markdown
Member

@SomberNight SomberNight commented Apr 19, 2026

This test was flaky: the mpp_set resolution gets set to SETTLING several asyncio event loop iterations before the hold invoice callback "cb" gets called. If the 0.1 sec polling triggers just in the middle of that interval, assert cb_got_called fails.

    async def check_mpp_state():
        async def wait_for_resolution():
            while True:
                await asyncio.sleep(0.1)
                if payment_key not in bob_w.received_mpp_htlcs:
                    continue
                if not bob_w.received_mpp_htlcs[payment_key].resolution == RecvMPPResolution.SETTLING:
                    continue
                return
        await util.wait_for2(wait_for_resolution(), timeout=2)
>       assert cb_got_called
E       assert False

tests/test_lnpeer.py:1898: AssertionError

see

electrum/electrum/lnpeer.py

Lines 3136 to 3137 in 16c8cb5

self.lnworker.set_mpp_resolution(payment_key, RecvMPPResolution.SETTLING)
return None, None, callback

fixes #10589


diff to reproduce the failure without present patch:

diff --git a/tests/test_lnpeer.py b/tests/test_lnpeer.py
index https://github.com/SomberNight/electrum/commit/8669931c24fc5ba3015b272b83cfdf0a3c24f067..e15973d68f 100644
--- a/tests/test_lnpeer.py
+++ b/tests/test_lnpeer.py
@@ -1885,6 +1885,7 @@ class TestPeerDirect(TestPeer):
             cb_got_called = False
             async def cb(_payment_hash):
                 self.logger.debug(f"hold invoice callback called. {bob_w.network.get_local_height()=}")
+                await asyncio.sleep(1)
                 nonlocal cb_got_called
                 cb_got_called = True

This test was flaky: the mpp_set resolution gets set to SETTLING several asyncio event loop iterations before the hold invoice callback "cb" gets called.
If the 0.1 sec polling triggers just in the middle of that interval, `assert cb_got_called` fails.

```
    async def check_mpp_state():
        async def wait_for_resolution():
            while True:
                await asyncio.sleep(0.1)
                if payment_key not in bob_w.received_mpp_htlcs:
                    continue
                if not bob_w.received_mpp_htlcs[payment_key].resolution == RecvMPPResolution.SETTLING:
                    continue
                return
        await util.wait_for2(wait_for_resolution(), timeout=2)
>       assert cb_got_called
E       assert False

tests/test_lnpeer.py:1898: AssertionError
```

see https://github.com/spesmilo/electrum/blob/16c8cb50e38c274cce8f9f66f28d8dd453f9f074/electrum/lnpeer.py#L3136-L3137

fixes spesmilo#10589

-----

diff to reproduce the failure without present patch:
```
diff --git a/tests/test_lnpeer.py b/tests/test_lnpeer.py
index 8669931..e15973d68f 100644
--- a/tests/test_lnpeer.py
+++ b/tests/test_lnpeer.py
@@ -1885,6 +1885,7 @@ class TestPeerDirect(TestPeer):
             cb_got_called = False
             async def cb(_payment_hash):
                 self.logger.debug(f"hold invoice callback called. {bob_w.network.get_local_height()=}")
+                await asyncio.sleep(1)
                 nonlocal cb_got_called
                 cb_got_called = True
```
@SomberNight SomberNight force-pushed the 202604_test_lnpeer_flaky_hold_invoice_set branch from 9941381 to ca8bdba Compare April 19, 2026 15:24
@ecdsa ecdsa merged commit c189360 into spesmilo:master Apr 21, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test_hold_invoice_set_doesnt_get_expired on Debian forky

2 participants