Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/test_framework.py
Show All 15 Lines | |||||
import time | import time | ||||
import traceback | import traceback | ||||
from .authproxy import JSONRPCException | from .authproxy import JSONRPCException | ||||
from . import coverage | from . import coverage | ||||
from .test_node import TestNode | from .test_node import TestNode | ||||
from .util import ( | from .util import ( | ||||
MAX_NODES, | MAX_NODES, | ||||
PortSeed, | PORT_MIN, | ||||
PORT_RANGE, | |||||
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, | |||||
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 56 Lines • ▼ Show 20 Lines | def main(self): | ||||
help="Attach a python debugger if test fails") | help="Attach a python debugger if test fails") | ||||
self.add_options(parser) | self.add_options(parser) | ||||
self.options = parser.parse_args() | self.options = parser.parse_args() | ||||
self.set_test_params() | self.set_test_params() | ||||
assert hasattr( | assert hasattr( | ||||
self, "num_nodes"), "Test must set self.num_nodes in set_test_params()" | self, "num_nodes"), "Test must set self.num_nodes in set_test_params()" | ||||
PortSeed.n = self.options.port_seed | self.port_seed = self.options.port_seed | ||||
os.environ['PATH'] = self.options.srcdir + ":" + \ | os.environ['PATH'] = self.options.srcdir + ":" + \ | ||||
self.options.srcdir + "/qt:" + os.environ['PATH'] | self.options.srcdir + "/qt:" + os.environ['PATH'] | ||||
check_json_precision() | check_json_precision() | ||||
self.options.cachedir = os.path.abspath(self.options.cachedir) | self.options.cachedir = os.path.abspath(self.options.cachedir) | ||||
▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | def add_nodes(self, num_nodes, extra_args=None, host="127.0.0.1", timewait=None, binary=None): | ||||
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], host, rpc_port(i), p2p_port(i), timewait=timewait, | self.nodes.append(TestNode(i, self.options.tmpdir, extra_args[i], host, self.rpc_port(i), self.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 All 38 Lines | def stop_nodes(self): | ||||
# Wait for nodes to stop | # Wait for nodes to stop | ||||
node.wait_until_stopped() | node.wait_until_stopped() | ||||
def restart_node(self, i, extra_args=None): | def restart_node(self, i, extra_args=None): | ||||
"""Stop and start a test node""" | """Stop and start a test node""" | ||||
self.stop_node(i) | self.stop_node(i) | ||||
self.start_node(i, extra_args) | self.start_node(i, extra_args) | ||||
def rpc_port(self, n): | |||||
return PORT_MIN + PORT_RANGE + n + (MAX_NODES * self.port_seed) % (PORT_RANGE - 1 - MAX_NODES) | |||||
def p2p_port(self, n): | |||||
assert(n <= MAX_NODES) | |||||
return PORT_MIN + n + (MAX_NODES * self.port_seed) % (PORT_RANGE - 1 - MAX_NODES) | |||||
def assert_start_raises_init_error(self, i, extra_args=None, expected_msg=None): | def assert_start_raises_init_error(self, i, extra_args=None, expected_msg=None): | ||||
with tempfile.SpooledTemporaryFile(max_size=2**16) as log_stderr: | with tempfile.SpooledTemporaryFile(max_size=2**16) as log_stderr: | ||||
try: | try: | ||||
self.start_node(i, extra_args, stderr=log_stderr) | self.start_node(i, extra_args, stderr=log_stderr) | ||||
self.stop_node(i) | self.stop_node(i) | ||||
except Exception as e: | except Exception as e: | ||||
assert 'bitcoind exited' in str(e) # node must have shutdown | assert 'bitcoind exited' in str(e) # node must have shutdown | ||||
self.nodes[i].running = False | self.nodes[i].running = False | ||||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | def _initialize_chain(self): | ||||
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( | datadir = initialize_datadir( | ||||
self.options.cachedir, i, p2p_port(i), rpc_port(i)) | self.options.cachedir, i, self.p2p_port(i), self.rpc_port(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(self.p2p_port(0))) | ||||
self.nodes.append(TestNode(i, self.options.cachedir, [ | self.nodes.append(TestNode(i, self.options.cachedir, extra_args=[ | ||||
], None, rpc_port(i), p2p_port(i), timewait=None, binary=None, stderr=None, mocktime=self.mocktime, coverage_dir=None)) | ], host=None, rpc_port=self.rpc_port(i), p2p_port=self.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 All 25 Lines | def _initialize_chain(self): | ||||
self.options.cachedir, i, "fee_estimates.dat")) | self.options.cachedir, i, "fee_estimates.dat")) | ||||
for i in range(self.num_nodes): | for i in range(self.num_nodes): | ||||
from_dir = os.path.join(self.options.cachedir, "node" + str(i)) | from_dir = os.path.join(self.options.cachedir, "node" + str(i)) | ||||
to_dir = os.path.join(self.options.tmpdir, "node" + str(i)) | to_dir = os.path.join(self.options.tmpdir, "node" + str(i)) | ||||
shutil.copytree(from_dir, to_dir) | shutil.copytree(from_dir, to_dir) | ||||
# Overwrite port/rpcport in bitcoin.conf | # Overwrite port/rpcport in bitcoin.conf | ||||
initialize_datadir(self.options.tmpdir, i, | initialize_datadir(self.options.tmpdir, i, | ||||
p2p_port(i), rpc_port(i)) | self.p2p_port(i), self.rpc_port(i)) | ||||
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. | ||||
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, | ||||
p2p_port(i), rpc_port(i)) | self.p2p_port(i), self.rpc_port(i)) | ||||
class ComparisonTestFramework(BitcoinTestFramework): | class ComparisonTestFramework(BitcoinTestFramework): | ||||
"""Test framework for doing p2p comparison testing | """Test framework for doing p2p comparison testing | ||||
Sets up some bitcoind binaries: | Sets up some bitcoind binaries: | ||||
- 1 binary: test binary | - 1 binary: test binary | ||||
- 2 binaries: 1 test binary, 1 ref binary | - 2 binaries: 1 test binary, 1 ref binary | ||||
Show All 29 Lines |