diff --git a/cardano_node_tests/utils/logfiles.py b/cardano_node_tests/utils/logfiles.py index 96f994a63..4723c5d5b 100644 --- a/cardano_node_tests/utils/logfiles.py +++ b/cardano_node_tests/utils/logfiles.py @@ -93,19 +93,33 @@ def _warn_once(message: str) -> None: # * Workaround for node issue https://github.com/IntersectMBO/cardano-node/issues/4369 # "MAIN THREAD FAILED" -if (os.environ.get("GITHUB_ACTIONS") or "").lower() == "true": - # We sometimes see this error on CI. It seems time is not synced properly on GitHub runners. - ERRORS_IGNORED.append("TraceBlockFromFuture") - -if cluster_nodes.get_cluster_type().type == cluster_nodes.ClusterType.TESTNET: - ERRORS_IGNORED.extend( - ( - # We can get this error when some clients are old, or are using wrong - # network magic. - "TrHandshakeClientError", - "TracePromoteWarmBigLedgerPeerAborted", + +def _get_ignored_error_regexes() -> list[str]: + """Return regexes of errors that are ignored in all log files. + + The environment-specific regexes are added lazily, so the cluster type is + determined on first use rather than at import time, and the module doesn't + mutate `ERRORS_IGNORED` on import. + """ + errors_ignored = list(ERRORS_IGNORED) + + if (os.environ.get("GITHUB_ACTIONS") or "").lower() == "true": + # We sometimes see this error on CI. It seems time is not synced properly + # on GitHub runners. + errors_ignored.append("TraceBlockFromFuture") + + if cluster_nodes.get_cluster_type().type == cluster_nodes.ClusterType.TESTNET: + errors_ignored.extend( + ( + # We can get this error when some clients are old, or are using wrong + # network magic. + "TrHandshakeClientError", + "TracePromoteWarmBigLedgerPeerAborted", + ) ) - ) + + return errors_ignored + # Errors that are ignored if there are expected messages in the log file before the error ERRORS_LOOK_BACK_LINES = 10 @@ -1029,6 +1043,8 @@ def _search( look_back_map=ERRORS_LOOK_BACK_MAP, ) + ignored_error_regexes = _get_ignored_error_regexes() + with locking.FileLockIfXdist(lock_file): errors = [] for logfile in cluster_env.state_dir.glob("*.std*"): @@ -1045,7 +1061,7 @@ def _search( # the whole file is going to be searched and the rules apply to all of it. ignore_rules = _get_ignore_rules(cluster_env=cluster_env, timestamp=timestamp) errors_ignored = _get_ignore_regex( - ignore_rules=ignore_rules, regexes=ERRORS_IGNORED, logfile=logfile + ignore_rules=ignore_rules, regexes=ignored_error_regexes, logfile=logfile ) # Search for errors in the log file diff --git a/framework_tests/test_logfiles.py b/framework_tests/test_logfiles.py index 62bea5270..85a78a25e 100644 --- a/framework_tests/test_logfiles.py +++ b/framework_tests/test_logfiles.py @@ -1036,3 +1036,53 @@ def test_rotated_logs_mtime_tiebreak(tmp_path: pl.Path): records = logfiles._get_rotated_logs(logfile=logfile, seek=0, timestamp=0.0, inode=None) assert [r.logfile for r in records] == [older, newer, logfile] + + +@pytest.mark.parametrize( + ("github_actions", "cluster_type", "extra_regexes"), + ( + pytest.param("", "local", [], id="local"), + pytest.param("true", "local", ["TraceBlockFromFuture"], id="github_actions"), + pytest.param( + "", + "testnet", + ["TrHandshakeClientError", "TracePromoteWarmBigLedgerPeerAborted"], + id="testnet", + ), + pytest.param( + "true", + "testnet", + [ + "TraceBlockFromFuture", + "TrHandshakeClientError", + "TracePromoteWarmBigLedgerPeerAborted", + ], + id="github_actions_testnet", + ), + ), +) +def test_get_ignored_error_regexes( + monkeypatch: pytest.MonkeyPatch, + github_actions: str, + cluster_type: str, + extra_regexes: list[str], +): + """Check that the ignored error regexes reflect the runtime environment. + + The environment-specific regexes are added lazily based on the current environment, + not based on the environment seen when the module was imported. + """ + monkeypatch.setenv("GITHUB_ACTIONS", github_actions) + cluster_type_obj = ( + cluster_nodes.TestnetCluster() + if cluster_type == "testnet" + else cluster_nodes.LocalCluster() + ) + monkeypatch.setattr(cluster_nodes, "get_cluster_type", lambda: cluster_type_obj) + + regexes = logfiles._get_ignored_error_regexes() + + assert set(logfiles.ERRORS_IGNORED).issubset(regexes) + for extra in extra_regexes: + assert extra in regexes + assert len(regexes) == len(logfiles.ERRORS_IGNORED) + len(extra_regexes)