""" Tests for logging_config module """ import logging from unittest.mock import MagicMock, patch from services.logging_config import DEFAULT_FORMAT, get_application_logger, get_request_logger, setup_logging class TestLoggingConfig: """Test logging configuration functions""" def test_default_format(self): """Test that DEFAULT_FORMAT is defined""" assert DEFAULT_FORMAT is not None assert isinstance(DEFAULT_FORMAT, str) assert "%(asctime)s" in DEFAULT_FORMAT assert "%(name)s" in DEFAULT_FORMAT assert "%(levelname)s" in DEFAULT_FORMAT assert "%(message)s" in DEFAULT_FORMAT @patch("services.logging_config.logging.getLogger") @patch("services.logging_config.logging.StreamHandler") def test_setup_logging_basic(self, mock_handler_class, mock_get_logger): """Test basic logging setup""" mock_handler = MagicMock() mock_handler_class.return_value = mock_handler mock_logger = MagicMock() mock_get_logger.return_value = mock_logger setup_logging(level="INFO", enable_request_logging=False) # Verify handler was created and configured mock_handler_class.assert_called_once() mock_handler.setFormatter.assert_called_once() # Verify logger was configured mock_logger.setLevel.assert_called_with(logging.INFO) mock_logger.addHandler.assert_called_with(mock_handler) @patch("services.logging_config.logging.getLogger") @patch("services.logging_config.logging.StreamHandler") def test_setup_logging_with_request_logging(self, mock_handler_class, mock_get_logger): """Test logging setup with request logging enabled""" mock_handler = MagicMock() mock_handler_class.return_value = mock_handler mock_logger = MagicMock() mock_get_logger.return_value = mock_logger with patch("services.logging_config._setup_request_logging") as mock_setup_request: setup_logging(level="DEBUG", enable_request_logging=True) # Verify request logging was set up mock_setup_request.assert_called_once() @patch("services.logging_config.logging.getLogger") def test_setup_logging_clears_handlers(self, mock_get_logger): """Test that setup_logging clears existing handlers""" mock_logger = MagicMock() mock_get_logger.return_value = mock_logger # Mock the root logger to have handlers with patch("services.logging_config.logging.getLogger") as mock_root_get_logger: mock_root_logger = MagicMock() mock_root_logger.handlers = [MagicMock(), MagicMock()] # Some existing handlers mock_root_get_logger.return_value = mock_root_logger setup_logging(level="INFO", enable_request_logging=False) # Verify handlers were cleared (removeHandler is called on root logger) assert mock_root_logger.removeHandler.called @patch("services.logging_config.logging.getLogger") def test_setup_logging_different_levels(self, mock_get_logger): """Test setup_logging with different log levels""" mock_logger = MagicMock() mock_get_logger.return_value = mock_logger # Test DEBUG level setup_logging(level="DEBUG", enable_request_logging=False) # The root logger gets set to DEBUG level assert mock_logger.setLevel.called # Test WARNING level setup_logging(level="WARNING", enable_request_logging=False) assert mock_logger.setLevel.called # Test ERROR level setup_logging(level="ERROR", enable_request_logging=False) assert mock_logger.setLevel.called @patch("services.logging_config.logging.getLogger") def test_get_request_logger(self, mock_get_logger): """Test get_request_logger function""" mock_logger = MagicMock() mock_get_logger.return_value = mock_logger result = get_request_logger() assert result == mock_logger mock_get_logger.assert_called_with("uvicorn.access") @patch("services.logging_config.logging.getLogger") def test_get_application_logger(self, mock_get_logger): """Test get_application_logger function""" mock_logger = MagicMock() mock_get_logger.return_value = mock_logger result = get_application_logger() assert result == mock_logger mock_get_logger.assert_called_with("labfusion.service_adapters") @patch("services.logging_config.logging.getLogger") def test_setup_request_logging(self, mock_get_logger): """Test _setup_request_logging function""" from services.logging_config import _setup_request_logging mock_access_logger = MagicMock() mock_error_logger = MagicMock() def mock_get_logger_side_effect(name): if name == "uvicorn.access": return mock_access_logger elif name == "uvicorn.error": return mock_error_logger return MagicMock() mock_get_logger.side_effect = mock_get_logger_side_effect mock_handler = MagicMock() _setup_request_logging(mock_handler) # Verify access logger was configured mock_access_logger.addHandler.assert_called_with(mock_handler) assert mock_access_logger.propagate is False # Verify error logger was configured mock_error_logger.addHandler.assert_called_with(mock_handler) assert mock_error_logger.propagate is False def test_logging_levels_enum(self): """Test that logging levels are properly defined""" assert hasattr(logging, "DEBUG") assert hasattr(logging, "INFO") assert hasattr(logging, "WARNING") assert hasattr(logging, "ERROR") assert hasattr(logging, "CRITICAL") @patch("services.logging_config.logging.getLogger") def test_logger_propagation_disabled(self, mock_get_logger): """Test that logger propagation is disabled for request loggers""" mock_access_logger = MagicMock() mock_error_logger = MagicMock() def mock_get_logger_side_effect(name): if name == "uvicorn.access": return mock_access_logger elif name == "uvicorn.error": return mock_error_logger return MagicMock() mock_get_logger.side_effect = mock_get_logger_side_effect from services.logging_config import _setup_request_logging mock_handler = MagicMock() _setup_request_logging(mock_handler) # Verify propagation is disabled assert mock_access_logger.propagate is False assert mock_error_logger.propagate is False def test_logging_format_consistency(self): """Test that logging format is consistent across functions""" # The format should be the same for all loggers assert "%(asctime)s" in DEFAULT_FORMAT assert "%(name)s" in DEFAULT_FORMAT assert "%(levelname)s" in DEFAULT_FORMAT assert "%(message)s" in DEFAULT_FORMAT @patch("services.logging_config.logging.getLogger") def test_multiple_setup_calls(self, mock_get_logger): """Test that multiple setup_logging calls work correctly""" mock_logger = MagicMock() mock_get_logger.return_value = mock_logger # First setup setup_logging(level="INFO", enable_request_logging=False) # Second setup setup_logging(level="DEBUG", enable_request_logging=True) # Should not raise any exceptions assert True def test_logging_config_imports(self): """Test that all required modules are imported""" import services.logging_config # Verify the module has the expected functions assert hasattr(services.logging_config, "setup_logging") assert hasattr(services.logging_config, "get_request_logger") assert hasattr(services.logging_config, "get_application_logger") assert hasattr(services.logging_config, "DEFAULT_FORMAT") assert hasattr(services.logging_config, "_setup_request_logging")