diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -22,7 +22,6 @@ from .messages import COIN, CTransaction, FromHex from .util import ( append_config, - assert_equal, delete_cookie_file, get_rpc_proxy, p2p_port, @@ -107,6 +106,14 @@ self.cleanup_on_exit = True self.p2ps = [] + def _node_msg(self, msg: str) -> str: + """Return a modified msg that identifies this node by its index as a debugging aid.""" + return "[node {}] {}".format(self.index, msg) + + def _raise_assertion_error(self, msg: str): + """Raise an AssertionError with msg modified to identify this node.""" + raise AssertionError(self._node_msg(msg)) + def __del__(self): # Ensure that we don't leave any bitcoind processes lying around after # the test ends @@ -114,7 +121,7 @@ # Should only happen on test failure # Avoid using logger, as that may have already been shutdown when # this destructor is called. - print("Cleaning up leftover process") + print(self._node_msg("Cleaning up leftover process")) self.process.kill() def __getattr__(self, name): @@ -122,8 +129,10 @@ if self.use_cli: return getattr(self.cli, name) else: - assert self.rpc is not None, "Error: RPC not initialized" - assert self.rpc_connected, "Error: No RPC connection" + assert self.rpc is not None, self._node_msg( + "Error: RPC not initialized") + assert self.rpc_connected, self._node_msg( + "Error: No RPC connection") return getattr(self.rpc, name) def clear_default_args(self): @@ -177,8 +186,8 @@ poll_per_s = 4 for _ in range(poll_per_s * self.rpc_timeout): if self.process.poll() is not None: - raise FailedToStartError( - 'bitcoind exited with status {} during initialization'.format(self.process.returncode)) + raise FailedToStartError(self._node_msg( + 'bitcoind exited with status {} during initialization'.format(self.process.returncode))) try: self.rpc = get_rpc_proxy(rpc_url(self.datadir, self.host, self.rpc_port), self.index, timeout=self.rpc_timeout, coveragedir=self.coverage_dir) @@ -198,14 +207,16 @@ if "No RPC credentials" not in str(e): raise time.sleep(1.0 / poll_per_s) - raise AssertionError("Unable to connect to bitcoind") + self._raise_assertion_error("Unable to connect to bitcoind") def get_wallet_rpc(self, wallet_name): if self.use_cli: return self.cli("-rpcwallet={}".format(wallet_name)) else: - assert self.rpc_connected - assert self.rpc + assert self.rpc is not None, self._node_msg( + "Error: RPC not initialized") + assert self.rpc_connected, self._node_msg( + "Error: RPC not connected") wallet_path = "wallet/{}".format(wallet_name) return self.rpc / wallet_path @@ -240,7 +251,8 @@ return False # process has stopped. Assert that it didn't return an error code. - assert_equal(return_code, 0) + assert return_code == 0, self._node_msg( + "Node returned non-zero exit code ({}) when stopping".format(return_code)) self.running = False self.process = None self.rpc_connected = False @@ -295,22 +307,22 @@ stderr = log_stderr.read().decode('utf-8').strip() if match == ErrorMatch.PARTIAL_REGEX: if re.search(expected_msg, stderr, flags=re.MULTILINE) is None: - raise AssertionError( + self._raise_assertion_error( 'Expected message "{}" does not partially match stderr:\n"{}"'.format(expected_msg, stderr)) elif match == ErrorMatch.FULL_REGEX: if re.fullmatch(expected_msg, stderr) is None: - raise AssertionError( + self._raise_assertion_error( 'Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr)) elif match == ErrorMatch.FULL_TEXT: if expected_msg != stderr: - raise AssertionError( + self._raise_assertion_error( 'Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr)) else: if expected_msg is None: assert_msg = "bitcoind should have exited with an error" else: assert_msg = "bitcoind should have exited with expected error " + expected_msg - raise AssertionError(assert_msg) + self._raise_assertion_error(assert_msg) def node_encrypt_wallet(self, passphrase): """"Encrypts the wallet. @@ -364,7 +376,7 @@ Convenience property - most tests only use a single p2p connection to each node, so this saves having to write node.p2ps[0] many times.""" - assert self.p2ps, "No p2p connection" + assert self.p2ps, self._node_msg("No p2p connection") return self.p2ps[0] def disconnect_p2ps(self):