Skip to content

Commit

Permalink
tests/test_lightningd.py: incorporate everything from old test-basic …
Browse files Browse the repository at this point in the history
…shell test.

This moves all the non-legacy blackbox testing into python.

Before:
	real	10m18.385s

After:
	real	9m54.877s

Note that this doesn't valgrind the subdaemons: that patch seems to cause
some issues in the python framework which I am still chasing.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell authored and cdecker committed Apr 29, 2017
1 parent be3b5f1 commit f61da7e
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 150 deletions.
3 changes: 0 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,7 @@ $(HELPER_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(CORE_PROTOBUF_OBJS) $(BITCOIN_OBJS
test-protocol: test/test_protocol
set -e; TMP=`mktemp`; for f in test/commits/*.script; do if ! $(VALGRIND) test/test_protocol < $$f > $$TMP; then echo "test/test_protocol < $$f FAILED" >&2; exit 1; fi; diff -u $$TMP $$f.expected; done; rm $$TMP

# FIXME: check doesn't depend on lightningd-blackbox-tests, since they
# can't run in parallel with daemon blackbox tests.
check: test-protocol
$(MAKE) lightningd-blackbox-tests
$(MAKE) pytest

pytest: daemon/lightningd daemon/lightning-cli lightningd-all
Expand Down
5 changes: 4 additions & 1 deletion lightningd/pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,11 @@ void payment_succeeded(struct lightningd *ld, struct htlc_end *dst,
const struct preimage *rval)
{
/* FIXME: dev_htlc will do this! */
if (!dst->pay_command)
if (!dst->pay_command) {
log_debug(ld->log, "Payment succeeded on HTLC %"PRIu64,
dst->htlc_id);
return;
}

assert(!dst->pay_command->rval);
dst->pay_command->rval = tal_dup(dst->pay_command,
Expand Down
20 changes: 0 additions & 20 deletions lightningd/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,5 @@ $(LIGHTNINGD_TEST_OBJS): $(LIGHTNINGD_HEADERS) $(LIGHTNINGD_SRC) $(LIGHTNINGD_LI

lightningd/tests: $(LIGHTNINGD_TEST_PROGRAMS:%=unittest/%)

# So far, only basic test.
lightningd-test-0-basic: lightningd-test-setup-0

lightningd-test-0-%:
NO_VALGRIND=$(NO_VALGRIND) VG_TRACE_CHILDREN="--trace-children=yes" VARIANT=0 lightningd/test/test-$*

# We shutdown first in case something is left over.
lightningd-test-setup-%: lightningd-all daemon/lightning-cli
VARIANT=$* daemon/test/scripts/shutdown.sh 2>/dev/null || true
VARIANT=$* daemon/test/scripts/setup.sh

lightningd-test-shutdown-0: lightningd-test-0-basic
VARIANT=0 daemon/test/scripts/shutdown.sh
lightningd-test-shutdown-1: lightningd-test-1-basic\ --restart
VARIANT=1 daemon/test/scripts/shutdown.sh
lightningd-test-shutdown-2: lightningd-test-2-basic\ --reconnect
VARIANT=2 daemon/test/scripts/shutdown.sh

lightningd-blackbox-tests: lightningd-test-shutdown-0 #lightningd-test-shutdown-1 lightningd-test-shutdown-2

check-source-bolt: $(LIGHTNINGD_TEST_SRC:%=bolt-check/%)
check-whitespace: $(LIGHTNINGD_TEST_SRC:%=check-whitespace/%)
123 changes: 0 additions & 123 deletions lightningd/test/test-basic

This file was deleted.

108 changes: 106 additions & 2 deletions tests/test_lightningd.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from hashlib import sha256
from lightning import LightningRpc, LegacyLightningRpc

import copy
import json
import logging
import os
import sys
Expand All @@ -19,6 +21,8 @@
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
logging.info("Tests running in '%s'", TEST_DIR)

def to_json(arg):
return json.loads(json.dumps(arg))

def setupBitcoind():
global bitcoind
Expand Down Expand Up @@ -138,12 +142,112 @@ def fund_channel(self,l1,l2,amount):
def test_connect(self):
l1,l2 = self.connect()

p1 = l1.rpc.getpeer(l2.info['id'])
p2 = l2.rpc.getpeer(l1.info['id'])
p1 = l1.rpc.getpeer(l2.info['id'], 'info')
p2 = l2.rpc.getpeer(l1.info['id'], 'info')

assert p1['condition'] == 'Exchanging gossip'
assert p2['condition'] == 'Exchanging gossip'

# It should have gone through these steps
assert 'condition: Starting handshake as initiator' in p1['log']
assert 'condition: Beginning gossip' in p1['log']
assert 'condition: Exchanging gossip' in p1['log']

# Both should still be owned by gossip
assert p1['owner'] == 'lightningd_gossip'
assert p2['owner'] == 'lightningd_gossip'

def test_htlc(self):
l1,l2 = self.connect()

self.fund_channel(l1, l2, 10**6)
l1.daemon.wait_for_log('condition: Funding tx reached depth 6')
l2.daemon.wait_for_log('condition: Funding tx reached depth 6')

secret = '1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd'
rhash = l1.rpc.dev_rhash(secret)['rhash']

# This is actually dust, and uncalled for.
l1.rpc.dev_newhtlc(l2.info['id'], 100000, l1.bitcoin.rpc.getblockcount() + 10, rhash)
l1.daemon.wait_for_log('Sending commit_sig with 0 htlc sigs')
l2.daemon.wait_for_log('their htlc 0 locked')
l2.daemon.wait_for_log('failed htlc 0 code 0x400f')
l1.daemon.wait_for_log('htlc 0 failed with code 0x400f')

# Set up invoice (non-dust, just to test), and pay it.
# This one isn't dust.
rhash = l2.rpc.invoice(100000000, 'testpayment1')['rhash']
assert l2.rpc.listinvoice('testpayment1')[0]['complete'] == False

l1.rpc.dev_newhtlc(l2.info['id'], 100000000, l1.bitcoin.rpc.getblockcount() + 10, rhash)
l1.daemon.wait_for_log('Sending commit_sig with 1 htlc sigs')
l2.daemon.wait_for_log('their htlc 1 locked')
l2.daemon.wait_for_log("Resolving invoice 'testpayment1' with HTLC 1")
assert l2.rpc.listinvoice('testpayment1')[0]['complete'] == True
l1.daemon.wait_for_log('Payment succeeded on HTLC 1')

# Balances should have changed.
p1 = l1.rpc.getpeer(l2.info['id'])
p2 = l2.rpc.getpeer(l1.info['id'])
assert p1['msatoshi_to_us'] == 900000000
assert p1['msatoshi_to_them'] == 100000000
assert p2['msatoshi_to_us'] == 100000000
assert p2['msatoshi_to_them'] == 900000000

def test_sendpay(self):
l1,l2 = self.connect()

self.fund_channel(l1, l2, 10**6)

amt = 200000000
rhash = l2.rpc.invoice(amt, 'testpayment2')['rhash']
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == False

routestep = { 'msatoshi' : amt, 'id' : l2.info['id'], 'delay' : 5}

# Insufficient funds.
rs = copy.deepcopy(routestep)
rs['msatoshi'] = rs['msatoshi'] - 1
self.assertRaises(ValueError, l1.rpc.sendpay, to_json([rs]), rhash)
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == False

# Gross overpayment (more than factor of 2)
rs = copy.deepcopy(routestep)
rs['msatoshi'] = rs['msatoshi'] * 2 + 1
self.assertRaises(ValueError, l1.rpc.sendpay, to_json([rs]), rhash)
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == False

# Insufficient delay.
rs = copy.deepcopy(routestep)
rs['delay'] = rs['delay'] - 2
self.assertRaises(ValueError, l1.rpc.sendpay, to_json([rs]), rhash)
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == False

# Bad ID.
rs = copy.deepcopy(routestep)
rs['id'] = '00000000000000000000000000000000'
self.assertRaises(ValueError, l1.rpc.sendpay, to_json([rs]), rhash)
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == False

# This works.
l1.rpc.sendpay(to_json([routestep]), rhash)
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == True

# Repeat will "succeed", but won't actually send anything (duplicate)
assert not l1.daemon.is_in_log('... succeeded')
l1.rpc.sendpay(to_json([routestep]), rhash)
l1.daemon.wait_for_log('... succeeded')
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == True

# Overpaying by "only" a factor of 2 succeeds.
rhash = l2.rpc.invoice(amt, 'testpayment3')['rhash']
assert l2.rpc.listinvoice('testpayment3')[0]['complete'] == False
routestep = { 'msatoshi' : amt * 2, 'id' : l2.info['id'], 'delay' : 5}
l1.rpc.sendpay(to_json([routestep]), rhash)
assert l2.rpc.listinvoice('testpayment3')[0]['complete'] == True

# FIXME: test paying via another node, should fail to pay twice.

def test_gossip_jsonrpc(self):
l1,l2 = self.connect()

Expand Down
14 changes: 13 additions & 1 deletion tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,19 @@ def tail(self):
logging.debug("%s: %s", self.prefix, line.decode().rstrip())
self.logs_cond.notifyAll()
self.running = False


def is_in_log(self, regex):
"""Look for `regex` in the logs."""

ex = re.compile(regex)
for l in self.logs:
if ex.search(l):
logging.debug("Found '%s' in logs", regex)
return True

logging.debug("Did not find '%s' in logs", regex)
return False

def wait_for_log(self, regex, offset=1000, timeout=60):
"""Look for `regex` in the logs.
Expand Down

0 comments on commit f61da7e

Please sign in to comment.