qa: Improve suppressed errors output

Original discussion: https://github.com/bitcoin/bitcoin/pull/30660#discussion_r2080132673
This commit is contained in:
Hodlinator 2025-05-14 14:40:15 +02:00
parent 075352ec8e
commit bf950c4544
No known key found for this signature in database
2 changed files with 11 additions and 9 deletions

View File

@ -89,7 +89,7 @@ class FeatureFrameworkStartupFailures(BitcoinTestFramework):
self.log.info("Verifying inability to connect to bitcoind's RPC interface due to wrong port results in one exception containing at least one OSError.") self.log.info("Verifying inability to connect to bitcoind's RPC interface due to wrong port results in one exception containing at least one OSError.")
self._verify_startup_failure( self._verify_startup_failure(
TestWrongRpcPortStartupFailure, [f"--internal_node_start_duration={node_start_duration}"], TestWrongRpcPortStartupFailure, [f"--internal_node_start_duration={node_start_duration}"],
r"AssertionError: \[node 0\] Unable to connect to bitcoind after \d+s \(ignored errors: {[^}]*'OSError \w+'?: \d+[^}]*}, latest error: \w+\([^)]+\)\)" r"AssertionError: \[node 0\] Unable to connect to bitcoind after \d+s \(ignored errors: {[^}]*'OSError \w+'?: \d+[^}]*}, latest: '[\w ]+'/\w+\([^)]+\)\)"
) )
self.log.info("Verifying startup failure due to invalid arg results in only one exception.") self.log.info("Verifying startup failure due to invalid arg results in only one exception.")

View File

@ -263,8 +263,13 @@ class TestNode():
"""Sets up an RPC connection to the bitcoind process. Returns False if unable to connect.""" """Sets up an RPC connection to the bitcoind process. Returns False if unable to connect."""
# Poll at a rate of four times per second # Poll at a rate of four times per second
poll_per_s = 4 poll_per_s = 4
suppressed_errors = collections.defaultdict(int) suppressed_errors = collections.defaultdict(int)
latest_error = "" latest_error = None
def suppress_error(category: str, e: Exception):
suppressed_errors[category] += 1
return (category, repr(e))
for _ in range(poll_per_s * self.rpc_timeout): for _ in range(poll_per_s * self.rpc_timeout):
if self.process.poll() is not None: if self.process.poll() is not None:
# Attach abrupt shutdown error/s to the exception message # Attach abrupt shutdown error/s to the exception message
@ -318,8 +323,7 @@ class TestNode():
# -342 Service unavailable, could be starting up or shutting down # -342 Service unavailable, could be starting up or shutting down
if e.error['code'] not in [-28, -342]: if e.error['code'] not in [-28, -342]:
raise # unknown JSON RPC exception raise # unknown JSON RPC exception
suppressed_errors[f"JSONRPCException {e.error['code']}"] += 1 latest_error = suppress_error(f"JSONRPCException {e.error['code']}", e)
latest_error = repr(e)
except OSError as e: except OSError as e:
error_num = e.errno error_num = e.errno
# Work around issue where socket timeouts don't have errno set. # Work around issue where socket timeouts don't have errno set.
@ -335,16 +339,14 @@ class TestNode():
errno.ECONNREFUSED # Port not yet open? errno.ECONNREFUSED # Port not yet open?
]: ]:
raise # unknown OS error raise # unknown OS error
suppressed_errors[f"OSError {errno.errorcode[error_num]}"] += 1 latest_error = suppress_error(f"OSError {errno.errorcode[error_num]}", e)
latest_error = repr(e)
except ValueError as e: except ValueError as e:
# Suppress if cookie file isn't generated yet and no rpcuser or rpcpassword; bitcoind may be starting. # Suppress if cookie file isn't generated yet and no rpcuser or rpcpassword; bitcoind may be starting.
if "No RPC credentials" not in str(e): if "No RPC credentials" not in str(e):
raise raise
suppressed_errors["missing_credentials"] += 1 latest_error = suppress_error("missing_credentials", e)
latest_error = repr(e)
time.sleep(1.0 / poll_per_s) time.sleep(1.0 / poll_per_s)
self._raise_assertion_error(f"Unable to connect to bitcoind after {self.rpc_timeout}s (ignored errors: {str(dict(suppressed_errors))}, latest error: {latest_error})") self._raise_assertion_error(f"Unable to connect to bitcoind after {self.rpc_timeout}s (ignored errors: {dict(suppressed_errors)!s}{'' if latest_error is None else f', latest: {latest_error[0]!r}/{latest_error[1]}'})")
def wait_for_cookie_credentials(self): def wait_for_cookie_credentials(self):
"""Ensures auth cookie credentials can be read, e.g. for testing CLI with -rpcwait before RPC connection is up.""" """Ensures auth cookie credentials can be read, e.g. for testing CLI with -rpcwait before RPC connection is up."""