[tests] fix - use rpc_timeout as rpc timeout
[bitcoinplatinum.git] / test / functional / test_framework / test_node.py
blob4063f988e81dab349f2c465566889520d7f0c295
1 #!/usr/bin/env python3
2 # Copyright (c) 2017 The Bitcoin Core developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 """Class for bitcoind node under test"""
7 import errno
8 import http.client
9 import logging
10 import os
11 import subprocess
12 import time
14 from .util import (
15 assert_equal,
16 get_rpc_proxy,
17 rpc_url,
19 from .authproxy import JSONRPCException
21 class TestNode():
22 """A class for representing a bitcoind node under test.
24 This class contains:
26 - state about the node (whether it's running, etc)
27 - a Python subprocess.Popen object representing the running process
28 - an RPC connection to the node
30 To make things easier for the test writer, a bit of magic is happening under the covers.
31 Any unrecognised messages will be dispatched to the RPC connection."""
33 def __init__(self, i, dirname, extra_args, rpchost, timewait, binary, stderr, mocktime, coverage_dir):
34 self.index = i
35 self.datadir = os.path.join(dirname, "node" + str(i))
36 self.rpchost = rpchost
37 if timewait:
38 self.rpc_timeout = timewait
39 else:
40 # Wait for up to 60 seconds for the RPC server to respond
41 self.rpc_timeout = 60
42 if binary is None:
43 self.binary = os.getenv("BITCOIND", "bitcoind")
44 else:
45 self.binary = binary
46 self.stderr = stderr
47 self.coverage_dir = coverage_dir
48 # Most callers will just need to add extra args to the standard list below. For those callers that need more flexibity, they can just set the args property directly.
49 self.extra_args = extra_args
50 self.args = [self.binary, "-datadir=" + self.datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(mocktime), "-uacomment=testnode%d" % i]
52 self.running = False
53 self.process = None
54 self.rpc_connected = False
55 self.rpc = None
56 self.url = None
57 self.log = logging.getLogger('TestFramework.node%d' % i)
59 def __getattr__(self, *args, **kwargs):
60 """Dispatches any unrecognised messages to the RPC connection."""
61 assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection"
62 return self.rpc.__getattr__(*args, **kwargs)
64 def start(self):
65 """Start the node."""
66 self.process = subprocess.Popen(self.args + self.extra_args, stderr=self.stderr)
67 self.running = True
68 self.log.debug("bitcoind started, waiting for RPC to come up")
70 def wait_for_rpc_connection(self):
71 """Sets up an RPC connection to the bitcoind process. Returns False if unable to connect."""
72 # Poll at a rate of four times per second
73 poll_per_s = 4
74 for _ in range(poll_per_s * self.rpc_timeout):
75 assert self.process.poll() is None, "bitcoind exited with status %i during initialization" % self.process.returncode
76 try:
77 self.rpc = get_rpc_proxy(rpc_url(self.datadir, self.index, self.rpchost), self.index, timeout=self.rpc_timeout, coveragedir=self.coverage_dir)
78 self.rpc.getblockcount()
79 # If the call to getblockcount() succeeds then the RPC connection is up
80 self.rpc_connected = True
81 self.url = self.rpc.url
82 self.log.debug("RPC successfully started")
83 return
84 except IOError as e:
85 if e.errno != errno.ECONNREFUSED: # Port not yet open?
86 raise # unknown IO error
87 except JSONRPCException as e: # Initialization phase
88 if e.error['code'] != -28: # RPC in warmup?
89 raise # unknown JSON RPC exception
90 except ValueError as e: # cookie file not found and no rpcuser or rpcassword. bitcoind still starting
91 if "No RPC credentials" not in str(e):
92 raise
93 time.sleep(1.0 / poll_per_s)
94 raise AssertionError("Unable to connect to bitcoind")
96 def get_wallet_rpc(self, wallet_name):
97 assert self.rpc_connected
98 assert self.rpc
99 wallet_path = "wallet/%s" % wallet_name
100 return self.rpc / wallet_path
102 def stop_node(self):
103 """Stop the node."""
104 if not self.running:
105 return
106 self.log.debug("Stopping node")
107 try:
108 self.stop()
109 except http.client.CannotSendRequest:
110 self.log.exception("Unable to stop node.")
112 def is_node_stopped(self):
113 """Checks whether the node has stopped.
115 Returns True if the node has stopped. False otherwise.
116 This method is responsible for freeing resources (self.process)."""
117 if not self.running:
118 return True
119 return_code = self.process.poll()
120 if return_code is not None:
121 # process has stopped. Assert that it didn't return an error code.
122 assert_equal(return_code, 0)
123 self.running = False
124 self.process = None
125 self.log.debug("Node stopped")
126 return True
127 return False
129 def node_encrypt_wallet(self, passphrase):
130 """"Encrypts the wallet.
132 This causes bitcoind to shutdown, so this method takes
133 care of cleaning up resources."""
134 self.encryptwallet(passphrase)
135 while not self.is_node_stopped():
136 time.sleep(0.1)
137 self.rpc = None
138 self.rpc_connected = False