mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-19 13:27:35 +02:00
QA: Adapt BitcoinTestFramework for chains other than "regtest"
This commit is contained in:
parent
a06be15279
commit
4454c52ae6
17 changed files with 72 additions and 68 deletions
|
|
@ -23,6 +23,7 @@ def main():
|
||||||
parser = argparse.ArgumentParser(usage='%(prog)s [options] <test temporary directory>', description=__doc__)
|
parser = argparse.ArgumentParser(usage='%(prog)s [options] <test temporary directory>', description=__doc__)
|
||||||
parser.add_argument('-c', '--color', dest='color', action='store_true', help='outputs the combined log with events colored by source (requires posix terminal colors. Use less -r for viewing)')
|
parser.add_argument('-c', '--color', dest='color', action='store_true', help='outputs the combined log with events colored by source (requires posix terminal colors. Use less -r for viewing)')
|
||||||
parser.add_argument('--html', dest='html', action='store_true', help='outputs the combined log as html. Requires jinja2. pip install jinja2')
|
parser.add_argument('--html', dest='html', action='store_true', help='outputs the combined log as html. Requires jinja2. pip install jinja2')
|
||||||
|
parser.add_argument('--chain', dest='chain', help='selected chain in the tests (default: regtest)', default='regtest')
|
||||||
args, unknown_args = parser.parse_known_args()
|
args, unknown_args = parser.parse_known_args()
|
||||||
|
|
||||||
if args.color and os.name != 'posix':
|
if args.color and os.name != 'posix':
|
||||||
|
|
@ -38,11 +39,11 @@ def main():
|
||||||
print("Unexpected arguments" + str(unknown_args))
|
print("Unexpected arguments" + str(unknown_args))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
log_events = read_logs(unknown_args[0])
|
log_events = read_logs(unknown_args[0], args.chain)
|
||||||
|
|
||||||
print_logs(log_events, color=args.color, html=args.html)
|
print_logs(log_events, color=args.color, html=args.html)
|
||||||
|
|
||||||
def read_logs(tmp_dir):
|
def read_logs(tmp_dir, chain):
|
||||||
"""Reads log files.
|
"""Reads log files.
|
||||||
|
|
||||||
Delegates to generator function get_log_events() to provide individual log events
|
Delegates to generator function get_log_events() to provide individual log events
|
||||||
|
|
@ -50,7 +51,7 @@ def read_logs(tmp_dir):
|
||||||
|
|
||||||
files = [("test", "%s/test_framework.log" % tmp_dir)]
|
files = [("test", "%s/test_framework.log" % tmp_dir)]
|
||||||
for i in itertools.count():
|
for i in itertools.count():
|
||||||
logfile = "{}/node{}/regtest/debug.log".format(tmp_dir, i)
|
logfile = "{}/node{}/{}/debug.log".format(tmp_dir, i, chain)
|
||||||
if not os.path.isfile(logfile):
|
if not os.path.isfile(logfile):
|
||||||
break
|
break
|
||||||
files.append(("node%d" % i, logfile))
|
files.append(("node%d" % i, logfile))
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class BlocksdirTest(BitcoinTestFramework):
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
self.stop_node(0)
|
self.stop_node(0)
|
||||||
shutil.rmtree(self.nodes[0].datadir)
|
shutil.rmtree(self.nodes[0].datadir)
|
||||||
initialize_datadir(self.options.tmpdir, 0)
|
initialize_datadir(self.options.tmpdir, 0, self.chain)
|
||||||
self.log.info("Starting with non exiting blocksdir ...")
|
self.log.info("Starting with non exiting blocksdir ...")
|
||||||
blocksdir_path = os.path.join(self.options.tmpdir, 'blocksdir')
|
blocksdir_path = os.path.join(self.options.tmpdir, 'blocksdir')
|
||||||
self.nodes[0].assert_start_raises_init_error(["-blocksdir=" + blocksdir_path], 'Error: Specified blocks directory "{}" does not exist.'.format(blocksdir_path))
|
self.nodes[0].assert_start_raises_init_error(["-blocksdir=" + blocksdir_path], 'Error: Specified blocks directory "{}" does not exist.'.format(blocksdir_path))
|
||||||
|
|
@ -28,8 +28,8 @@ class BlocksdirTest(BitcoinTestFramework):
|
||||||
self.start_node(0, ["-blocksdir=" + blocksdir_path])
|
self.start_node(0, ["-blocksdir=" + blocksdir_path])
|
||||||
self.log.info("mining blocks..")
|
self.log.info("mining blocks..")
|
||||||
self.nodes[0].generate(10)
|
self.nodes[0].generate(10)
|
||||||
assert os.path.isfile(os.path.join(blocksdir_path, "regtest", "blocks", "blk00000.dat"))
|
assert os.path.isfile(os.path.join(blocksdir_path, self.chain, "blocks", "blk00000.dat"))
|
||||||
assert os.path.isdir(os.path.join(self.nodes[0].datadir, "regtest", "blocks", "index"))
|
assert os.path.isdir(os.path.join(self.nodes[0].datadir, self.chain, "blocks", "index"))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
||||||
|
|
@ -65,13 +65,13 @@ class ConfArgsTest(BitcoinTestFramework):
|
||||||
# Temporarily disabled, because this test would access the user's home dir (~/.bitcoin)
|
# Temporarily disabled, because this test would access the user's home dir (~/.bitcoin)
|
||||||
#self.start_node(0, ['-conf='+conf_file, '-wallet=w1'])
|
#self.start_node(0, ['-conf='+conf_file, '-wallet=w1'])
|
||||||
#self.stop_node(0)
|
#self.stop_node(0)
|
||||||
#assert os.path.exists(os.path.join(new_data_dir, 'regtest', 'wallets', 'w1'))
|
#assert os.path.exists(os.path.join(new_data_dir, self.chain, 'wallets', 'w1'))
|
||||||
|
|
||||||
# Ensure command line argument overrides datadir in conf
|
# Ensure command line argument overrides datadir in conf
|
||||||
os.mkdir(new_data_dir_2)
|
os.mkdir(new_data_dir_2)
|
||||||
self.nodes[0].datadir = new_data_dir_2
|
self.nodes[0].datadir = new_data_dir_2
|
||||||
self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2'])
|
self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2'])
|
||||||
assert os.path.exists(os.path.join(new_data_dir_2, 'regtest', 'wallets', 'w2'))
|
assert os.path.exists(os.path.join(new_data_dir_2, self.chain, 'wallets', 'w2'))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
ConfArgsTest().main()
|
ConfArgsTest().main()
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class LoggingTest(BitcoinTestFramework):
|
||||||
self.setup_clean_chain = True
|
self.setup_clean_chain = True
|
||||||
|
|
||||||
def relative_log_path(self, name):
|
def relative_log_path(self, name):
|
||||||
return os.path.join(self.nodes[0].datadir, "regtest", name)
|
return os.path.join(self.nodes[0].datadir, self.chain, name)
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
# test default log file name
|
# test default log file name
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ class PruneTest(BitcoinTestFramework):
|
||||||
def setup_network(self):
|
def setup_network(self):
|
||||||
self.setup_nodes()
|
self.setup_nodes()
|
||||||
|
|
||||||
self.prunedir = os.path.join(self.nodes[2].datadir, 'regtest', 'blocks', '')
|
self.prunedir = os.path.join(self.nodes[2].datadir, self.chain, 'blocks', '')
|
||||||
|
|
||||||
connect_nodes(self.nodes[0], 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
connect_nodes(self.nodes[1], 2)
|
connect_nodes(self.nodes[1], 2)
|
||||||
|
|
@ -257,7 +257,7 @@ class PruneTest(BitcoinTestFramework):
|
||||||
assert_equal(ret, expected_ret)
|
assert_equal(ret, expected_ret)
|
||||||
|
|
||||||
def has_block(index):
|
def has_block(index):
|
||||||
return os.path.isfile(os.path.join(self.nodes[node_number].datadir, "regtest", "blocks", "blk{:05}.dat".format(index)))
|
return os.path.isfile(os.path.join(self.nodes[node_number].datadir, self.chain, "blocks", "blk{:05}.dat".format(index)))
|
||||||
|
|
||||||
# should not prune because chain tip of node 3 (995) < PruneAfterHeight (1000)
|
# should not prune because chain tip of node 3 (995) < PruneAfterHeight (1000)
|
||||||
assert_raises_rpc_error(-1, "Blockchain is too short for pruning", node.pruneblockchain, height(500))
|
assert_raises_rpc_error(-1, "Blockchain is too short for pruning", node.pruneblockchain, height(500))
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class TestBitcoinCli(BitcoinTestFramework):
|
||||||
rpc_response = self.nodes[0].getblockchaininfo()
|
rpc_response = self.nodes[0].getblockchaininfo()
|
||||||
assert_equal(cli_response, rpc_response)
|
assert_equal(cli_response, rpc_response)
|
||||||
|
|
||||||
user, password = get_auth_cookie(self.nodes[0].datadir)
|
user, password = get_auth_cookie(self.nodes[0].datadir, self.chain)
|
||||||
|
|
||||||
self.log.info("Test -stdinrpcpass option")
|
self.log.info("Test -stdinrpcpass option")
|
||||||
assert_equal(0, self.nodes[0].cli('-rpcuser=%s' % user, '-stdinrpcpass', input=password).getblockcount())
|
assert_equal(0, self.nodes[0].cli('-rpcuser=%s' % user, '-stdinrpcpass', input=password).getblockcount())
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,8 @@ class MempoolPersistTest(BitcoinTestFramework):
|
||||||
self.start_node(0)
|
self.start_node(0)
|
||||||
wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5)
|
wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5)
|
||||||
|
|
||||||
mempooldat0 = os.path.join(self.nodes[0].datadir, 'regtest', 'mempool.dat')
|
mempooldat0 = os.path.join(self.nodes[0].datadir, self.chain, 'mempool.dat')
|
||||||
mempooldat1 = os.path.join(self.nodes[1].datadir, 'regtest', 'mempool.dat')
|
mempooldat1 = os.path.join(self.nodes[1].datadir, self.chain, 'mempool.dat')
|
||||||
self.log.debug("Remove the mempool.dat file. Verify that savemempool to disk via RPC re-creates it")
|
self.log.debug("Remove the mempool.dat file. Verify that savemempool to disk via RPC re-creates it")
|
||||||
os.remove(mempooldat0)
|
os.remove(mempooldat0)
|
||||||
self.nodes[0].savemempool()
|
self.nodes[0].savemempool()
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class MiningTest(BitcoinTestFramework):
|
||||||
self.log.info('getmininginfo')
|
self.log.info('getmininginfo')
|
||||||
mining_info = node.getmininginfo()
|
mining_info = node.getmininginfo()
|
||||||
assert_equal(mining_info['blocks'], 200)
|
assert_equal(mining_info['blocks'], 200)
|
||||||
assert_equal(mining_info['chain'], 'regtest')
|
assert_equal(mining_info['chain'], self.chain)
|
||||||
assert_equal(mining_info['currentblocktx'], 0)
|
assert_equal(mining_info['currentblocktx'], 0)
|
||||||
assert_equal(mining_info['currentblockweight'], 0)
|
assert_equal(mining_info['currentblockweight'], 0)
|
||||||
assert_equal(mining_info['difficulty'], Decimal('4.656542373906925E-10'))
|
assert_equal(mining_info['difficulty'], Decimal('4.656542373906925E-10'))
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class RPCBindTest(BitcoinTestFramework):
|
||||||
self.nodes[0].rpchost = None
|
self.nodes[0].rpchost = None
|
||||||
self.start_nodes([base_args])
|
self.start_nodes([base_args])
|
||||||
# connect to node through non-loopback interface
|
# connect to node through non-loopback interface
|
||||||
node = get_rpc_proxy(rpc_url(self.nodes[0].datadir, 0, "%s:%d" % (rpchost, rpcport)), 0, coveragedir=self.options.coveragedir)
|
node = get_rpc_proxy(rpc_url(self.nodes[0].datadir, 0, self.chain, "%s:%d" % (rpchost, rpcport)), 0, coveragedir=self.options.coveragedir)
|
||||||
node.getnetworkinfo()
|
node.getnetworkinfo()
|
||||||
self.stop_nodes()
|
self.stop_nodes()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class ScantxoutsetTest(BitcoinTestFramework):
|
||||||
|
|
||||||
self.log.info("Stop node, remove wallet, mine again some blocks...")
|
self.log.info("Stop node, remove wallet, mine again some blocks...")
|
||||||
self.stop_node(0)
|
self.stop_node(0)
|
||||||
shutil.rmtree(os.path.join(self.nodes[0].datadir, "regtest", 'wallets'))
|
shutil.rmtree(os.path.join(self.nodes[0].datadir, self.chain, 'wallets'))
|
||||||
self.start_node(0)
|
self.start_node(0)
|
||||||
self.nodes[0].generate(110)
|
self.nodes[0].generate(110)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Sets test framework defaults. Do not override this method. Instead, override the set_test_params() method"""
|
"""Sets test framework defaults. Do not override this method. Instead, override the set_test_params() method"""
|
||||||
|
self.chain = "regtest"
|
||||||
self.setup_clean_chain = False
|
self.setup_clean_chain = False
|
||||||
self.nodes = []
|
self.nodes = []
|
||||||
self.network_thread = None
|
self.network_thread = None
|
||||||
|
|
@ -267,7 +268,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||||
assert_equal(len(extra_args), num_nodes)
|
assert_equal(len(extra_args), num_nodes)
|
||||||
assert_equal(len(binary), num_nodes)
|
assert_equal(len(binary), num_nodes)
|
||||||
for i in range(num_nodes):
|
for i in range(num_nodes):
|
||||||
self.nodes.append(TestNode(i, get_datadir_path(self.options.tmpdir, i), rpchost=rpchost, timewait=self.rpc_timewait, bitcoind=binary[i], bitcoin_cli=self.options.bitcoincli, mocktime=self.mocktime, coverage_dir=self.options.coveragedir, extra_conf=extra_confs[i], extra_args=extra_args[i], use_cli=self.options.usecli))
|
self.nodes.append(TestNode(i, get_datadir_path(self.options.tmpdir, i), self.chain, rpchost=rpchost, timewait=self.rpc_timewait, bitcoind=binary[i], bitcoin_cli=self.options.bitcoincli, mocktime=self.mocktime, coverage_dir=self.options.coveragedir, extra_conf=extra_confs[i], extra_args=extra_args[i], use_cli=self.options.usecli))
|
||||||
|
|
||||||
def start_node(self, i, *args, **kwargs):
|
def start_node(self, i, *args, **kwargs):
|
||||||
"""Start a bitcoind"""
|
"""Start a bitcoind"""
|
||||||
|
|
@ -414,11 +415,11 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||||
|
|
||||||
# Create cache directories, run bitcoinds:
|
# Create cache directories, run bitcoinds:
|
||||||
for i in range(MAX_NODES):
|
for i in range(MAX_NODES):
|
||||||
datadir = initialize_datadir(self.options.cachedir, i)
|
datadir = initialize_datadir(self.options.cachedir, i, self.chain)
|
||||||
args = [self.options.bitcoind, "-datadir=" + datadir]
|
args = [self.options.bitcoind, "-datadir=" + datadir]
|
||||||
if i > 0:
|
if i > 0:
|
||||||
args.append("-connect=127.0.0.1:" + str(p2p_port(0)))
|
args.append("-connect=127.0.0.1:" + str(p2p_port(0)))
|
||||||
self.nodes.append(TestNode(i, get_datadir_path(self.options.cachedir, i), extra_conf=["bind=127.0.0.1"], extra_args=[], rpchost=None, timewait=self.rpc_timewait, bitcoind=self.options.bitcoind, bitcoin_cli=self.options.bitcoincli, mocktime=self.mocktime, coverage_dir=None))
|
self.nodes.append(TestNode(i, get_datadir_path(self.options.cachedir, i), self.chain, extra_conf=["bind=127.0.0.1"], extra_args=[], rpchost=None, timewait=self.rpc_timewait, bitcoind=self.options.bitcoind, bitcoin_cli=self.options.bitcoincli, mocktime=self.mocktime, coverage_dir=None))
|
||||||
self.nodes[i].args = args
|
self.nodes[i].args = args
|
||||||
self.start_node(i)
|
self.start_node(i)
|
||||||
|
|
||||||
|
|
@ -450,7 +451,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||||
self.disable_mocktime()
|
self.disable_mocktime()
|
||||||
|
|
||||||
def cache_path(n, *paths):
|
def cache_path(n, *paths):
|
||||||
return os.path.join(get_datadir_path(self.options.cachedir, n), "regtest", *paths)
|
return os.path.join(get_datadir_path(self.options.cachedir, n), self.chain, *paths)
|
||||||
|
|
||||||
for i in range(MAX_NODES):
|
for i in range(MAX_NODES):
|
||||||
for entry in os.listdir(cache_path(i)):
|
for entry in os.listdir(cache_path(i)):
|
||||||
|
|
@ -461,7 +462,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||||
from_dir = get_datadir_path(self.options.cachedir, i)
|
from_dir = get_datadir_path(self.options.cachedir, i)
|
||||||
to_dir = get_datadir_path(self.options.tmpdir, i)
|
to_dir = get_datadir_path(self.options.tmpdir, i)
|
||||||
shutil.copytree(from_dir, to_dir)
|
shutil.copytree(from_dir, to_dir)
|
||||||
initialize_datadir(self.options.tmpdir, i) # Overwrite port/rpcport in bitcoin.conf
|
initialize_datadir(self.options.tmpdir, i, self.chain) # Overwrite port/rpcport in bitcoin.conf
|
||||||
|
|
||||||
def _initialize_chain_clean(self):
|
def _initialize_chain_clean(self):
|
||||||
"""Initialize empty blockchain for use by the test.
|
"""Initialize empty blockchain for use by the test.
|
||||||
|
|
@ -469,7 +470,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||||
Create an empty blockchain and num_nodes wallets.
|
Create an empty blockchain and num_nodes wallets.
|
||||||
Useful if a test case wants complete control over initialization."""
|
Useful if a test case wants complete control over initialization."""
|
||||||
for i in range(self.num_nodes):
|
for i in range(self.num_nodes):
|
||||||
initialize_datadir(self.options.tmpdir, i)
|
initialize_datadir(self.options.tmpdir, i, self.chain)
|
||||||
|
|
||||||
|
|
||||||
class SkipTest(Exception):
|
class SkipTest(Exception):
|
||||||
|
|
|
||||||
|
|
@ -57,11 +57,12 @@ class TestNode():
|
||||||
To make things easier for the test writer, any unrecognised messages will
|
To make things easier for the test writer, any unrecognised messages will
|
||||||
be dispatched to the RPC connection."""
|
be dispatched to the RPC connection."""
|
||||||
|
|
||||||
def __init__(self, i, datadir, *, rpchost, timewait, bitcoind, bitcoin_cli, mocktime, coverage_dir, extra_conf=None, extra_args=None, use_cli=False):
|
def __init__(self, i, datadir, chain, *, rpchost, timewait, bitcoind, bitcoin_cli, mocktime, coverage_dir, extra_conf=None, extra_args=None, use_cli=False):
|
||||||
self.index = i
|
self.index = i
|
||||||
self.datadir = datadir
|
self.datadir = datadir
|
||||||
self.stdout_dir = os.path.join(self.datadir, "stdout")
|
self.stdout_dir = os.path.join(self.datadir, "stdout")
|
||||||
self.stderr_dir = os.path.join(self.datadir, "stderr")
|
self.stderr_dir = os.path.join(self.datadir, "stderr")
|
||||||
|
self.chain = chain
|
||||||
self.rpchost = rpchost
|
self.rpchost = rpchost
|
||||||
self.rpc_timeout = timewait
|
self.rpc_timeout = timewait
|
||||||
self.binary = bitcoind
|
self.binary = bitcoind
|
||||||
|
|
@ -83,7 +84,7 @@ class TestNode():
|
||||||
"-uacomment=testnode%d" % i
|
"-uacomment=testnode%d" % i
|
||||||
]
|
]
|
||||||
|
|
||||||
self.cli = TestNodeCLI(bitcoin_cli, self.datadir)
|
self.cli = TestNodeCLI(bitcoin_cli, self.datadir, self.chain)
|
||||||
self.use_cli = use_cli
|
self.use_cli = use_cli
|
||||||
|
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
@ -138,7 +139,7 @@ class TestNode():
|
||||||
# Delete any existing cookie file -- if such a file exists (eg due to
|
# Delete any existing cookie file -- if such a file exists (eg due to
|
||||||
# unclean shutdown), it will get overwritten anyway by bitcoind, and
|
# unclean shutdown), it will get overwritten anyway by bitcoind, and
|
||||||
# potentially interfere with our attempt to authenticate
|
# potentially interfere with our attempt to authenticate
|
||||||
delete_cookie_file(self.datadir)
|
delete_cookie_file(self.datadir, self.chain)
|
||||||
|
|
||||||
# add environment variable LIBC_FATAL_STDERR_=1 so that libc errors are written to stderr and not the terminal
|
# add environment variable LIBC_FATAL_STDERR_=1 so that libc errors are written to stderr and not the terminal
|
||||||
subp_env = dict(os.environ, LIBC_FATAL_STDERR_="1")
|
subp_env = dict(os.environ, LIBC_FATAL_STDERR_="1")
|
||||||
|
|
@ -157,7 +158,7 @@ class TestNode():
|
||||||
raise FailedToStartError(self._node_msg(
|
raise FailedToStartError(self._node_msg(
|
||||||
'bitcoind exited with status {} during initialization'.format(self.process.returncode)))
|
'bitcoind exited with status {} during initialization'.format(self.process.returncode)))
|
||||||
try:
|
try:
|
||||||
self.rpc = get_rpc_proxy(rpc_url(self.datadir, self.index, self.rpchost), self.index, timeout=self.rpc_timeout, coveragedir=self.coverage_dir)
|
self.rpc = get_rpc_proxy(rpc_url(self.datadir, self.index, self.chain, self.rpchost), self.index, timeout=self.rpc_timeout, coveragedir=self.coverage_dir)
|
||||||
self.rpc.getblockcount()
|
self.rpc.getblockcount()
|
||||||
# If the call to getblockcount() succeeds then the RPC connection is up
|
# If the call to getblockcount() succeeds then the RPC connection is up
|
||||||
self.rpc_connected = True
|
self.rpc_connected = True
|
||||||
|
|
@ -325,16 +326,17 @@ class TestNodeCLIAttr:
|
||||||
class TestNodeCLI():
|
class TestNodeCLI():
|
||||||
"""Interface to bitcoin-cli for an individual node"""
|
"""Interface to bitcoin-cli for an individual node"""
|
||||||
|
|
||||||
def __init__(self, binary, datadir):
|
def __init__(self, binary, datadir, chain):
|
||||||
self.options = []
|
self.options = []
|
||||||
self.binary = binary
|
self.binary = binary
|
||||||
self.datadir = datadir
|
self.datadir = datadir
|
||||||
|
self.chain = chain
|
||||||
self.input = None
|
self.input = None
|
||||||
self.log = logging.getLogger('TestFramework.bitcoincli')
|
self.log = logging.getLogger('TestFramework.bitcoincli')
|
||||||
|
|
||||||
def __call__(self, *options, input=None):
|
def __call__(self, *options, input=None):
|
||||||
# TestNodeCLI is callable with bitcoin-cli command-line options
|
# TestNodeCLI is callable with bitcoin-cli command-line options
|
||||||
cli = TestNodeCLI(self.binary, self.datadir)
|
cli = TestNodeCLI(self.binary, self.datadir, self.chain)
|
||||||
cli.options = [str(o) for o in options]
|
cli.options = [str(o) for o in options]
|
||||||
cli.input = input
|
cli.input = input
|
||||||
return cli
|
return cli
|
||||||
|
|
@ -356,7 +358,7 @@ class TestNodeCLI():
|
||||||
pos_args = [str(arg).lower() if type(arg) is bool else str(arg) for arg in args]
|
pos_args = [str(arg).lower() if type(arg) is bool else str(arg) for arg in args]
|
||||||
named_args = [str(key) + "=" + str(value) for (key, value) in kwargs.items()]
|
named_args = [str(key) + "=" + str(value) for (key, value) in kwargs.items()]
|
||||||
assert not (pos_args and named_args), "Cannot use positional arguments and named arguments in the same bitcoin-cli call"
|
assert not (pos_args and named_args), "Cannot use positional arguments and named arguments in the same bitcoin-cli call"
|
||||||
p_args = [self.binary, "-datadir=" + self.datadir] + self.options
|
p_args = [self.binary, "-datadir=" + self.datadir, "-chain=" + self.chain] + self.options
|
||||||
if named_args:
|
if named_args:
|
||||||
p_args += ["-named"]
|
p_args += ["-named"]
|
||||||
if command is not None:
|
if command is not None:
|
||||||
|
|
|
||||||
|
|
@ -273,8 +273,8 @@ def p2p_port(n):
|
||||||
def rpc_port(n):
|
def rpc_port(n):
|
||||||
return PORT_MIN + PORT_RANGE + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES)
|
return PORT_MIN + PORT_RANGE + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES)
|
||||||
|
|
||||||
def rpc_url(datadir, i, rpchost=None):
|
def rpc_url(datadir, i, chain, rpchost=None):
|
||||||
rpc_u, rpc_p = get_auth_cookie(datadir)
|
rpc_u, rpc_p = get_auth_cookie(datadir, chain)
|
||||||
host = '127.0.0.1'
|
host = '127.0.0.1'
|
||||||
port = rpc_port(i)
|
port = rpc_port(i)
|
||||||
if rpchost:
|
if rpchost:
|
||||||
|
|
@ -288,13 +288,16 @@ def rpc_url(datadir, i, rpchost=None):
|
||||||
# Node functions
|
# Node functions
|
||||||
################
|
################
|
||||||
|
|
||||||
def initialize_datadir(dirname, n):
|
def get_datadir_path(dirname, n):
|
||||||
|
return os.path.join(dirname, "node" + str(n))
|
||||||
|
|
||||||
|
def initialize_datadir(dirname, n, chain):
|
||||||
datadir = get_datadir_path(dirname, n)
|
datadir = get_datadir_path(dirname, n)
|
||||||
if not os.path.isdir(datadir):
|
if not os.path.isdir(datadir):
|
||||||
os.makedirs(datadir)
|
os.makedirs(datadir)
|
||||||
with open(os.path.join(datadir, "bitcoin.conf"), 'w', encoding='utf8') as f:
|
with open(os.path.join(datadir, "bitcoin.conf"), 'w', encoding='utf8') as f:
|
||||||
f.write("regtest=1\n")
|
f.write("chain=%s\n" % chain)
|
||||||
f.write("[regtest]\n")
|
f.write("[%s]\n" % chain)
|
||||||
f.write("port=" + str(p2p_port(n)) + "\n")
|
f.write("port=" + str(p2p_port(n)) + "\n")
|
||||||
f.write("rpcport=" + str(rpc_port(n)) + "\n")
|
f.write("rpcport=" + str(rpc_port(n)) + "\n")
|
||||||
f.write("server=1\n")
|
f.write("server=1\n")
|
||||||
|
|
@ -306,15 +309,12 @@ def initialize_datadir(dirname, n):
|
||||||
os.makedirs(os.path.join(datadir, 'stdout'), exist_ok=True)
|
os.makedirs(os.path.join(datadir, 'stdout'), exist_ok=True)
|
||||||
return datadir
|
return datadir
|
||||||
|
|
||||||
def get_datadir_path(dirname, n):
|
|
||||||
return os.path.join(dirname, "node" + str(n))
|
|
||||||
|
|
||||||
def append_config(datadir, options):
|
def append_config(datadir, options):
|
||||||
with open(os.path.join(datadir, "bitcoin.conf"), 'a', encoding='utf8') as f:
|
with open(os.path.join(datadir, "bitcoin.conf"), 'a', encoding='utf8') as f:
|
||||||
for option in options:
|
for option in options:
|
||||||
f.write(option + "\n")
|
f.write(option + "\n")
|
||||||
|
|
||||||
def get_auth_cookie(datadir):
|
def get_auth_cookie(datadir, chain):
|
||||||
user = None
|
user = None
|
||||||
password = None
|
password = None
|
||||||
if os.path.isfile(os.path.join(datadir, "bitcoin.conf")):
|
if os.path.isfile(os.path.join(datadir, "bitcoin.conf")):
|
||||||
|
|
@ -326,8 +326,8 @@ def get_auth_cookie(datadir):
|
||||||
if line.startswith("rpcpassword="):
|
if line.startswith("rpcpassword="):
|
||||||
assert password is None # Ensure that there is only one rpcpassword line
|
assert password is None # Ensure that there is only one rpcpassword line
|
||||||
password = line.split("=")[1].strip("\n")
|
password = line.split("=")[1].strip("\n")
|
||||||
if os.path.isfile(os.path.join(datadir, "regtest", ".cookie")):
|
if os.path.isfile(os.path.join(datadir, chain, ".cookie")):
|
||||||
with open(os.path.join(datadir, "regtest", ".cookie"), 'r', encoding="ascii") as f:
|
with open(os.path.join(datadir, chain, ".cookie"), 'r', encoding="ascii") as f:
|
||||||
userpass = f.read()
|
userpass = f.read()
|
||||||
split_userpass = userpass.split(':')
|
split_userpass = userpass.split(':')
|
||||||
user = split_userpass[0]
|
user = split_userpass[0]
|
||||||
|
|
@ -337,10 +337,10 @@ def get_auth_cookie(datadir):
|
||||||
return user, password
|
return user, password
|
||||||
|
|
||||||
# If a cookie file exists in the given datadir, delete it.
|
# If a cookie file exists in the given datadir, delete it.
|
||||||
def delete_cookie_file(datadir):
|
def delete_cookie_file(datadir, chain):
|
||||||
if os.path.isfile(os.path.join(datadir, "regtest", ".cookie")):
|
if os.path.isfile(os.path.join(datadir, chain, ".cookie")):
|
||||||
logger.debug("Deleting leftover cookie file")
|
logger.debug("Deleting leftover cookie file")
|
||||||
os.remove(os.path.join(datadir, "regtest", ".cookie"))
|
os.remove(os.path.join(datadir, chain, ".cookie"))
|
||||||
|
|
||||||
def get_bip9_status(node, key):
|
def get_bip9_status(node, key):
|
||||||
info = node.getblockchaininfo()
|
info = node.getblockchaininfo()
|
||||||
|
|
|
||||||
|
|
@ -92,9 +92,9 @@ class WalletBackupTest(BitcoinTestFramework):
|
||||||
self.stop_node(2)
|
self.stop_node(2)
|
||||||
|
|
||||||
def erase_three(self):
|
def erase_three(self):
|
||||||
os.remove(os.path.join(self.nodes[0].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
os.remove(os.path.join(self.nodes[0].datadir, self.chain, 'wallets', 'wallet.dat'))
|
||||||
os.remove(os.path.join(self.nodes[1].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
os.remove(os.path.join(self.nodes[1].datadir, self.chain, 'wallets', 'wallet.dat'))
|
||||||
os.remove(os.path.join(self.nodes[2].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
os.remove(os.path.join(self.nodes[2].datadir, self.chain, 'wallets', 'wallet.dat'))
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
self.log.info("Generating initial blockchain")
|
self.log.info("Generating initial blockchain")
|
||||||
|
|
@ -152,13 +152,13 @@ class WalletBackupTest(BitcoinTestFramework):
|
||||||
self.erase_three()
|
self.erase_three()
|
||||||
|
|
||||||
# Start node2 with no chain
|
# Start node2 with no chain
|
||||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'blocks'))
|
shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'blocks'))
|
||||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'chainstate'))
|
shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'chainstate'))
|
||||||
|
|
||||||
# Restore wallets from backup
|
# Restore wallets from backup
|
||||||
shutil.copyfile(os.path.join(self.nodes[0].datadir, 'wallet.bak'), os.path.join(self.nodes[0].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
shutil.copyfile(os.path.join(self.nodes[0].datadir, 'wallet.bak'), os.path.join(self.nodes[0].datadir, self.chain, 'wallets', 'wallet.dat'))
|
||||||
shutil.copyfile(os.path.join(self.nodes[1].datadir, 'wallet.bak'), os.path.join(self.nodes[1].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
shutil.copyfile(os.path.join(self.nodes[1].datadir, 'wallet.bak'), os.path.join(self.nodes[1].datadir, self.chain, 'wallets', 'wallet.dat'))
|
||||||
shutil.copyfile(os.path.join(self.nodes[2].datadir, 'wallet.bak'), os.path.join(self.nodes[2].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
shutil.copyfile(os.path.join(self.nodes[2].datadir, 'wallet.bak'), os.path.join(self.nodes[2].datadir, self.chain, 'wallets', 'wallet.dat'))
|
||||||
|
|
||||||
self.log.info("Re-starting nodes")
|
self.log.info("Re-starting nodes")
|
||||||
self.start_three()
|
self.start_three()
|
||||||
|
|
@ -173,8 +173,8 @@ class WalletBackupTest(BitcoinTestFramework):
|
||||||
self.erase_three()
|
self.erase_three()
|
||||||
|
|
||||||
#start node2 with no chain
|
#start node2 with no chain
|
||||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'blocks'))
|
shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'blocks'))
|
||||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'chainstate'))
|
shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'chainstate'))
|
||||||
|
|
||||||
self.start_three()
|
self.start_three()
|
||||||
|
|
||||||
|
|
@ -194,10 +194,10 @@ class WalletBackupTest(BitcoinTestFramework):
|
||||||
|
|
||||||
# Backup to source wallet file must fail
|
# Backup to source wallet file must fail
|
||||||
sourcePaths = [
|
sourcePaths = [
|
||||||
os.path.join(self.nodes[0].datadir, 'regtest', 'wallets', 'wallet.dat'),
|
os.path.join(self.nodes[0].datadir, self.chain, 'wallets', 'wallet.dat'),
|
||||||
os.path.join(self.nodes[0].datadir, 'regtest', '.', 'wallets', 'wallet.dat'),
|
os.path.join(self.nodes[0].datadir, self.chain, '.', 'wallets', 'wallet.dat'),
|
||||||
os.path.join(self.nodes[0].datadir, 'regtest', 'wallets', ''),
|
os.path.join(self.nodes[0].datadir, self.chain, 'wallets', ''),
|
||||||
os.path.join(self.nodes[0].datadir, 'regtest', 'wallets')]
|
os.path.join(self.nodes[0].datadir, self.chain, 'wallets')]
|
||||||
|
|
||||||
for sourcePath in sourcePaths:
|
for sourcePath in sourcePaths:
|
||||||
assert_raises_rpc_error(-4, "backup failed", self.nodes[0].backupwallet, sourcePath)
|
assert_raises_rpc_error(-4, "backup failed", self.nodes[0].backupwallet, sourcePath)
|
||||||
|
|
|
||||||
|
|
@ -72,11 +72,11 @@ class WalletHDTest(BitcoinTestFramework):
|
||||||
|
|
||||||
self.log.info("Restore backup ...")
|
self.log.info("Restore backup ...")
|
||||||
self.stop_node(1)
|
self.stop_node(1)
|
||||||
# we need to delete the complete regtest directory
|
# we need to delete the complete chain directory
|
||||||
# otherwise node1 would auto-recover all funds in flag the keypool keys as used
|
# otherwise node1 would auto-recover all funds in flag the keypool keys as used
|
||||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "blocks"))
|
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "blocks"))
|
||||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "chainstate"))
|
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "chainstate"))
|
||||||
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat"))
|
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, self.chain, "wallets", "wallet.dat"))
|
||||||
self.start_node(1)
|
self.start_node(1)
|
||||||
|
|
||||||
# Assert that derivation is deterministic
|
# Assert that derivation is deterministic
|
||||||
|
|
@ -98,9 +98,9 @@ class WalletHDTest(BitcoinTestFramework):
|
||||||
|
|
||||||
# Try a RPC based rescan
|
# Try a RPC based rescan
|
||||||
self.stop_node(1)
|
self.stop_node(1)
|
||||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "blocks"))
|
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "blocks"))
|
||||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "chainstate"))
|
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "chainstate"))
|
||||||
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat"))
|
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, self.chain, "wallets", "wallet.dat"))
|
||||||
self.start_node(1, extra_args=self.extra_args[1])
|
self.start_node(1, extra_args=self.extra_args[1])
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes_bi(self.nodes, 0, 1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
|
||||||
self.extra_args = [[], ['-keypool=100']]
|
self.extra_args = [[], ['-keypool=100']]
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
wallet_path = os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat")
|
wallet_path = os.path.join(self.nodes[1].datadir, self.chain, "wallets", "wallet.dat")
|
||||||
wallet_backup_path = os.path.join(self.nodes[1].datadir, "wallet.bak")
|
wallet_backup_path = os.path.join(self.nodes[1].datadir, "wallet.bak")
|
||||||
self.nodes[0].generate(101)
|
self.nodes[0].generate(101)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
node = self.nodes[0]
|
node = self.nodes[0]
|
||||||
|
|
||||||
data_dir = lambda *p: os.path.join(node.datadir, 'regtest', *p)
|
data_dir = lambda *p: os.path.join(node.datadir, self.chain, *p)
|
||||||
wallet_dir = lambda *p: data_dir('wallets', *p)
|
wallet_dir = lambda *p: data_dir('wallets', *p)
|
||||||
wallet = lambda name: node.get_wallet_rpc(name)
|
wallet = lambda name: node.get_wallet_rpc(name)
|
||||||
|
|
||||||
|
|
@ -168,7 +168,7 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||||
assert_equal(w4.getbalance(), 3)
|
assert_equal(w4.getbalance(), 3)
|
||||||
|
|
||||||
batch = w1.batch([w1.getblockchaininfo.get_request(), w1.getwalletinfo.get_request()])
|
batch = w1.batch([w1.getblockchaininfo.get_request(), w1.getwalletinfo.get_request()])
|
||||||
assert_equal(batch[0]["result"]["chain"], "regtest")
|
assert_equal(batch[0]["result"]["chain"], self.chain)
|
||||||
assert_equal(batch[1]["result"]["walletname"], "w1")
|
assert_equal(batch[1]["result"]["walletname"], "w1")
|
||||||
|
|
||||||
self.log.info('Check for per-wallet settxfee call')
|
self.log.info('Check for per-wallet settxfee call')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue