"""日志文件轮转与敏感信息脱敏测试。""" import gzip import logging import tempfile from datetime import datetime, timedelta from pathlib import Path from utils.logger import ( _SensitiveDataFilter, _SizeAndDayRotatingFileHandler, _parse_size, ) class TestLogger: def test_size_parser_accepts_human_readable_values(self): assert _parse_size("2K") == 2 * 1024 assert _parse_size("3MiB") == 3 * 1024 * 1024 assert _parse_size("invalid", default=123) == 123 def test_file_log_redacts_credentials_and_compresses_rotation(self): with tempfile.TemporaryDirectory() as tmpdir: log_path = Path(tmpdir) / "app-2026-08-28.log" handler = _SizeAndDayRotatingFileHandler( log_path, max_bytes=1, retention_days=14 ) handler.setFormatter(logging.Formatter("%(message)s")) handler.addFilter(_SensitiveDataFilter()) test_logger = logging.getLogger("tests.logger.redaction") test_logger.handlers = [handler] test_logger.setLevel(logging.INFO) test_logger.propagate = False try: test_logger.info("Cookie: access_token=super-secret; uid=1") test_logger.info("Authorization: Bearer top-secret-token") finally: handler.close() test_logger.handlers = [] archives = list(Path(tmpdir).glob("app-2026-08-28.log.*.gz")) assert len(archives) == 1 archived_content = gzip.open(archives[0], "rt", encoding="utf-8").read() current_content = log_path.read_text(encoding="utf-8") combined = archived_content + current_content assert "super-secret" not in combined assert "top-secret-token" not in combined assert "Cookie: [REDACTED]" in combined assert "Authorization: [REDACTED]" in combined def test_daily_log_switches_to_a_new_dated_file(self): with tempfile.TemporaryDirectory() as tmpdir: today = datetime.now().date() old_path = ( Path(tmpdir) / f"app-{(today - timedelta(days=1)).isoformat()}.log" ) handler = _SizeAndDayRotatingFileHandler( old_path, max_bytes=1024, retention_days=14 ) handler.setFormatter(logging.Formatter("%(message)s")) handler._active_day = today - timedelta(days=1) test_logger = logging.getLogger("tests.logger.daily") test_logger.handlers = [handler] test_logger.setLevel(logging.INFO) test_logger.propagate = False try: test_logger.info("today") finally: handler.close() test_logger.handlers = [] current_path = Path(tmpdir) / f"app-{today.isoformat()}.log" assert current_path.exists() assert current_path.read_text(encoding="utf-8").strip() == "today"