Skip to content

Commit 939aec3

Browse files
committed
pytest: make hold_timeout.py test plugin release on a prompt, not timeout.
Avoids guessing what the timeout should be, use a file trigger. This is more optimal, and should reduce a flake in test_sql under valgrind. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 1ad72fd commit 939aec3

3 files changed

Lines changed: 24 additions & 11 deletions

File tree

tests/plugins/hold_invoice.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33
"""
44

55
from pyln.client import Plugin
6+
import os
67
import time
78

89
plugin = Plugin()
910

1011

1112
@plugin.hook('invoice_payment')
1213
def on_payment(payment, plugin, **kwargs):
13-
time.sleep(float(plugin.get_option('holdtime')))
14+
# Block until file appears
15+
while not os.path.exists("unhold"):
16+
time.sleep(0.25)
1417
return {'result': 'continue'}
1518

1619

17-
plugin.add_option('holdtime', '10', 'The time to hold invoice for.')
1820
plugin.run()

tests/test_pay.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,7 +2667,7 @@ def test_setchannel_startup_opts(node_factory, bitcoind):
26672667
def test_channel_spendable(node_factory, bitcoind, anchors):
26682668
"""Test that spendable_msat is accurate"""
26692669
sats = 10**6
2670-
opts = {'plugin': os.path.join(os.getcwd(), 'tests/plugins/hold_invoice.py'), 'holdtime': '30'}
2670+
opts = {'plugin': os.path.join(os.getcwd(), 'tests/plugins/hold_invoice.py')}
26712671
if anchors is False:
26722672
opts['dev-force-features'] = "-23"
26732673
l1, l2 = node_factory.line_graph(2, fundamount=sats, wait_for_announce=True,
@@ -2693,6 +2693,8 @@ def test_channel_spendable(node_factory, bitcoind, anchors):
26932693
# hold_invoice.py plugin.
26942694
wait_for(lambda: len(l1.rpc.listpeerchannels()['channels'][0]['htlcs']) == 1)
26952695
assert l1.rpc.listpeerchannels()['channels'][0]['spendable_msat'] == Millisatoshi(0)
2696+
# Tell hold_invoice.py to release hold
2697+
open(os.path.join(l2.daemon.lightning_dir, TEST_NETWORK, "unhold"), "w").close()
26962698
l1.rpc.waitsendpay(payment_hash, TIMEOUT)
26972699

26982700
# Make sure l2 thinks it's all over.
@@ -2718,14 +2720,15 @@ def test_channel_spendable(node_factory, bitcoind, anchors):
27182720
# hold_invoice.py plugin.
27192721
wait_for(lambda: len(l2.rpc.listpeerchannels()['channels'][0]['htlcs']) == 1)
27202722
assert l2.rpc.listpeerchannels()['channels'][0]['spendable_msat'] == Millisatoshi(0)
2723+
open(os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, "unhold"), "w").close()
27212724
l2.rpc.waitsendpay(payment_hash, TIMEOUT)
27222725

27232726

27242727
def test_channel_receivable(node_factory, bitcoind):
27252728
"""Test that receivable_msat is accurate"""
27262729
sats = 10**6
27272730
l1, l2 = node_factory.line_graph(2, fundamount=sats, wait_for_announce=True,
2728-
opts={'plugin': os.path.join(os.getcwd(), 'tests/plugins/hold_invoice.py'), 'holdtime': '30'})
2731+
opts={'plugin': os.path.join(os.getcwd(), 'tests/plugins/hold_invoice.py')})
27292732

27302733
inv = l2.rpc.invoice('any', 'inv', 'for testing')
27312734
payment_hash = inv['payment_hash']
@@ -2747,6 +2750,7 @@ def test_channel_receivable(node_factory, bitcoind):
27472750
# hold_invoice.py plugin.
27482751
wait_for(lambda: len(l2.rpc.listpeerchannels()['channels'][0]['htlcs']) == 1)
27492752
assert l2.rpc.listpeerchannels()['channels'][0]['receivable_msat'] == Millisatoshi(0)
2753+
open(os.path.join(l2.daemon.lightning_dir, TEST_NETWORK, "unhold"), "w").close()
27502754
l1.rpc.waitsendpay(payment_hash, TIMEOUT)
27512755

27522756
# Make sure both think it's all over.
@@ -2773,6 +2777,7 @@ def test_channel_receivable(node_factory, bitcoind):
27732777
# hold_invoice.py plugin.
27742778
wait_for(lambda: len(l1.rpc.listpeerchannels()['channels'][0]['htlcs']) == 1)
27752779
assert l1.rpc.listpeerchannels()['channels'][0]['receivable_msat'] == Millisatoshi(0)
2780+
open(os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, "unhold"), "w").close()
27762781
l2.rpc.waitsendpay(payment_hash, TIMEOUT)
27772782

27782783

@@ -2786,7 +2791,6 @@ def test_channel_spendable_large(node_factory, bitcoind):
27862791
wait_for_announce=True,
27872792
opts={
27882793
'plugin': os.path.join(os.getcwd(), 'tests/plugins/hold_invoice.py'),
2789-
'holdtime': '30'
27902794
}
27912795
)
27922796

@@ -2809,6 +2813,7 @@ def test_channel_spendable_large(node_factory, bitcoind):
28092813
# Exact amount should succeed.
28102814
route = l1.rpc.getroute(l2.info['id'], spendable, riskfactor=1, fuzzpercent=0)['route']
28112815
l1.rpc.sendpay(route, payment_hash, payment_secret=inv['payment_secret'])
2816+
open(os.path.join(l2.daemon.lightning_dir, TEST_NETWORK, "unhold"), "w").close()
28122817
l1.rpc.waitsendpay(payment_hash, TIMEOUT)
28132818

28142819

tests/test_plugin.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import ast
1818
import copy
1919
import json
20-
import math
2120
import os
2221
import pytest
2322
import random
@@ -663,14 +662,21 @@ def test_invoice_payment_hook(node_factory):
663662
l2.daemon.wait_for_log('preimage=' + '0' * 64)
664663

665664

666-
def test_invoice_payment_hook_hold(node_factory):
665+
def test_invoice_payment_hook_hold(node_factory, executor):
667666
""" l1 uses the hold_invoice plugin to delay invoice payment.
668667
"""
669-
opts = [{}, {'plugin': os.path.join(os.getcwd(), 'tests/plugins/hold_invoice.py'), 'holdtime': TIMEOUT / 2}]
668+
opts = [{}, {'plugin': os.path.join(os.getcwd(), 'tests/plugins/hold_invoice.py')}]
670669
l1, l2 = node_factory.line_graph(2, opts=opts)
671670

672671
inv1 = l2.rpc.invoice(1230, 'label', 'description', preimage='1' * 64)
673-
l1.rpc.pay(inv1['bolt11'])
672+
673+
# This should block.
674+
f = executor.submit(l1.rpc.pay, inv1['bolt11'])
675+
time.sleep(5)
676+
assert not f.done()
677+
678+
open(os.path.join(l2.daemon.lightning_dir, TEST_NETWORK, "unhold"), "w").close()
679+
f.result(TIMEOUT)
674680

675681

676682
@pytest.mark.openchannel('v1')
@@ -4034,8 +4040,7 @@ def test_sql(node_factory, bitcoind):
40344040
l2.rpc.pay(l3.rpc.invoice(amount_msat=12300, label='inv2', description='description')['bolt11'])
40354041

40364042
# And I need at least one HTLC in-flight so listpeers.channels.htlcs isn't empty:
4037-
l3.rpc.plugin_start(os.path.join(os.getcwd(), 'tests/plugins/hold_invoice.py'),
4038-
holdtime=int(math.sqrt(TIMEOUT) + 1) * 2)
4043+
l3.rpc.plugin_start(os.path.join(os.getcwd(), 'tests/plugins/hold_invoice.py'))
40394044
inv = l3.rpc.invoice(amount_msat=12300, label='inv3', description='description')
40404045
route = l1.rpc.getroute(l3.info['id'], 12300, 1)['route']
40414046
l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret'])
@@ -4103,6 +4108,7 @@ def test_sql(node_factory, bitcoind):
41034108
l3.daemon.wait_for_log("Refreshing channel: {}".format(scid))
41044109

41054110
# This has to wait for the hold_invoice plugin to let go!
4111+
open(os.path.join(l3.daemon.lightning_dir, TEST_NETWORK, "unhold"), "w").close()
41064112
txid = only_one(l1.rpc.close(l2.info['id'])['txids'])
41074113
bitcoind.generate_block(13, wait_for_mempool=txid)
41084114
wait_for(lambda: len(l3.rpc.listchannels(source=l1.info['id'])['channels']) == 0)

0 commit comments

Comments
 (0)