Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/comptool.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2015-2016 The Bitcoin Core developers | # Copyright (c) 2015-2016 The Bitcoin Core developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
from .mininode import * | from .mininode import * | ||||
from .blockstore import BlockStore, TxStore | from .blockstore import BlockStore, TxStore | ||||
from .util import p2p_port | from .util import p2p_port, wait_until | ||||
import logging | import logging | ||||
logger = logging.getLogger("TestFramework.comptool") | logger = logging.getLogger("TestFramework.comptool") | ||||
''' | ''' | ||||
This is a tool for comparing two or more bitcoinds to each other | This is a tool for comparing two or more bitcoinds to each other | ||||
using a script provided. | using a script provided. | ||||
▲ Show 20 Lines • Show All 183 Lines • ▼ Show 20 Lines | class TestManager(): | ||||
def clear_all_connections(self): | def clear_all_connections(self): | ||||
self.connections = [] | self.connections = [] | ||||
self.test_nodes = [] | self.test_nodes = [] | ||||
def wait_for_disconnections(self): | def wait_for_disconnections(self): | ||||
def disconnected(): | def disconnected(): | ||||
return all(node.closed for node in self.test_nodes) | return all(node.closed for node in self.test_nodes) | ||||
return wait_until(disconnected, timeout=10) | wait_until(disconnected, timeout=10, lock=mininode_lock) | ||||
def wait_for_verack(self): | def wait_for_verack(self): | ||||
return all(node.wait_for_verack() for node in self.test_nodes) | return all(node.wait_for_verack() for node in self.test_nodes) | ||||
def wait_for_pings(self, counter): | def wait_for_pings(self, counter): | ||||
def received_pongs(): | def received_pongs(): | ||||
return all(node.received_ping_response(counter) for node in self.test_nodes) | return all(node.received_ping_response(counter) for node in self.test_nodes) | ||||
return wait_until(received_pongs) | wait_until(received_pongs, lock=mininode_lock) | ||||
# sync_blocks: Wait for all connections to request the blockhash given | # sync_blocks: Wait for all connections to request the blockhash given | ||||
# then send get_headers to find out the tip of each node, and synchronize | # then send get_headers to find out the tip of each node, and synchronize | ||||
# the response by using a ping (and waiting for pong with same nonce). | # the response by using a ping (and waiting for pong with same nonce). | ||||
def sync_blocks(self, blockhash, num_blocks): | def sync_blocks(self, blockhash, num_blocks): | ||||
def blocks_requested(): | def blocks_requested(): | ||||
return all( | return all( | ||||
blockhash in node.block_request_map and node.block_request_map[ | blockhash in node.block_request_map and node.block_request_map[ | ||||
blockhash] | blockhash] | ||||
for node in self.test_nodes | for node in self.test_nodes | ||||
) | ) | ||||
# --> error if not requested | # --> error if not requested | ||||
if not wait_until(blocks_requested, attempts=20 * num_blocks): | wait_until(blocks_requested, attempts=20 * | ||||
raise AssertionError("Not all nodes requested block") | num_blocks, lock=mininode_lock) | ||||
# Send getheaders message | # Send getheaders message | ||||
[c.cb.send_getheaders() for c in self.connections] | [c.cb.send_getheaders() for c in self.connections] | ||||
# Send ping and wait for response -- synchronization hack | # Send ping and wait for response -- synchronization hack | ||||
[c.cb.send_ping(self.ping_counter) for c in self.connections] | [c.cb.send_ping(self.ping_counter) for c in self.connections] | ||||
self.wait_for_pings(self.ping_counter) | self.wait_for_pings(self.ping_counter) | ||||
self.ping_counter += 1 | self.ping_counter += 1 | ||||
# Analogous to sync_block (see above) | # Analogous to sync_block (see above) | ||||
def sync_transaction(self, txhash, num_events): | def sync_transaction(self, txhash, num_events): | ||||
# Wait for nodes to request transaction (50ms sleep * 20 tries * | # Wait for nodes to request transaction (50ms sleep * 20 tries * | ||||
# num_events) | # num_events) | ||||
def transaction_requested(): | def transaction_requested(): | ||||
return all( | return all( | ||||
txhash in node.tx_request_map and node.tx_request_map[txhash] | txhash in node.tx_request_map and node.tx_request_map[txhash] | ||||
for node in self.test_nodes | for node in self.test_nodes | ||||
) | ) | ||||
# --> error if not requested | # --> error if not requested | ||||
if not wait_until(transaction_requested, attempts=20 * num_events): | wait_until(transaction_requested, attempts=20 * | ||||
raise AssertionError("Not all nodes requested transaction") | num_events, lock=mininode_lock) | ||||
# Get the mempool | # Get the mempool | ||||
[c.cb.send_mempool() for c in self.connections] | [c.cb.send_mempool() for c in self.connections] | ||||
# Send ping and wait for response -- synchronization hack | # Send ping and wait for response -- synchronization hack | ||||
[c.cb.send_ping(self.ping_counter) for c in self.connections] | [c.cb.send_ping(self.ping_counter) for c in self.connections] | ||||
self.wait_for_pings(self.ping_counter) | self.wait_for_pings(self.ping_counter) | ||||
self.ping_counter += 1 | self.ping_counter += 1 | ||||
▲ Show 20 Lines • Show All 183 Lines • Show Last 20 Lines |