154 lines
4.9 KiB
Python
154 lines
4.9 KiB
Python
"""Unit tests for logging module."""
|
|
|
|
import logging
|
|
from pathlib import Path
|
|
from tempfile import TemporaryDirectory
|
|
|
|
import pytest
|
|
|
|
from webdrop_bridge.utils.logging import get_logger, setup_logging
|
|
|
|
|
|
class TestSetupLogging:
|
|
"""Test logging configuration."""
|
|
|
|
def test_setup_logging_console_only(self):
|
|
"""Test console-only logging setup."""
|
|
logger = setup_logging(name="test_console", level="DEBUG")
|
|
|
|
assert logger.name == "test_console"
|
|
assert logger.level == logging.DEBUG
|
|
assert len(logger.handlers) == 1
|
|
assert isinstance(logger.handlers[0], logging.StreamHandler)
|
|
|
|
def test_setup_logging_with_file(self, tmp_path):
|
|
"""Test logging setup with file handler."""
|
|
log_file = tmp_path / "test.log"
|
|
|
|
logger = setup_logging(
|
|
name="test_file",
|
|
level="INFO",
|
|
log_file=log_file,
|
|
)
|
|
|
|
assert logger.name == "test_file"
|
|
assert len(logger.handlers) == 2
|
|
|
|
# Find file handler
|
|
file_handler = None
|
|
for handler in logger.handlers:
|
|
if isinstance(handler, logging.handlers.RotatingFileHandler):
|
|
file_handler = handler
|
|
break
|
|
|
|
assert file_handler is not None
|
|
assert log_file.exists()
|
|
|
|
def test_setup_logging_invalid_level(self):
|
|
"""Test that invalid log level raises KeyError."""
|
|
with pytest.raises(KeyError, match="Invalid logging level"):
|
|
setup_logging(level="INVALID")
|
|
|
|
def test_setup_logging_invalid_file_path(self):
|
|
"""Test that inaccessible file path raises ValueError."""
|
|
# Use a path that can't be created (on Windows, CON is reserved)
|
|
if Path.cwd().drive: # Windows
|
|
invalid_path = Path("CON") / "invalid.log"
|
|
else: # Unix - use root-only directory
|
|
invalid_path = Path("/root") / "invalid.log"
|
|
|
|
with pytest.raises(ValueError, match="Cannot write to log file"):
|
|
setup_logging(log_file=invalid_path)
|
|
|
|
def test_setup_logging_custom_format(self, tmp_path):
|
|
"""Test logging with custom format string."""
|
|
log_file = tmp_path / "test.log"
|
|
custom_fmt = "%(levelname)s:%(name)s:%(message)s"
|
|
|
|
logger = setup_logging(
|
|
name="test_format",
|
|
level="INFO",
|
|
log_file=log_file,
|
|
fmt=custom_fmt,
|
|
)
|
|
|
|
# Log a test message
|
|
logger.info("test message")
|
|
|
|
# Check format in log file
|
|
content = log_file.read_text()
|
|
assert "INFO:test_format:test message" in content
|
|
|
|
def test_setup_logging_creates_parent_dirs(self, tmp_path):
|
|
"""Test that setup_logging creates parent directories."""
|
|
log_file = tmp_path / "nested" / "dir" / "test.log"
|
|
|
|
logger = setup_logging(
|
|
name="test_nested",
|
|
level="INFO",
|
|
log_file=log_file,
|
|
)
|
|
|
|
logger.info("test")
|
|
|
|
assert log_file.exists()
|
|
assert log_file.parent.exists()
|
|
|
|
def test_setup_logging_removes_duplicates(self):
|
|
"""Test that multiple setup calls don't duplicate handlers."""
|
|
logger_name = "test_duplicates"
|
|
|
|
# First setup
|
|
logger1 = setup_logging(name=logger_name, level="DEBUG")
|
|
initial_handler_count = len(logger1.handlers)
|
|
|
|
# Second setup (should clear old handlers)
|
|
logger2 = setup_logging(name=logger_name, level="INFO")
|
|
|
|
assert logger2 is logger1 # Same logger object
|
|
assert len(logger2.handlers) == initial_handler_count
|
|
|
|
|
|
class TestGetLogger:
|
|
"""Test get_logger convenience function."""
|
|
|
|
def test_get_logger(self):
|
|
"""Test getting a logger instance."""
|
|
logger = get_logger("test.module")
|
|
|
|
assert isinstance(logger, logging.Logger)
|
|
assert logger.name == "test.module"
|
|
|
|
def test_get_logger_default_name(self):
|
|
"""Test get_logger uses __name__ by default."""
|
|
logger = get_logger()
|
|
|
|
# Should return a logger (when no name provided, uses logging module __name__)
|
|
assert isinstance(logger, logging.Logger)
|
|
assert logger.name == "webdrop_bridge.utils.logging"
|
|
|
|
|
|
class TestLogRotation:
|
|
"""Test log file rotation."""
|
|
|
|
def test_rotating_file_handler_configured(self, tmp_path):
|
|
"""Test that file handler is configured for rotation."""
|
|
log_file = tmp_path / "test.log"
|
|
|
|
logger = setup_logging(
|
|
name="test_rotation",
|
|
level="INFO",
|
|
log_file=log_file,
|
|
)
|
|
|
|
# Find rotating file handler
|
|
rotating_handler = None
|
|
for handler in logger.handlers:
|
|
if isinstance(handler, logging.handlers.RotatingFileHandler):
|
|
rotating_handler = handler
|
|
break
|
|
|
|
assert rotating_handler is not None
|
|
# Default: 10 MB max, 5 backups
|
|
assert rotating_handler.maxBytes == 10 * 1024 * 1024
|
|
assert rotating_handler.backupCount == 5
|