qa: Improve assert_start_raises_init_error output
What changed, and why it matters
This is a small cleanup in Bitcoin Core's internal test helper code. It changes how an error message is re-raised so that Python no longer prints a confusing 'another exception occurred' chain when a test node fails to start. There is no change to the Bitcoin network protocol, wallet handling, consensus rules, or any production code.
No security action needed. This is a test-framework quality-of-life improvement and can be reviewed as ordinary code maintenance.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch modifies test/functional/test_framework/test_node.py’s assert_start_raises_init_error helper. It moves the _raise_assertion_error call outside the except subprocess.TimeoutExpired block by storing the message in assert_msg and raising afterward. This suppresses Python’s exception chaining output (‘During handling of the above exception, another exception occurred’). It also updates a docstring comment from ‘throw’ to ‘raise’. The behavior of the test assertion itself is unchanged.
Changed components
test/functional/test_framework/test_node.pyInspect captured patch +8 / −3
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index 060a932d..674513bf 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -712,11 +712,12 @@ class TestNode():
extra_args: extra arguments to pass through to bitcoind
expected_msg: regex that stderr should match when bitcoind fails
- Will throw if bitcoind starts without an error.
- Will throw if an expected_msg is provided and it does not match bitcoind's stdout."""
+ Will raise if bitcoind starts without an error.
+ Will raise if an expected_msg is provided and it does not match bitcoind's stdout."""
assert not self.running
with tempfile.NamedTemporaryFile(dir=self.stderr_dir, delete=False) as log_stderr, \
tempfile.NamedTemporaryFile(dir=self.stdout_dir, delete=False) as log_stdout:
+ assert_msg = None
try:
self.start(extra_args, stdout=log_stdout, stderr=log_stderr, *args, **kwargs)
ret = self.process.wait(timeout=self.rpc_timeout)
@@ -740,7 +741,7 @@ class TestNode():
if expected_msg != stderr:
self._raise_assertion_error(
'Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr))
- except subprocess.TimeoutExpired:
+ except subprocess.TimeoutExpired as e:
self.process.kill()
self.running = False
self.process = None
@@ -749,6 +750,10 @@ class TestNode():
assert_msg += "with an error"
else:
assert_msg += "with expected error " + expected_msg
+ assert_msg += f" (cmd: {e.cmd})"
+
+ # Raise assertion outside of except-block above in order for it not to be treated as a knock-on exception.
+ if assert_msg:
self._raise_assertion_error(assert_msg)
def add_p2p_connection(self, p2p_conn, *, wait_for_verack=True, send_version=True, supports_v2_p2p=None, wait_for_v2_handshake=True, expect_success=True, **kwargs):
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.