"""验证日志脱敏边界,不需要 PySide6 或真机。""" from __future__ import annotations import sys from pathlib import Path import tempfile import unittest CLIENT_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(CLIENT_ROOT / "src")) from cmbuyer_client.logging_policy import configure_application_logger, redact_text from cmbuyer_client.runtime import RuntimePaths class LoggingPolicyTests(unittest.TestCase): def test_redact_text_hides_required_sensitive_values(self) -> None: message = ( "token=secret-value authorization: Bearer-value " "address='浙江省杭州市' phone=13800138000 payment=card-value" ) redacted = redact_text(message) for raw_value in ("secret-value", "Bearer-value", "浙江省杭州市", "13800138000", "card-value"): self.assertNotIn(raw_value, redacted) self.assertIn("token=[已隐藏]", redacted) def test_file_handler_writes_only_redacted_text(self) -> None: with tempfile.TemporaryDirectory() as directory: paths = RuntimePaths.from_root(Path(directory)) logger = configure_application_logger(paths) try: logger.info("token=not-for-log phone=13900139000 payment=not-for-log") for handler in logger.handlers: handler.flush() content = (paths.logs / "client.log").read_text(encoding="utf-8") finally: # Windows 不允许在 FileHandler 持有文件时删除临时目录。 for handler in tuple(logger.handlers): logger.removeHandler(handler) handler.close() self.assertNotIn("not-for-log", content) self.assertNotIn("13900139000", content) self.assertIn("[已隐藏]", content) def test_bearer_bare_token_and_traceback_are_redacted(self) -> None: token = "a" * 64 with tempfile.TemporaryDirectory() as directory: paths = RuntimePaths.from_root(Path(directory)) logger = configure_application_logger(paths) try: try: raise RuntimeError("credential=" + token) except RuntimeError: logger.exception("Authorization: Bearer %s bare=%s", token, token) for handler in logger.handlers: handler.flush() content = (paths.logs / "client.log").read_text(encoding="utf-8") finally: for handler in tuple(logger.handlers): logger.removeHandler(handler) handler.close() self.assertNotIn(token, content) self.assertIn("[已隐藏]", content)