From b970cdf20fce43fb58dde1cbf713e97ff21d7a2e Mon Sep 17 00:00:00 2001 From: Ryan Ofsky Date: Wed, 14 Jan 2026 08:37:37 -0500 Subject: [PATCH] test framework: expand expected_stderr, expected_ret_code options Allow `expected_stderr` option passed to `wait_until_stopped` and `is_node_stopped` helper functions to be a regex pattern instead of just a fixed string. Allow `expected_ret_code` be list of possible exit codes instead of a single error code to handle the case where exit codes vary depending on OS and libc. --- test/functional/test_framework/test_node.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index b56cf64ce99..89665ab232f 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -22,6 +22,7 @@ import collections import shlex import shutil import sys +from collections.abc import Iterable from pathlib import Path from .authproxy import ( @@ -469,6 +470,12 @@ class TestNode(): """Checks whether the node has stopped. Returns True if the node has stopped. False otherwise. + + If the process has exited, asserts that the exit code matches + `expected_ret_code` (which may be a single value or an iterable of values), + and that stderr matches `expected_stderr` exactly or, if a regex pattern is + provided, contains the pattern. + This method is responsible for freeing resources (self.process).""" if not self.running: return True @@ -477,12 +484,17 @@ class TestNode(): return False # process has stopped. Assert that it didn't return an error code. - assert return_code == expected_ret_code, self._node_msg( + if not isinstance(expected_ret_code, Iterable): + expected_ret_code = (expected_ret_code,) + assert return_code in expected_ret_code, self._node_msg( f"Node returned unexpected exit code ({return_code}) vs ({expected_ret_code}) when stopping") # Check that stderr is as expected self.stderr.seek(0) stderr = self.stderr.read().decode('utf-8').strip() - if stderr != expected_stderr: + if isinstance(expected_stderr, re.Pattern): + if not expected_stderr.search(stderr): + raise AssertionError(f"Unexpected stderr {stderr!r} does not contain {expected_stderr.pattern!r}") + elif stderr != expected_stderr: raise AssertionError("Unexpected stderr {} != {}".format(stderr, expected_stderr)) self.stdout.close()