Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/test_framework.py
Show All 23 Lines | from .util import ( | ||||
PortSeed, | PortSeed, | ||||
assert_equal, | assert_equal, | ||||
check_json_precision, | check_json_precision, | ||||
connect_nodes_bi, | connect_nodes_bi, | ||||
disconnect_nodes, | disconnect_nodes, | ||||
initialize_datadir, | initialize_datadir, | ||||
log_filename, | log_filename, | ||||
p2p_port, | p2p_port, | ||||
rpc_port, | |||||
set_node_times, | set_node_times, | ||||
sync_blocks, | sync_blocks, | ||||
sync_mempools, | sync_mempools, | ||||
) | ) | ||||
class TestStatus(Enum): | class TestStatus(Enum): | ||||
PASSED = 1 | PASSED = 1 | ||||
▲ Show 20 Lines • Show All 165 Lines • ▼ Show 20 Lines | class BitcoinTestFramework(): | ||||
def setup_network(self): | def setup_network(self): | ||||
"""Override this method to customize test network topology""" | """Override this method to customize test network topology""" | ||||
self.setup_nodes() | self.setup_nodes() | ||||
# Connect the nodes as a "chain". This allows us | # Connect the nodes as a "chain". This allows us | ||||
# to split the network between nodes 1 and 2 to get | # to split the network between nodes 1 and 2 to get | ||||
# two halves that can work on competing chains. | # two halves that can work on competing chains. | ||||
for i in range(self.num_nodes - 1): | for i in range(self.num_nodes - 1): | ||||
connect_nodes_bi(self.nodes, i, i + 1) | connect_nodes_bi(self.nodes[i], self.nodes[i+1]) | ||||
self.sync_all() | self.sync_all() | ||||
def setup_nodes(self): | def setup_nodes(self): | ||||
"""Override this method to customize test node setup""" | """Override this method to customize test node setup""" | ||||
extra_args = None | extra_args = None | ||||
if hasattr(self, "extra_args"): | if hasattr(self, "extra_args"): | ||||
extra_args = self.extra_args | extra_args = self.extra_args | ||||
self.add_nodes(self.num_nodes, extra_args) | self.add_nodes(self.num_nodes, extra_args) | ||||
self.start_nodes() | self.start_nodes() | ||||
def run_test(self): | def run_test(self): | ||||
"""Tests must override this method to define test logic""" | """Tests must override this method to define test logic""" | ||||
raise NotImplementedError | raise NotImplementedError | ||||
# Public helper methods. These can be accessed by the subclass test scripts. | # Public helper methods. These can be accessed by the subclass test scripts. | ||||
def add_nodes(self, num_nodes, extra_args=None, rpchost=None, timewait=None, binary=None): | def add_nodes(self, num_nodes, extra_args=None, host="127.0.0.1", timewait=None, binary=None): | ||||
"""Instantiate TestNode objects""" | """Instantiate TestNode objects""" | ||||
if extra_args is None: | if extra_args is None: | ||||
extra_args = [[]] * num_nodes | extra_args = [[]] * num_nodes | ||||
if binary is None: | if binary is None: | ||||
binary = [None] * num_nodes | binary = [None] * num_nodes | ||||
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, self.options.tmpdir, extra_args[i], rpchost, timewait=timewait, | self.nodes.append(TestNode(i, self.options.tmpdir, extra_args[i], host, rpc_port(i), p2p_port(i), timewait=timewait, | ||||
binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir)) | binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir)) | ||||
def start_node(self, i, extra_args=None, stderr=None): | def start_node(self, i, extra_args=None, stderr=None): | ||||
"""Start a bitcoind""" | """Start a bitcoind""" | ||||
node = self.nodes[i] | node = self.nodes[i] | ||||
node.start(extra_args, stderr) | node.start(extra_args, stderr) | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | class BitcoinTestFramework(): | ||||
def wait_for_node_exit(self, i, timeout): | def wait_for_node_exit(self, i, timeout): | ||||
self.nodes[i].process.wait(timeout) | self.nodes[i].process.wait(timeout) | ||||
def split_network(self): | def split_network(self): | ||||
""" | """ | ||||
Split the network of four nodes into nodes 0/1 and 2/3. | Split the network of four nodes into nodes 0/1 and 2/3. | ||||
""" | """ | ||||
disconnect_nodes(self.nodes[1], 2) | disconnect_nodes(self.nodes[1], self.nodes[2]) | ||||
disconnect_nodes(self.nodes[2], 1) | disconnect_nodes(self.nodes[2], self.nodes[1]) | ||||
self.sync_all([self.nodes[:2], self.nodes[2:]]) | self.sync_all([self.nodes[:2], self.nodes[2:]]) | ||||
def join_network(self): | def join_network(self): | ||||
""" | """ | ||||
Join the (previously split) network halves together. | Join the (previously split) network halves together. | ||||
""" | """ | ||||
connect_nodes_bi(self.nodes, 1, 2) | connect_nodes_bi(self.nodes[1], self.nodes[2]) | ||||
self.sync_all() | self.sync_all() | ||||
def sync_all(self, node_groups=None): | def sync_all(self, node_groups=None): | ||||
if not node_groups: | if not node_groups: | ||||
node_groups = [self.nodes] | node_groups = [self.nodes] | ||||
for group in node_groups: | for group in node_groups: | ||||
sync_blocks(group) | sync_blocks(group) | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | def _start_logging(self): | ||||
rpc_handler.setLevel(logging.DEBUG) | rpc_handler.setLevel(logging.DEBUG) | ||||
rpc_logger.addHandler(rpc_handler) | rpc_logger.addHandler(rpc_handler) | ||||
def _initialize_chain(self): | def _initialize_chain(self): | ||||
"""Initialize a pre-mined blockchain for use by the test. | """Initialize a pre-mined blockchain for use by the test. | ||||
Create a cache of a 200-block-long chain (with wallet) for MAX_NODES | Create a cache of a 200-block-long chain (with wallet) for MAX_NODES | ||||
Afterward, create num_nodes copies from the cache.""" | Afterward, create num_nodes copies from the cache.""" | ||||
assert self.num_nodes <= MAX_NODES | assert self.num_nodes <= MAX_NODES | ||||
create_cache = False | create_cache = False | ||||
for i in range(MAX_NODES): | for i in range(MAX_NODES): | ||||
if not os.path.isdir(os.path.join(self.options.cachedir, 'node' + str(i))): | if not os.path.isdir(os.path.join(self.options.cachedir, 'node' + str(i))): | ||||
create_cache = True | create_cache = True | ||||
break | break | ||||
if create_cache: | if create_cache: | ||||
self.log.debug("Creating data directories from cached datadir") | self.log.debug("Creating data directories from cached datadir") | ||||
# find and delete old cache directories if any exist | # find and delete old cache directories if any exist | ||||
for i in range(MAX_NODES): | for i in range(MAX_NODES): | ||||
if os.path.isdir(os.path.join(self.options.cachedir, "node" + str(i))): | if os.path.isdir(os.path.join(self.options.cachedir, "node" + str(i))): | ||||
shutil.rmtree(os.path.join( | shutil.rmtree(os.path.join( | ||||
self.options.cachedir, "node" + str(i))) | self.options.cachedir, "node" + str(i))) | ||||
# 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) | ||||
args = [os.getenv("BITCOIND", "bitcoind"), "-server", | args = [os.getenv("BITCOIND", "bitcoind"), "-server", | ||||
"-keypool=1", "-datadir=" + datadir, "-discover=0"] | "-keypool=1", "-datadir=" + datadir, "-discover=0"] | ||||
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, self.options.cachedir, extra_args=[ | self.nodes.append(TestNode(i, self.options.cachedir, [ | ||||
], rpchost=None, timewait=None, binary=None, stderr=None, mocktime=self.mocktime, coverage_dir=None)) | ], None, rpc_port(i), p2p_port(i), timewait=None, binary=None, stderr=None, mocktime=self.mocktime, coverage_dir=None)) | ||||
self.nodes[i].args = args | self.nodes[i].args = args | ||||
self.start_node(i) | self.start_node(i) | ||||
# Wait for RPC connections to be ready | # Wait for RPC connections to be ready | ||||
for node in self.nodes: | for node in self.nodes: | ||||
node.wait_for_rpc_connection() | node.wait_for_rpc_connection() | ||||
# Create a 200-block-long chain; each of the 4 first nodes | # Create a 200-block-long chain; each of the 4 first nodes | ||||
▲ Show 20 Lines • Show All 78 Lines • Show Last 20 Lines |