Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/test_framework.py
Show All 26 Lines | from .util import ( | ||||
connect_nodes, | connect_nodes, | ||||
disconnect_nodes, | disconnect_nodes, | ||||
get_datadir_path, | get_datadir_path, | ||||
initialize_datadir, | initialize_datadir, | ||||
MAX_NODES, | MAX_NODES, | ||||
p2p_port, | p2p_port, | ||||
PortSeed, | PortSeed, | ||||
rpc_port, | rpc_port, | ||||
sync_blocks, | |||||
sync_mempools, | |||||
) | ) | ||||
class TestStatus(Enum): | class TestStatus(Enum): | ||||
PASSED = 1 | PASSED = 1 | ||||
FAILED = 2 | FAILED = 2 | ||||
SKIPPED = 3 | SKIPPED = 3 | ||||
▲ Show 20 Lines • Show All 479 Lines • ▼ Show 20 Lines | class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): | ||||
def join_network(self): | def join_network(self): | ||||
""" | """ | ||||
Join the (previously split) network halves together. | Join the (previously split) network halves together. | ||||
""" | """ | ||||
connect_nodes(self.nodes[1], self.nodes[2]) | connect_nodes(self.nodes[1], self.nodes[2]) | ||||
self.sync_all() | self.sync_all() | ||||
def sync_blocks(self, nodes=None, **kwargs): | def sync_blocks(self, nodes=None, wait=1, timeout=60): | ||||
sync_blocks(nodes or self.nodes, **kwargs) | """ | ||||
Wait until everybody has the same tip. | |||||
sync_blocks needs to be called with an rpc_connections set that has least | |||||
one node already synced to the latest, stable tip, otherwise there's a | |||||
chance it might return before all nodes are stably synced. | |||||
""" | |||||
rpc_connections = nodes or self.nodes | |||||
timeout = int(timeout * self.options.timeout_factor) | |||||
stop_time = time.time() + timeout | |||||
while time.time() <= stop_time: | |||||
best_hash = [x.getbestblockhash() for x in rpc_connections] | |||||
if best_hash.count(best_hash[0]) == len(rpc_connections): | |||||
return | |||||
# Check that each peer has at least one connection | |||||
assert (all([len(x.getpeerinfo()) for x in rpc_connections])) | |||||
time.sleep(wait) | |||||
raise AssertionError("Block sync timed out after {}s:{}".format( | |||||
timeout, | |||||
"".join("\n {!r}".format(b) for b in best_hash), | |||||
)) | |||||
def sync_mempools(self, nodes=None, **kwargs): | def sync_mempools(self, nodes=None, wait=1, timeout=60, | ||||
sync_mempools(nodes or self.nodes, **kwargs) | flush_scheduler=True): | ||||
""" | |||||
Wait until everybody has the same transactions in their memory | |||||
pools | |||||
""" | |||||
rpc_connections = nodes or self.nodes | |||||
timeout = int(timeout * self.options.timeout_factor) | |||||
stop_time = time.time() + timeout | |||||
while time.time() <= stop_time: | |||||
pool = [set(r.getrawmempool()) for r in rpc_connections] | |||||
if pool.count(pool[0]) == len(rpc_connections): | |||||
if flush_scheduler: | |||||
for r in rpc_connections: | |||||
r.syncwithvalidationinterfacequeue() | |||||
return | |||||
# Check that each peer has at least one connection | |||||
assert (all([len(x.getpeerinfo()) for x in rpc_connections])) | |||||
time.sleep(wait) | |||||
raise AssertionError("Mempool sync timed out after {}s:{}".format( | |||||
timeout, | |||||
"".join("\n {!r}".format(m) for m in pool), | |||||
)) | |||||
def sync_all(self, nodes=None, **kwargs): | def sync_all(self, nodes=None): | ||||
self.sync_blocks(nodes, **kwargs) | self.sync_blocks(nodes) | ||||
self.sync_mempools(nodes, **kwargs) | self.sync_mempools(nodes) | ||||
# Private helper methods. These should not be accessed by the subclass | # Private helper methods. These should not be accessed by the subclass | ||||
# test scripts. | # test scripts. | ||||
def _start_logging(self): | def _start_logging(self): | ||||
# Add logger and logging handlers | # Add logger and logging handlers | ||||
self.log = logging.getLogger('TestFramework') | self.log = logging.getLogger('TestFramework') | ||||
self.log.setLevel(logging.DEBUG) | self.log.setLevel(logging.DEBUG) | ||||
▲ Show 20 Lines • Show All 170 Lines • Show Last 20 Lines |