Changeset View
Standalone View
test/functional/test_framework/util.py
Show First 20 Lines • Show All 264 Lines • ▼ Show 20 Lines | |||||
# The maximum number of nodes a single test can spawn | # The maximum number of nodes a single test can spawn | ||||
MAX_NODES = 8 | MAX_NODES = 8 | ||||
# Don't assign rpc or p2p ports lower than this | # Don't assign rpc or p2p ports lower than this | ||||
PORT_MIN = 11000 | PORT_MIN = 11000 | ||||
# The number of ports to "reserve" for p2p and rpc, each | # The number of ports to "reserve" for p2p and rpc, each | ||||
PORT_RANGE = 5000 | PORT_RANGE = 5000 | ||||
class PortSeed: | |||||
schancel: The point of this diff is to remove this guy. | |||||
# Must be initialized with a unique integer for each process | |||||
n = None | |||||
def get_rpc_proxy(url, node_number, timeout=None, coveragedir=None): | def get_rpc_proxy(url, node_number, timeout=None, coveragedir=None): | ||||
""" | """ | ||||
Args: | Args: | ||||
url (str): URL of the RPC server to call | url (str): URL of the RPC server to call | ||||
node_number (int): the node number (or id) that this calls to | node_number (int): the node number (or id) that this calls to | ||||
Kwargs: | Kwargs: | ||||
timeout (int): HTTP timeout in seconds | timeout (int): HTTP timeout in seconds | ||||
Show All 10 Lines | def get_rpc_proxy(url, node_number, timeout=None, coveragedir=None): | ||||
proxy.url = url # store URL on proxy for info | proxy.url = url # store URL on proxy for info | ||||
coverage_logfile = coverage.get_filename( | coverage_logfile = coverage.get_filename( | ||||
coveragedir, node_number) if coveragedir else None | coveragedir, node_number) if coveragedir else None | ||||
return coverage.AuthServiceProxyWrapper(proxy, coverage_logfile) | return coverage.AuthServiceProxyWrapper(proxy, coverage_logfile) | ||||
def p2p_port(n): | def rpc_url(datadir, i, rpchost, rpc_port): | ||||
schancelUnsubmitted Done Inline ActionsThis was simplified so there isn't a need to construct a string to specify the port. The port now needs to be passed in because rpc_port is attached to BitcoinTestFramework schancel: This was simplified so there isn't a need to construct a string to specify the port. The port… | |||||
assert(n <= MAX_NODES) | |||||
return PORT_MIN + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES) | |||||
def rpc_port(n): | |||||
return PORT_MIN + PORT_RANGE + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES) | |||||
def rpc_url(datadir, i, rpchost=None): | |||||
rpc_u, rpc_p = get_auth_cookie(datadir) | rpc_u, rpc_p = get_auth_cookie(datadir) | ||||
host = '127.0.0.1' | host = '127.0.0.1' | ||||
port = rpc_port(i) | |||||
if rpchost: | if rpchost: | ||||
parts = rpchost.split(':') | |||||
if len(parts) == 2: | |||||
host, port = parts | |||||
else: | |||||
host = rpchost | host = rpchost | ||||
return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, host, int(port)) | return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, host, int(rpc_port)) | ||||
# Node functions | # Node functions | ||||
################ | ################ | ||||
def initialize_datadir(dirname, n): | def initialize_datadir(dirname, n, p2p_port, rpc_port): | ||||
schancelUnsubmitted Done Inline ActionsRequire the ports to be passed in as we don't have access to a BitcoinTestFramework instance, nor do I think it makes sense to pass one in. schancel: Require the ports to be passed in as we don't have access to a `BitcoinTestFramework` instance… | |||||
datadir = os.path.join(dirname, "node" + str(n)) | datadir = os.path.join(dirname, "node" + str(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("regtest=1\n") | ||||
f.write("port=" + str(p2p_port(n)) + "\n") | f.write("port=" + str(p2p_port) + "\n") | ||||
f.write("rpcport=" + str(rpc_port(n)) + "\n") | f.write("rpcport=" + str(rpc_port) + "\n") | ||||
f.write("listenonion=0\n") | f.write("listenonion=0\n") | ||||
f.write("usecashaddr=1\n") | f.write("usecashaddr=1\n") | ||||
return datadir | return datadir | ||||
def get_datadir_path(dirname, n): | def get_datadir_path(dirname, n): | ||||
return os.path.join(dirname, "node" + str(n)) | return os.path.join(dirname, "node" + str(n)) | ||||
Show All 30 Lines | def get_bip9_status(node, key): | ||||
return info['bip9_softforks'][key] | return info['bip9_softforks'][key] | ||||
def set_node_times(nodes, t): | def set_node_times(nodes, t): | ||||
for node in nodes: | for node in nodes: | ||||
node.setmocktime(t) | node.setmocktime(t) | ||||
def disconnect_nodes(from_connection, node_num): | def disconnect_nodes(from_connection, node): | ||||
schancelUnsubmitted Done Inline ActionsThis change could probably be separated out. I made it because I wasn't sure if something had gotten messed up elsewhere with string formatting. schancel: This change could probably be separated out. I made it because I wasn't sure if something had… | |||||
jasonbcoxUnsubmitted Not Done Inline ActionsYes, please separate it out. This diff is big enough as it is. jasonbcox: Yes, please separate it out. This diff is big enough as it is. | |||||
for peer_id in [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']]: | for peer_id in [peer['id'] for peer in from_connection.getpeerinfo() if node.nodename in peer['subver']]: | ||||
from_connection.disconnectnode(nodeid=peer_id) | from_connection.disconnectnode(nodeid=peer_id) | ||||
for _ in range(50): | for _ in range(50): | ||||
if [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']] == []: | if [peer['id'] for peer in from_connection.getpeerinfo() if node.nodename in peer['subver']] == []: | ||||
break | break | ||||
time.sleep(0.1) | time.sleep(0.1) | ||||
else: | else: | ||||
raise AssertionError("timed out waiting for disconnect") | raise AssertionError("timed out waiting for disconnect") | ||||
def connect_nodes(from_connection, node_num): | def connect_nodes(from_connection, node): | ||||
schancelUnsubmitted Done Inline ActionsSwitch from node_num to node. We store the port there so we can disconnect/connect nodes. An Alternative would be to take a BitcoinTestFramework, or make this a method there. I think this is the best option, but requires a lot of tests to change. schancel: Switch from `node_num` to `node`. We store the port there so we can disconnect/connect nodes. | |||||
ip_port = "127.0.0.1:" + str(p2p_port(node_num)) | ip_port = "{}:{}".format(node.host, node.p2p_port) | ||||
from_connection.addnode(ip_port, "onetry") | from_connection.addnode(ip_port, "onetry") | ||||
# poll until version handshake complete to avoid race conditions | # poll until version handshake complete to avoid race conditions | ||||
# with transaction relaying | # with transaction relaying | ||||
while any(peer['version'] == 0 for peer in from_connection.getpeerinfo()): | while any(peer['version'] == 0 for peer in from_connection.getpeerinfo()): | ||||
time.sleep(0.1) | time.sleep(0.1) | ||||
def connect_nodes_bi(nodes, a, b): | def connect_nodes_bi(a, b): | ||||
connect_nodes(nodes[a], b) | connect_nodes(a, b) | ||||
connect_nodes(nodes[b], a) | connect_nodes(b, a) | ||||
def sync_blocks(rpc_connections, *, wait=1, timeout=60): | def sync_blocks(rpc_connections, *, wait=1, timeout=60): | ||||
""" | """ | ||||
Wait until everybody has the same tip. | Wait until everybody has the same tip. | ||||
sync_blocks needs to be called with an rpc_connections set that has least | 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 | one node already synced to the latest, stable tip, otherwise there's a | ||||
▲ Show 20 Lines • Show All 222 Lines • Show Last 20 Lines |
The point of this diff is to remove this guy.