Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/test_node.py
Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | class TestNode(): | ||||
- a Python subprocess.Popen object representing the running process | - a Python subprocess.Popen object representing the running process | ||||
- an RPC connection to the node | - an RPC connection to the node | ||||
- one or more P2P connections to the node | - one or more P2P connections to the node | ||||
To make things easier for the test writer, any unrecognised messages will | To make things easier for the test writer, any unrecognised messages will | ||||
be dispatched to the RPC connection.""" | be dispatched to the RPC connection.""" | ||||
def __init__(self, i, datadir, *, chain, host, rpc_port, p2p_port, timewait, bitcoind, bitcoin_cli, | def __init__(self, i, datadir, *, chain, host, rpc_port, p2p_port, timewait, bitcoind, bitcoin_cli, | ||||
coverage_dir, extra_conf=None, extra_args=None, use_cli=False, emulator=None, start_perf=False): | coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, emulator=None, start_perf=False): | ||||
""" | """ | ||||
Kwargs: | Kwargs: | ||||
start_perf (bool): If True, begin profiling the node with `perf` as soon as | start_perf (bool): If True, begin profiling the node with `perf` as soon as | ||||
the node starts. | the node starts. | ||||
""" | """ | ||||
self.index = i | self.index = i | ||||
self.datadir = datadir | self.datadir = datadir | ||||
self.bitcoinconf = os.path.join(self.datadir, "bitcoin.conf") | self.bitcoinconf = os.path.join(self.datadir, "bitcoin.conf") | ||||
self.stdout_dir = os.path.join(self.datadir, "stdout") | self.stdout_dir = os.path.join(self.datadir, "stdout") | ||||
self.stderr_dir = os.path.join(self.datadir, "stderr") | self.stderr_dir = os.path.join(self.datadir, "stderr") | ||||
self.chain = chain | self.chain = chain | ||||
self.host = host | self.host = host | ||||
self.rpc_port = rpc_port | self.rpc_port = rpc_port | ||||
self.p2p_port = p2p_port | self.p2p_port = p2p_port | ||||
self.name = "testnode-{}".format(i) | self.name = "testnode-{}".format(i) | ||||
self.rpc_timeout = timewait | self.rpc_timeout = timewait | ||||
self.binary = bitcoind | self.binary = bitcoind | ||||
if not os.path.isfile(self.binary): | if not os.path.isfile(self.binary): | ||||
raise FileNotFoundError( | raise FileNotFoundError( | ||||
"Binary '{}' could not be found.\nTry setting it manually:\n\tBITCOIND=<path/to/bitcoind> {}".format(self.binary, sys.argv[0])) | "Binary '{}' could not be found.\nTry setting it manually:\n\tBITCOIND=<path/to/bitcoind> {}".format(self.binary, sys.argv[0])) | ||||
self.coverage_dir = coverage_dir | self.coverage_dir = coverage_dir | ||||
self.cwd = cwd | |||||
if extra_conf is not None: | if extra_conf is not None: | ||||
append_config(datadir, extra_conf) | append_config(datadir, extra_conf) | ||||
# Most callers will just need to add extra args to the default list | # Most callers will just need to add extra args to the default list | ||||
# below. | # below. | ||||
# For those callers that need more flexibility, they can access the | # For those callers that need more flexibility, they can access the | ||||
# default args using the provided facilities. | # default args using the provided facilities. | ||||
# Note that common args are set in the config file (see | # Note that common args are set in the config file (see | ||||
# initialize_datadir) | # initialize_datadir) | ||||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | def remove_default_args(self, args): | ||||
# Remove all occurrences of rm_arg in self.default_args: | # Remove all occurrences of rm_arg in self.default_args: | ||||
# - if the arg is a flag (-flag), then the names must match | # - if the arg is a flag (-flag), then the names must match | ||||
# - if the arg is a value (-key=value) then the name must starts | # - if the arg is a value (-key=value) then the name must starts | ||||
# with "-key=" (the '"' char is to avoid removing "-key_suffix" | # with "-key=" (the '"' char is to avoid removing "-key_suffix" | ||||
# arg is "-key" is the argument to remove). | # arg is "-key" is the argument to remove). | ||||
self.default_args = [def_arg for def_arg in self.default_args | self.default_args = [def_arg for def_arg in self.default_args | ||||
if rm_arg != def_arg and not def_arg.startswith(rm_arg + '=')] | if rm_arg != def_arg and not def_arg.startswith(rm_arg + '=')] | ||||
def start(self, extra_args=None, *, stdout=None, | def start(self, extra_args=None, *, cwd=None, stdout=None, | ||||
stderr=None, **kwargs): | stderr=None, **kwargs): | ||||
"""Start the node.""" | """Start the node.""" | ||||
if extra_args is None: | if extra_args is None: | ||||
extra_args = self.extra_args | extra_args = self.extra_args | ||||
# Add a new stdout and stderr file each time bitcoind is started | # Add a new stdout and stderr file each time bitcoind is started | ||||
if stderr is None: | if stderr is None: | ||||
stderr = tempfile.NamedTemporaryFile( | stderr = tempfile.NamedTemporaryFile( | ||||
dir=self.stderr_dir, delete=False) | dir=self.stderr_dir, delete=False) | ||||
if stdout is None: | if stdout is None: | ||||
stdout = tempfile.NamedTemporaryFile( | stdout = tempfile.NamedTemporaryFile( | ||||
dir=self.stdout_dir, delete=False) | dir=self.stdout_dir, delete=False) | ||||
self.stderr = stderr | self.stderr = stderr | ||||
self.stdout = stdout | self.stdout = stdout | ||||
if cwd is None: | |||||
cwd = self.cwd | |||||
# Delete any existing cookie file -- if such a file exists (eg due to | # Delete any existing cookie file -- if such a file exists (eg due to | ||||
# unclean shutdown), it will get overwritten anyway by bitcoind, and | # unclean shutdown), it will get overwritten anyway by bitcoind, and | ||||
# potentially interfere with our attempt to authenticate | # potentially interfere with our attempt to authenticate | ||||
delete_cookie_file(self.datadir, self.chain) | delete_cookie_file(self.datadir, self.chain) | ||||
# add environment variable LIBC_FATAL_STDERR_=1 so that libc errors are | # add environment variable LIBC_FATAL_STDERR_=1 so that libc errors are | ||||
# written to stderr and not the terminal | # written to stderr and not the terminal | ||||
subp_env = dict(os.environ, LIBC_FATAL_STDERR_="1") | subp_env = dict(os.environ, LIBC_FATAL_STDERR_="1") | ||||
p_args = [self.binary] + self.default_args + extra_args | p_args = [self.binary] + self.default_args + extra_args | ||||
if self.emulator is not None: | if self.emulator is not None: | ||||
p_args = [self.emulator] + p_args | p_args = [self.emulator] + p_args | ||||
self.process = subprocess.Popen( | self.process = subprocess.Popen( | ||||
p_args, | p_args, | ||||
env=subp_env, | env=subp_env, | ||||
stdout=stdout, | stdout=stdout, | ||||
stderr=stderr, | stderr=stderr, | ||||
cwd=cwd, | |||||
**kwargs) | **kwargs) | ||||
self.running = True | self.running = True | ||||
self.log.debug("bitcoind started, waiting for RPC to come up") | self.log.debug("bitcoind started, waiting for RPC to come up") | ||||
if self.start_perf: | if self.start_perf: | ||||
self._start_perf() | self._start_perf() | ||||
▲ Show 20 Lines • Show All 442 Lines • Show Last 20 Lines |