tests: reset borg.output.progress logger between tests to fix flakiness

ProgressIndicatorBase installs a handler on the process-global
'borg.output.progress' logger and only removes it in __del__. In-process
(fork=False) command execution leaves this logger at level INFO /
propagate=False with lingering handlers, and that state leaks across tests.

When a later progress test runs, the "if not self.logger.handlers" guard
skips the stderr handler setup, so progress output goes to the logging
system instead of the stderr captured by capfd. Under xdist this surfaces
as order/distribution-dependent failures of the progress tests
(test_progress_percentage_*, test_extract_progress, test_progress_on,
test_check_usage, ...).

Add an autouse fixture that removes handlers and resets level/propagate on
the progress logger after each test. This also makes the intra-test
workaround in test_check_usage unnecessary (the progress logger level is
set per command run by _setup_implied_logging), so remove it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Thomas Waldmann 2026-06-18 20:47:16 +02:00
parent bdfb50f0c6
commit 8efc67baee
No known key found for this signature in database
GPG key ID: 243ACFA951F78E01
2 changed files with 18 additions and 2 deletions

View file

@ -4411,8 +4411,6 @@ class ArchiverCheckTestCase(ArchiverTestCaseBase):
self.assert_in('Starting repository check', output)
self.assert_in('Starting archive consistency check', output)
self.assert_in('Checking segments', output)
# reset logging to new process default to avoid need for fork=True on next check
logging.getLogger('borg.output.progress').setLevel(logging.NOTSET)
output = self.cmd('check', '-v', '--repository-only', self.repository_location, exit_code=0)
self.assert_in('Starting repository check', output)
self.assert_not_in('Starting archive consistency check', output)

View file

@ -1,3 +1,4 @@
import logging
import os
import pytest
@ -26,6 +27,23 @@ from borg.testsuite import are_symlinks_supported, are_hardlinks_supported, is_u
from borg.testsuite.platform import fakeroot_detected # noqa: E402
@pytest.fixture(autouse=True)
def reset_progress_logger():
# ProgressIndicatorBase installs a handler on the process-global
# 'borg.output.progress' logger and only removes it in __del__, and in-process
# (fork=False) command execution leaves this logger at level INFO / propagate=False.
# This state leaks across tests and makes the progress tests flaky (the progress
# output ends up in the logging system instead of on the stderr captured by capfd).
# Reset it after each test to keep tests isolated.
yield
logger = logging.getLogger('borg.output.progress')
for handler in logger.handlers[:]:
logger.removeHandler(handler)
handler.close()
logger.setLevel(logging.NOTSET)
logger.propagate = True
@pytest.fixture(autouse=True)
def clean_env(tmpdir_factory, monkeypatch):
# avoid that we access / modify the user's normal .config / .cache directory: