pytest: Spawn a new bitcoind for each test

Since we seem to have some isolation concerns when re-generating the
same HSM secret and re-parsing the blockchain some blocks in the past.

This also alleviates the problem of printing to a logging stream that
has been closed. Previously bitcoind would keep running despite a test
had failed and continue logging to the, now closed, StringIO that
py.test uses when capturing stdout.

The performance impact seems to be 1-3 second per test, not too bad
IMHO for increased test isolation and cleaner logs:

|--------------------+---------------+----------|
|                    | No_valgrind   | Valgrind |
|--------------------+---------------+----------|
| bitcoind per suite | 10 min 24 sec | 46:15.31 |
| bitcoind per test  | 11 min 38 sec | 49:21.64 |
|--------------------+---------------+----------|

Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
Christian Decker 2018-01-05 15:20:43 +01:00 committed by Rusty Russell
parent 00e75d3d81
commit 55d2e4b1d0

View File

@ -35,9 +35,9 @@ logging.info("Tests running in '%s'", TEST_DIR)
def to_json(arg):
return json.loads(json.dumps(arg))
def setupBitcoind():
def setupBitcoind(directory):
global bitcoind
bitcoind = utils.BitcoinD(rpcport=28332)
bitcoind = utils.BitcoinD(bitcoin_dir=directory, rpcport=28332)
bitcoind.start()
info = bitcoind.rpc.getblockchaininfo()
# Make sure we have segwit and some funds
@ -70,14 +70,6 @@ def tearDownBitcoind():
bitcoind.proc.kill()
bitcoind.proc.wait()
def setUpModule():
setupBitcoind()
def tearDownModule():
tearDownBitcoind()
def breakpoint():
import pdb; pdb.set_trace()
@ -161,6 +153,8 @@ class NodeFactory(object):
class BaseLightningDTests(unittest.TestCase):
def setUp(self):
bitcoin_dir = os.path.join(TEST_DIR, self._testMethodName, "bitcoind")
setupBitcoind(bitcoin_dir)
# Most of the executor threads will be waiting for IO, so
# let's have a few of them
self.executor = futures.ThreadPoolExecutor(max_workers=20)
@ -208,6 +202,7 @@ class BaseLightningDTests(unittest.TestCase):
ok = self.node_factory.killall([not n.may_fail for n in self.node_factory.nodes])
self.executor.shutdown(wait=False)
tearDownBitcoind()
err_count = 0
# Do not check for valgrind error files if it is disabled
if VALGRIND:
@ -224,11 +219,6 @@ class BaseLightningDTests(unittest.TestCase):
if not ok:
raise Exception("At least one lightning exited with unexpected non-zero return code")
@classmethod
def tearDownClass(cls):
"""We need 100 blocks between runs, since otherwise they might see the txs from a previous run, and get very confused!"""
bitcoind.generate_block(100)
class LightningDTests(BaseLightningDTests):
def connect(self):
l1 = self.node_factory.get_node()