qa: Only complain about expected messages that were not found
What changed, and why it matters
This is a small quality-of-life improvement to Bitcoin Core's internal testing tools. It changes how test error messages are printed so that only the log messages that were actually missing are reported, rather than the whole list. It also avoids rechecking messages that were already found. There is no change to the live Bitcoin network code, wallet, consensus rules, or any user-facing behavior.
No security action needed. Treat as a normal test-framework cleanup commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch modifies two helper context managers in test/functional/test_framework/test_node.py (wait_for_debug_log and wait_for_debug_log_bytes). Previously, the code scanned the entire expected_msgs list on every poll iteration and, on failure, reported the full expected_msgs list. The new code maintains a remaining_expected list, pops found messages, and only reports the messages still missing on timeout. This is purely a test-framework refactor with no functional change to log detection semantics or to node runtime code.
Changed components
test/functional/test_framework/test_node.pyInspect captured patch +12 / −13
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index cf92f926..653d58d0 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -546,6 +546,7 @@ class TestNode():
unexpected_msgs = []
assert_equal(type(expected_msgs), list)
assert_equal(type(unexpected_msgs), list)
+ remaining_expected = list(expected_msgs)
time_end = time.time() + timeout * self.timeout_factor
prev_size = self.debug_log_size(encoding="utf-8") # Must use same encoding that is used to read() below
@@ -556,7 +557,6 @@ class TestNode():
yield
while True:
- found = True
with open(self.debug_log_path, encoding="utf-8", errors="replace") as dl:
dl.seek(prev_size)
log = dl.read()
@@ -564,15 +564,15 @@ class TestNode():
if unexpected_msg in log:
self._raise_assertion_error(f'Unexpected message "{unexpected_msg}" '
f'found in log:\n\n{join_log(log)}\n\n')
- for expected_msg in expected_msgs:
- if expected_msg not in log:
- found = False
- if found:
+ while remaining_expected and remaining_expected[-1] in log:
+ remaining_expected.pop()
+ if not remaining_expected:
return
if time.time() >= time_end:
break
time.sleep(0.05)
- self._raise_assertion_error(f'Expected message(s) {expected_msgs!s} '
+ remaining_expected = [e for e in remaining_expected if e not in log]
+ self._raise_assertion_error(f'Expected message(s) {remaining_expected!s} '
f'not found in log:\n\n{join_log(log)}\n\n')
@contextlib.contextmanager
@@ -582,20 +582,18 @@ class TestNode():
"""
time_end = time.time() + timeout * self.timeout_factor
prev_size = self.debug_log_size(mode="rb") # Must use same mode that is used to read() below
+ remaining_expected = list(expected_msgs)
yield
while True:
- found = True
with open(self.debug_log_path, "rb") as dl:
dl.seek(prev_size)
log = dl.read()
- for expected_msg in expected_msgs:
- if expected_msg not in log:
- found = False
-
- if found:
+ while remaining_expected and remaining_expected[-1] in log:
+ remaining_expected.pop()
+ if not remaining_expected:
return
if time.time() >= time_end:
@@ -605,7 +603,8 @@ class TestNode():
# No sleep here because we want to detect the message fragment as fast as
# possible.
- self._raise_assertion_error(f'Expected message(s) {expected_msgs!s} '
+ remaining_expected = [e for e in remaining_expected if e not in log]
+ self._raise_assertion_error(f'Expected message(s) {remaining_expected!s} '
f'not found in log:\n\n{print_log}\n\n')
@contextlib.contextmanager
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.