aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/abandonconflict.py9
-rwxr-xr-xtest/functional/disablewallet.py2
-rwxr-xr-xtest/functional/import-abort-rescan.py66
-rwxr-xr-xtest/functional/mempool_persist.py90
-rwxr-xr-xtest/functional/p2p-segwit.py21
-rwxr-xr-xtest/functional/sendheaders.py16
-rw-r--r--test/functional/test_framework/authproxy.py7
-rwxr-xr-xtest/functional/test_framework/mininode.py9
-rwxr-xr-xtest/functional/test_framework/test_framework.py215
-rw-r--r--test/functional/test_framework/util.py81
-rwxr-xr-xtest/functional/test_runner.py7
-rwxr-xr-xtest/functional/zmq_test.py4
12 files changed, 304 insertions, 223 deletions
diff --git a/test/functional/abandonconflict.py b/test/functional/abandonconflict.py
index 0439d168de..9748757641 100755
--- a/test/functional/abandonconflict.py
+++ b/test/functional/abandonconflict.py
@@ -10,10 +10,8 @@
which are not included in a block and are not currently in the mempool. It has
no effect on transactions which are already conflicted or abandoned.
"""
-
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import urllib.parse
class AbandonConflictTest(BitcoinTestFramework):
def __init__(self):
@@ -37,8 +35,8 @@ class AbandonConflictTest(BitcoinTestFramework):
assert(balance - newbalance < Decimal("0.001")) #no more than fees lost
balance = newbalance
- url = urllib.parse.urlparse(self.nodes[1].url)
- self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1)))
+ # Disconnect nodes so node0's transactions don't get into node1's mempool
+ disconnect_nodes(self.nodes[0], 1)
# Identify the 10btc outputs
nA = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txA, 1)["vout"]) if vout["value"] == Decimal("10"))
@@ -78,8 +76,9 @@ class AbandonConflictTest(BitcoinTestFramework):
stop_node(self.nodes[0],0)
self.nodes[0]=start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"])
- # Verify txs no longer in mempool
+ # Verify txs no longer in either node's mempool
assert_equal(len(self.nodes[0].getrawmempool()), 0)
+ assert_equal(len(self.nodes[1].getrawmempool()), 0)
# Not in mempool txs from self should only reduce balance
# inputs are still spent, but change not received
diff --git a/test/functional/disablewallet.py b/test/functional/disablewallet.py
index 3f77a1828d..d344513414 100755
--- a/test/functional/disablewallet.py
+++ b/test/functional/disablewallet.py
@@ -21,6 +21,8 @@ class DisableWalletTest (BitcoinTestFramework):
self.extra_args = [["-disablewallet"]]
def run_test (self):
+ # Make sure wallet is really disabled
+ assert_raises_jsonrpc(-32601, 'Method not found', self.nodes[0].getwalletinfo)
x = self.nodes[0].validateaddress('3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy')
assert(x['isvalid'] == False)
x = self.nodes[0].validateaddress('mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ')
diff --git a/test/functional/import-abort-rescan.py b/test/functional/import-abort-rescan.py
deleted file mode 100755
index ffe45bbb1d..0000000000
--- a/test/functional/import-abort-rescan.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2017 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Test wallet import RPCs.
-
-Test rescan behavior of importprivkey when aborted. The test ensures that:
-1. The abortrescan command indeed stops the rescan process.
-2. Subsequent rescan catches the aborted address UTXO
-"""
-
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import (assert_equal, get_rpc_proxy)
-from decimal import Decimal
-import threading # for bg importprivkey
-import time # for sleep
-
-class ImportAbortRescanTest(BitcoinTestFramework):
- def __init__(self):
- super().__init__()
- self.setup_clean_chain = True
-
- def run_test(self):
- # Generate for BTC
- assert_equal(self.nodes[0].getbalance(), 0)
- assert_equal(self.nodes[1].getbalance(), 0)
- self.nodes[0].generate(300)
- assert_equal(self.nodes[1].getbalance(), 0)
- # Make blocks with spam to cause rescan delay
- for i in range(5):
- for j in range(5):
- self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.1)
- self.nodes[0].generate(10)
- addr = self.nodes[0].getnewaddress()
- privkey = self.nodes[0].dumpprivkey(addr)
- self.nodes[0].sendtoaddress(addr, 0.123)
- self.nodes[0].generate(10) # mature tx
- self.sync_all()
-
- # Import this address in the background ...
- node1ref = get_rpc_proxy(self.nodes[1].url, 1, timeout=600)
- importthread = threading.Thread(target=node1ref.importprivkey, args=[privkey])
- importthread.start()
- # ... then abort rescan; try a bunch until abortres becomes true,
- # because we will start checking before above thread starts processing
- for i in range(2000):
- time.sleep(0.001)
- abortres = self.nodes[1].abortrescan()
- if abortres: break
- assert abortres # if false, we failed to abort
- # import should die soon
- for i in range(10):
- time.sleep(0.1)
- deadres = not importthread.isAlive()
- if deadres: break
-
- assert deadres # if false, importthread did not die soon enough
- assert_equal(self.nodes[1].getbalance(), 0.0)
-
- # Import a different address and let it run
- self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress()))
- # Expect original privkey to now also be discovered and added to balance
- assert_equal(self.nodes[1].getbalance(), Decimal("0.123"))
-
-if __name__ == "__main__":
- ImportAbortRescanTest().main()
diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py
new file mode 100755
index 0000000000..7b15476ea2
--- /dev/null
+++ b/test/functional/mempool_persist.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+# Copyright (c) 2014-2017 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test mempool persistence.
+
+By default, bitcoind will dump mempool on shutdown and
+then reload it on startup. This can be overridden with
+the -persistmempool=0 command line option.
+
+Test is as follows:
+
+ - start node0, node1 and node2. node1 has -persistmempool=0
+ - create 5 transactions on node2 to its own address. Note that these
+ are not sent to node0 or node1 addresses because we don't want
+ them to be saved in the wallet.
+ - check that node0 and node1 have 5 transactions in their mempools
+ - shutdown all nodes.
+ - startup node0. Verify that it still has 5 transactions
+ in its mempool. Shutdown node0. This tests that by default the
+ mempool is persistent.
+ - startup node1. Verify that its mempool is empty. Shutdown node1.
+ This tests that with -persistmempool=0, the mempool is not
+ dumped to disk when the node is shut down.
+ - Restart node0 with -persistmempool=0. Verify that its mempool is
+ empty. Shutdown node0. This tests that with -persistmempool=0,
+ the mempool is not loaded from disk on start up.
+ - Restart node0 with -persistmempool. Verify that it has 5
+ transactions in its mempool. This tests that -persistmempool=0
+ does not overwrite a previously valid mempool stored on disk.
+
+"""
+import time
+
+from test_framework.mininode import wait_until
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+
+class MempoolPersistTest(BitcoinTestFramework):
+
+ def __init__(self):
+ super().__init__()
+ # We need 3 nodes for this test. Node1 does not have a persistent mempool.
+ self.num_nodes = 3
+ self.setup_clean_chain = False
+ self.extra_args = [[], ["-persistmempool=0"], []]
+
+ def run_test(self):
+ chain_height = self.nodes[0].getblockcount()
+ assert_equal(chain_height, 200)
+
+ self.log.debug("Mine a single block to get out of IBD")
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ self.log.debug("Send 5 transactions from node2 (to its own address)")
+ for i in range(5):
+ self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("10"))
+ self.sync_all()
+
+ self.log.debug("Verify that node0 and node1 have 5 transactions in their mempools")
+ assert_equal(len(self.nodes[0].getrawmempool()), 5)
+ assert_equal(len(self.nodes[1].getrawmempool()), 5)
+
+ self.log.debug("Stop-start node0 and node1. Verify that node0 has the transactions in its mempool and node1 does not.")
+ stop_nodes(self.nodes)
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir))
+ self.nodes.append(start_node(1, self.options.tmpdir))
+ # Give bitcoind a second to reload the mempool
+ time.sleep(1)
+ assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5)
+ assert_equal(len(self.nodes[1].getrawmempool()), 0)
+
+ self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.")
+ stop_nodes(self.nodes)
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-persistmempool=0"]))
+ # Give bitcoind a second to reload the mempool
+ time.sleep(1)
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
+
+ self.log.debug("Stop-start node0. Verify that it has the transactions in its mempool.")
+ stop_nodes(self.nodes)
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir))
+ assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5)
+
+if __name__ == '__main__':
+ MempoolPersistTest().main()
diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p-segwit.py
index 335777b2ab..24d4d37c42 100755
--- a/test/functional/p2p-segwit.py
+++ b/test/functional/p2p-segwit.py
@@ -61,16 +61,6 @@ class TestNode(NodeConnCB):
self.send_message(msg)
self.wait_for_getdata()
- def announce_block(self, block, use_header):
- with mininode_lock:
- self.last_message.pop("getdata", None)
- if use_header:
- msg = msg_headers()
- msg.headers = [ CBlockHeader(block) ]
- self.send_message(msg)
- else:
- self.send_message(msg_inv(inv=[CInv(2, block.sha256)]))
-
def request_block(self, blockhash, inv_type, timeout=60):
with mininode_lock:
self.last_message.pop("block", None)
@@ -926,9 +916,9 @@ class SegWitTest(BitcoinTestFramework):
tx3.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ]
# Also check that old_node gets a tx announcement, even though this is
# a witness transaction.
- self.old_node.wait_for_inv(CInv(1, tx2.sha256)) # wait until tx2 was inv'ed
+ self.old_node.wait_for_inv([CInv(1, tx2.sha256)]) # wait until tx2 was inv'ed
self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True)
- self.old_node.wait_for_inv(CInv(1, tx3.sha256))
+ self.old_node.wait_for_inv([CInv(1, tx3.sha256)])
# Test that getrawtransaction returns correct witness information
# hash, size, vsize
@@ -1029,13 +1019,18 @@ class SegWitTest(BitcoinTestFramework):
block4 = self.build_next_block(nVersion=4)
block4.solve()
self.old_node.getdataset = set()
+
# Blocks can be requested via direct-fetch (immediately upon processing the announcement)
# or via parallel download (with an indeterminate delay from processing the announcement)
# so to test that a block is NOT requested, we could guess a time period to sleep for,
# and then check. We can avoid the sleep() by taking advantage of transaction getdata's
# being processed after block getdata's, and announce a transaction as well,
# and then check to see if that particular getdata has been received.
- self.old_node.announce_block(block4, use_header=False)
+ # Since 0.14, inv's will only be responded to with a getheaders, so send a header
+ # to announce this block.
+ msg = msg_headers()
+ msg.headers = [ CBlockHeader(block4) ]
+ self.old_node.send_message(msg)
self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0])
assert(block4.sha256 not in self.old_node.getdataset)
diff --git a/test/functional/sendheaders.py b/test/functional/sendheaders.py
index 97d64c0d98..44c357c6db 100755
--- a/test/functional/sendheaders.py
+++ b/test/functional/sendheaders.py
@@ -243,7 +243,7 @@ class SendHeadersTest(BitcoinTestFramework):
if i == 0:
# first request the block
test_node.get_data([tip])
- test_node.wait_for_block(tip, timeout=5)
+ test_node.wait_for_block(tip)
elif i == 1:
# next try requesting header and block
test_node.get_headers(locator=[old_tip], hashstop=tip)
@@ -258,7 +258,7 @@ class SendHeadersTest(BitcoinTestFramework):
new_block = create_block(tip, create_coinbase(height+1), block_time)
new_block.solve()
test_node.send_header_for_blocks([new_block])
- test_node.wait_for_getdata([new_block.sha256], timeout=5)
+ test_node.wait_for_getdata([new_block.sha256])
test_node.send_message(msg_block(new_block))
test_node.sync_with_ping() # make sure this block is processed
inv_node.clear_last_announcement()
@@ -297,18 +297,18 @@ class SendHeadersTest(BitcoinTestFramework):
if j == 0:
# Announce via inv
test_node.send_block_inv(tip)
- test_node.wait_for_getheaders(timeout=5)
+ test_node.wait_for_getheaders()
# Should have received a getheaders now
test_node.send_header_for_blocks(blocks)
# Test that duplicate inv's won't result in duplicate
# getdata requests, or duplicate headers announcements
[ inv_node.send_block_inv(x.sha256) for x in blocks ]
- test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=5)
+ test_node.wait_for_getdata([x.sha256 for x in blocks])
inv_node.sync_with_ping()
else:
# Announce via headers
test_node.send_header_for_blocks(blocks)
- test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=5)
+ test_node.wait_for_getdata([x.sha256 for x in blocks])
# Test that duplicate headers won't result in duplicate
# getdata requests (the check is further down)
inv_node.send_header_for_blocks(blocks)
@@ -495,7 +495,7 @@ class SendHeadersTest(BitcoinTestFramework):
with mininode_lock:
test_node.last_message.pop("getheaders", None)
test_node.send_header_for_blocks([blocks[1]])
- test_node.wait_for_getheaders(timeout=1)
+ test_node.wait_for_getheaders()
test_node.send_header_for_blocks(blocks)
test_node.wait_for_getdata([x.sha256 for x in blocks])
[ test_node.send_message(msg_block(x)) for x in blocks ]
@@ -518,7 +518,7 @@ class SendHeadersTest(BitcoinTestFramework):
with mininode_lock:
test_node.last_message.pop("getheaders", None)
test_node.send_header_for_blocks([blocks[i]])
- test_node.wait_for_getheaders(timeout=1)
+ test_node.wait_for_getheaders()
# Next header will connect, should re-set our count:
test_node.send_header_for_blocks([blocks[0]])
@@ -533,7 +533,7 @@ class SendHeadersTest(BitcoinTestFramework):
with mininode_lock:
test_node.last_message.pop("getheaders", None)
test_node.send_header_for_blocks([blocks[i%len(blocks)]])
- test_node.wait_for_getheaders(timeout=1)
+ test_node.wait_for_getheaders()
# Eventually this stops working.
test_node.send_header_for_blocks([blocks[-1]])
diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py
index 9ab3094b06..dfcc524313 100644
--- a/test/functional/test_framework/authproxy.py
+++ b/test/functional/test_framework/authproxy.py
@@ -42,6 +42,7 @@ import decimal
import json
import logging
import socket
+import time
try:
import urllib.parse as urlparse
except ImportError:
@@ -163,6 +164,7 @@ class AuthServiceProxy(object):
return self._request('POST', self.__url.path, postdata.encode('utf-8'))
def _get_response(self):
+ req_start_time = time.time()
try:
http_response = self.__conn.getresponse()
except socket.timeout as e:
@@ -183,8 +185,9 @@ class AuthServiceProxy(object):
responsedata = http_response.read().decode('utf8')
response = json.loads(responsedata, parse_float=decimal.Decimal)
+ elapsed = time.time() - req_start_time
if "error" in response and response["error"] is None:
- log.debug("<-%s- %s"%(response["id"], json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii)))
+ log.debug("<-%s- [%.6f] %s"%(response["id"], elapsed, json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii)))
else:
- log.debug("<-- "+responsedata)
+ log.debug("<-- [%.6f] %s"%(elapsed,responsedata))
return response
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index 03db0d1092..fb3ed1473a 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -1358,6 +1358,8 @@ class msg_reject(object):
# Helper function
def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf')):
+ if attempts == float('inf') and timeout == float('inf'):
+ timeout = 60
attempt = 0
elapsed = 0
@@ -1604,7 +1606,12 @@ class NodeConnCB(object):
assert wait_until(test_function, timeout=timeout)
def wait_for_inv(self, expected_inv, timeout=60):
- test_function = lambda: self.last_message.get("inv") and self.last_message["inv"] != expected_inv
+ """Waits for an INV message and checks that the first inv object in the message was as expected."""
+ if len(expected_inv) > 1:
+ raise NotImplementedError("wait_for_inv() will only verify the first inv object")
+ test_function = lambda: self.last_message.get("inv") and \
+ self.last_message["inv"].inv[0].type == expected_inv[0].type and \
+ self.last_message["inv"].inv[0].hash == expected_inv[0].hash
assert wait_until(test_function, timeout=timeout)
def wait_for_verack(self, timeout=60):
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index e912dcbaff..8d8139e4e4 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -8,28 +8,55 @@ from collections import deque
import logging
import optparse
import os
-import sys
import shutil
+import subprocess
+import sys
import tempfile
import time
from .util import (
- initialize_chain,
- start_nodes,
+ PortSeed,
+ MAX_NODES,
+ bitcoind_processes,
+ check_json_precision,
connect_nodes_bi,
+ disable_mocktime,
disconnect_nodes,
+ enable_coverage,
+ enable_mocktime,
+ get_mocktime,
+ get_rpc_proxy,
+ initialize_datadir,
+ log_filename,
+ p2p_port,
+ rpc_url,
+ set_node_times,
+ start_node,
+ start_nodes,
+ stop_node,
+ stop_nodes,
sync_blocks,
sync_mempools,
- stop_nodes,
- stop_node,
- enable_coverage,
- check_json_precision,
- initialize_chain_clean,
- PortSeed,
+ wait_for_bitcoind_start,
)
from .authproxy import JSONRPCException
class BitcoinTestFramework(object):
+ """Base class for a bitcoin test script.
+
+ Individual bitcoin test scripts should subclass this class and override the following methods:
+
+ - __init__()
+ - add_options()
+ - setup_chain()
+ - setup_network()
+ - run_test()
+
+ The main() method should not be overridden.
+
+ This class also contains various public and private helper methods."""
+
+ # Methods to override in subclass test scripts.
TEST_EXIT_PASSED = 0
TEST_EXIT_FAILED = 1
@@ -40,27 +67,15 @@ class BitcoinTestFramework(object):
self.setup_clean_chain = False
self.nodes = None
- def run_test(self):
- raise NotImplementedError
-
def add_options(self, parser):
pass
def setup_chain(self):
self.log.info("Initializing test directory "+self.options.tmpdir)
if self.setup_clean_chain:
- initialize_chain_clean(self.options.tmpdir, self.num_nodes)
+ self._initialize_chain_clean(self.options.tmpdir, self.num_nodes)
else:
- initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir)
-
- def stop_node(self, num_node):
- stop_node(self.nodes[num_node], num_node)
-
- def setup_nodes(self):
- extra_args = None
- if hasattr(self, "extra_args"):
- extra_args = self.extra_args
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args)
+ self._initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir)
def setup_network(self):
self.setup_nodes()
@@ -72,27 +87,16 @@ class BitcoinTestFramework(object):
connect_nodes_bi(self.nodes, i, i + 1)
self.sync_all()
- def split_network(self):
- """
- Split the network of four nodes into nodes 0/1 and 2/3.
- """
- disconnect_nodes(self.nodes[1], 2)
- disconnect_nodes(self.nodes[2], 1)
- self.sync_all([self.nodes[:2], self.nodes[2:]])
-
- def sync_all(self, node_groups=None):
- if not node_groups:
- node_groups = [self.nodes]
+ def setup_nodes(self):
+ extra_args = None
+ if hasattr(self, "extra_args"):
+ extra_args = self.extra_args
+ self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args)
- [sync_blocks(group) for group in node_groups]
- [sync_mempools(group) for group in node_groups]
+ def run_test(self):
+ raise NotImplementedError
- def join_network(self):
- """
- Join the (previously split) network halves together.
- """
- connect_nodes_bi(self.nodes, 1, 2)
- self.sync_all()
+ # Main function. This should not be overridden by the subclass test scripts.
def main(self):
@@ -115,6 +119,8 @@ class BitcoinTestFramework(object):
help="The seed to use for assigning port numbers (default: current process id)")
parser.add_option("--coveragedir", dest="coveragedir",
help="Write tested RPC commands into this directory")
+ parser.add_option("--configfile", dest="configfile",
+ help="Location of the test framework config file")
self.add_options(parser)
(self.options, self.args) = parser.parse_args()
@@ -154,7 +160,7 @@ class BitcoinTestFramework(object):
if not self.options.noshutdown:
self.log.info("Stopping nodes")
- stop_nodes(self.nodes)
+ self.stop_nodes()
else:
self.log.info("Note: bitcoinds were not stopped and may still be running")
@@ -188,6 +194,45 @@ class BitcoinTestFramework(object):
logging.shutdown()
sys.exit(self.TEST_EXIT_FAILED)
+ # Public helper methods. These can be accessed by the subclass test scripts.
+
+ def start_node(self, i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None):
+ return start_node(i, dirname, extra_args, rpchost, timewait, binary, stderr)
+
+ def start_nodes(self, num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None):
+ return start_nodes(num_nodes, dirname, extra_args, rpchost, timewait, binary)
+
+ def stop_node(self, num_node):
+ stop_node(self.nodes[num_node], num_node)
+
+ def stop_nodes(self):
+ stop_nodes(self.nodes)
+
+ def split_network(self):
+ """
+ Split the network of four nodes into nodes 0/1 and 2/3.
+ """
+ disconnect_nodes(self.nodes[1], 2)
+ disconnect_nodes(self.nodes[2], 1)
+ self.sync_all([self.nodes[:2], self.nodes[2:]])
+
+ def join_network(self):
+ """
+ Join the (previously split) network halves together.
+ """
+ connect_nodes_bi(self.nodes, 1, 2)
+ self.sync_all()
+
+ def sync_all(self, node_groups=None):
+ if not node_groups:
+ node_groups = [self.nodes]
+
+ for group in node_groups:
+ sync_blocks(group)
+ sync_mempools(group)
+
+ # Private helper methods. These should not be accessed by the subclass test scripts.
+
def _start_logging(self):
# Add logger and logging handlers
self.log = logging.getLogger('TestFramework')
@@ -216,6 +261,88 @@ class BitcoinTestFramework(object):
rpc_handler.setLevel(logging.DEBUG)
rpc_logger.addHandler(rpc_handler)
+ def _initialize_chain(self, test_dir, num_nodes, cachedir):
+ """Initialize a pre-mined blockchain for use by the test.
+
+ Create a cache of a 200-block-long chain (with wallet) for MAX_NODES
+ Afterward, create num_nodes copies from the cache."""
+
+ assert num_nodes <= MAX_NODES
+ create_cache = False
+ for i in range(MAX_NODES):
+ if not os.path.isdir(os.path.join(cachedir, 'node' + str(i))):
+ create_cache = True
+ break
+
+ if create_cache:
+ self.log.debug("Creating data directories from cached datadir")
+
+ # find and delete old cache directories if any exist
+ for i in range(MAX_NODES):
+ if os.path.isdir(os.path.join(cachedir, "node" + str(i))):
+ shutil.rmtree(os.path.join(cachedir, "node" + str(i)))
+
+ # Create cache directories, run bitcoinds:
+ for i in range(MAX_NODES):
+ datadir = initialize_datadir(cachedir, i)
+ args = [os.getenv("BITCOIND", "bitcoind"), "-server", "-keypool=1", "-datadir=" + datadir, "-discover=0"]
+ if i > 0:
+ args.append("-connect=127.0.0.1:" + str(p2p_port(0)))
+ bitcoind_processes[i] = subprocess.Popen(args)
+ self.log.debug("initialize_chain: bitcoind started, waiting for RPC to come up")
+ wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i)
+ self.log.debug("initialize_chain: RPC successfully started")
+
+ self.nodes = []
+ for i in range(MAX_NODES):
+ try:
+ self.nodes.append(get_rpc_proxy(rpc_url(i), i))
+ except:
+ self.log.exception("Error connecting to node %d" % i)
+ sys.exit(1)
+
+ # Create a 200-block-long chain; each of the 4 first nodes
+ # gets 25 mature blocks and 25 immature.
+ # Note: To preserve compatibility with older versions of
+ # initialize_chain, only 4 nodes will generate coins.
+ #
+ # blocks are created with timestamps 10 minutes apart
+ # starting from 2010 minutes in the past
+ enable_mocktime()
+ block_time = get_mocktime() - (201 * 10 * 60)
+ for i in range(2):
+ for peer in range(4):
+ for j in range(25):
+ set_node_times(self.nodes, block_time)
+ self.nodes[peer].generate(1)
+ block_time += 10 * 60
+ # Must sync before next peer starts generating blocks
+ sync_blocks(self.nodes)
+
+ # Shut them down, and clean up cache directories:
+ self.stop_nodes()
+ self.nodes = []
+ disable_mocktime()
+ for i in range(MAX_NODES):
+ os.remove(log_filename(cachedir, i, "debug.log"))
+ os.remove(log_filename(cachedir, i, "db.log"))
+ os.remove(log_filename(cachedir, i, "peers.dat"))
+ os.remove(log_filename(cachedir, i, "fee_estimates.dat"))
+
+ for i in range(num_nodes):
+ from_dir = os.path.join(cachedir, "node" + str(i))
+ to_dir = os.path.join(test_dir, "node" + str(i))
+ shutil.copytree(from_dir, to_dir)
+ initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf
+
+ def _initialize_chain_clean(self, test_dir, num_nodes):
+ """Initialize empty blockchain for use by the test.
+
+ Create an empty blockchain and num_nodes wallets.
+ Useful if a test case wants complete control over initialization."""
+ for i in range(num_nodes):
+ initialize_datadir(test_dir, i)
+
# Test framework for doing p2p comparison testing, which sets up some bitcoind
# binaries:
# 1 binary: test binary
@@ -238,7 +365,7 @@ class ComparisonTestFramework(BitcoinTestFramework):
help="bitcoind binary to use for reference nodes (if any)")
def setup_network(self):
- self.nodes = start_nodes(
+ self.nodes = self.start_nodes(
self.num_nodes, self.options.tmpdir,
extra_args=[['-whitelist=127.0.0.1']] * self.num_nodes,
binary=[self.options.testbinary] +
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 9186c3cbe9..2b56fe8d62 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -226,87 +226,6 @@ def wait_for_bitcoind_start(process, url, i):
raise # unknown JSON RPC exception
time.sleep(0.25)
-def initialize_chain(test_dir, num_nodes, cachedir):
- """
- Create a cache of a 200-block-long chain (with wallet) for MAX_NODES
- Afterward, create num_nodes copies from the cache
- """
-
- assert num_nodes <= MAX_NODES
- create_cache = False
- for i in range(MAX_NODES):
- if not os.path.isdir(os.path.join(cachedir, 'node'+str(i))):
- create_cache = True
- break
-
- if create_cache:
- logger.debug("Creating data directories from cached datadir")
-
- #find and delete old cache directories if any exist
- for i in range(MAX_NODES):
- if os.path.isdir(os.path.join(cachedir,"node"+str(i))):
- shutil.rmtree(os.path.join(cachedir,"node"+str(i)))
-
- # Create cache directories, run bitcoinds:
- for i in range(MAX_NODES):
- datadir=initialize_datadir(cachedir, i)
- args = [ os.getenv("BITCOIND", "bitcoind"), "-server", "-keypool=1", "-datadir="+datadir, "-discover=0" ]
- if i > 0:
- args.append("-connect=127.0.0.1:"+str(p2p_port(0)))
- bitcoind_processes[i] = subprocess.Popen(args)
- logger.debug("initialize_chain: bitcoind started, waiting for RPC to come up")
- wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i)
- logger.debug("initialize_chain: RPC successfully started")
-
- rpcs = []
- for i in range(MAX_NODES):
- try:
- rpcs.append(get_rpc_proxy(rpc_url(i), i))
- except:
- sys.stderr.write("Error connecting to "+url+"\n")
- sys.exit(1)
-
- # Create a 200-block-long chain; each of the 4 first nodes
- # gets 25 mature blocks and 25 immature.
- # Note: To preserve compatibility with older versions of
- # initialize_chain, only 4 nodes will generate coins.
- #
- # blocks are created with timestamps 10 minutes apart
- # starting from 2010 minutes in the past
- enable_mocktime()
- block_time = get_mocktime() - (201 * 10 * 60)
- for i in range(2):
- for peer in range(4):
- for j in range(25):
- set_node_times(rpcs, block_time)
- rpcs[peer].generate(1)
- block_time += 10*60
- # Must sync before next peer starts generating blocks
- sync_blocks(rpcs)
-
- # Shut them down, and clean up cache directories:
- stop_nodes(rpcs)
- disable_mocktime()
- for i in range(MAX_NODES):
- os.remove(log_filename(cachedir, i, "debug.log"))
- os.remove(log_filename(cachedir, i, "db.log"))
- os.remove(log_filename(cachedir, i, "peers.dat"))
- os.remove(log_filename(cachedir, i, "fee_estimates.dat"))
-
- for i in range(num_nodes):
- from_dir = os.path.join(cachedir, "node"+str(i))
- to_dir = os.path.join(test_dir, "node"+str(i))
- shutil.copytree(from_dir, to_dir)
- initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf
-
-def initialize_chain_clean(test_dir, num_nodes):
- """
- Create an empty blockchain and num_nodes wallets.
- Useful if a test case wants complete control over initialization.
- """
- for i in range(num_nodes):
- datadir=initialize_datadir(test_dir, i)
-
def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None):
"""
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 0996b1bc20..c87010b0f4 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -85,6 +85,7 @@ BASE_SCRIPTS= [
'rest.py',
'mempool_spendcoinbase.py',
'mempool_reorg.py',
+ 'mempool_persist.py',
'httpbasics.py',
'multi_rpc.py',
'proxy_test.py',
@@ -109,7 +110,6 @@ BASE_SCRIPTS= [
'rpcnamedargs.py',
'listsinceblock.py',
'p2p-leaktests.py',
- 'import-abort-rescan.py',
]
EXTENDED_SCRIPTS = [
@@ -178,7 +178,10 @@ def main():
# Read config generated by configure.
config = configparser.ConfigParser()
- config.read_file(open(os.path.dirname(__file__) + "/config.ini"))
+ configfile = os.path.abspath(os.path.dirname(__file__)) + "/config.ini"
+ config.read_file(open(configfile))
+
+ passon_args.append("--configfile=%s" % configfile)
# Set up logging
logging_level = logging.INFO if args.quiet else logging.DEBUG
diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py
index a72630406e..918e13bcd4 100755
--- a/test/functional/zmq_test.py
+++ b/test/functional/zmq_test.py
@@ -29,7 +29,9 @@ class ZMQTest (BitcoinTestFramework):
# Check that bitcoin has been built with ZMQ enabled
config = configparser.ConfigParser()
- config.read_file(open(os.path.dirname(__file__) + "/config.ini"))
+ if not self.options.configfile:
+ self.options.configfile = os.path.dirname(__file__) + "/config.ini"
+ config.read_file(open(self.options.configfile))
if not config["components"].getboolean("ENABLE_ZMQ"):
self.log.warning("bitcoind has not been built with zmq enabled. Skipping zmq tests!")