Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/test_node.py
Show First 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | PRIV_KEYS = [ | ||||
'cPiRWE8KMjTRxH1MWkPerhfoHFn5iHPWVK5aPqjW8NxmdwenFinJ'), | 'cPiRWE8KMjTRxH1MWkPerhfoHFn5iHPWVK5aPqjW8NxmdwenFinJ'), | ||||
] | ] | ||||
def get_deterministic_priv_key(self): | def get_deterministic_priv_key(self): | ||||
"""Return a deterministic priv key in base58, that only depends on the node's index""" | """Return a deterministic priv key in base58, that only depends on the node's index""" | ||||
assert len(self.PRIV_KEYS) == MAX_NODES | assert len(self.PRIV_KEYS) == MAX_NODES | ||||
return self.PRIV_KEYS[self.index] | return self.PRIV_KEYS[self.index] | ||||
def get_mem_rss(self): | |||||
"""Get the memory usage (RSS) per `ps`. | |||||
If process is stopped or `ps` is unavailable, return None. | |||||
""" | |||||
if not (self.running and self.process): | |||||
self.log.warning( | |||||
"Couldn't get memory usage; process isn't running.") | |||||
return None | |||||
try: | |||||
return int(subprocess.check_output( | |||||
"ps h -o rss {}".format(self.process.pid), | |||||
shell=True, stderr=subprocess.DEVNULL).strip()) | |||||
# Catching `Exception` broadly to avoid failing on platforms where ps | |||||
# isn't installed or doesn't work as expected, e.g. OpenBSD. | |||||
# | |||||
# We could later use something like `psutils` to work across platforms. | |||||
except Exception: | |||||
self.log.exception("Unable to get memory usage") | |||||
return None | |||||
def _node_msg(self, msg: str) -> str: | def _node_msg(self, msg: str) -> str: | ||||
"""Return a modified msg that identifies this node by its index as a debugging aid.""" | """Return a modified msg that identifies this node by its index as a debugging aid.""" | ||||
return "[node {}] {}".format(self.index, msg) | return "[node {}] {}".format(self.index, msg) | ||||
def _raise_assertion_error(self, msg: str): | def _raise_assertion_error(self, msg: str): | ||||
"""Raise an AssertionError with msg modified to identify this node.""" | """Raise an AssertionError with msg modified to identify this node.""" | ||||
raise AssertionError(self._node_msg(msg)) | raise AssertionError(self._node_msg(msg)) | ||||
▲ Show 20 Lines • Show All 221 Lines • ▼ Show 20 Lines | def assert_debug_log(self, expected_msgs, unexpected_msgs=None, timeout=2): | ||||
return | return | ||||
if time.time() >= time_end: | if time.time() >= time_end: | ||||
break | break | ||||
time.sleep(0.05) | time.sleep(0.05) | ||||
self._raise_assertion_error( | self._raise_assertion_error( | ||||
'Expected messages "{}" does not partially match log:\n\n{}\n\n'.format( | 'Expected messages "{}" does not partially match log:\n\n{}\n\n'.format( | ||||
str(expected_msgs), print_log)) | str(expected_msgs), print_log)) | ||||
@contextlib.contextmanager | |||||
def assert_memory_usage_stable(self, perc_increase_allowed=0.03): | |||||
"""Context manager that allows the user to assert that a node's memory usage (RSS) | |||||
hasn't increased beyond some threshold percentage. | |||||
""" | |||||
before_memory_usage = self.get_mem_rss() | |||||
yield | |||||
after_memory_usage = self.get_mem_rss() | |||||
if not (before_memory_usage and after_memory_usage): | |||||
self.log.warning( | |||||
"Unable to detect memory usage (RSS) - skipping memory check.") | |||||
return | |||||
perc_increase_memory_usage = 1 - \ | |||||
(float(before_memory_usage) / after_memory_usage) | |||||
if perc_increase_memory_usage > perc_increase_allowed: | |||||
self._raise_assertion_error( | |||||
"Memory usage increased over threshold of {:.3f}% from {} to {} ({:.3f}%)".format( | |||||
perc_increase_allowed * 100, before_memory_usage, after_memory_usage, | |||||
perc_increase_memory_usage * 100)) | |||||
def assert_start_raises_init_error( | def assert_start_raises_init_error( | ||||
self, extra_args=None, expected_msg=None, match=ErrorMatch.FULL_TEXT, *args, **kwargs): | self, extra_args=None, expected_msg=None, match=ErrorMatch.FULL_TEXT, *args, **kwargs): | ||||
"""Attempt to start the node and expect it to raise an error. | """Attempt to start the node and expect it to raise an error. | ||||
extra_args: extra arguments to pass through to bitcoind | extra_args: extra arguments to pass through to bitcoind | ||||
expected_msg: regex that stderr should match when bitcoind fails | expected_msg: regex that stderr should match when bitcoind fails | ||||
Will throw if bitcoind starts without an error. | Will throw if bitcoind starts without an error. | ||||
▲ Show 20 Lines • Show All 178 Lines • Show Last 20 Lines |