Skip to main content
Glama
test_config_service.py9.04 kB
"""Unit tests for ConfigService. Tests configuration loading, hot-reload, file watching, and endpoint overrides. """ import pytest import yaml from src.services.config_service import ConfigService, get_config_service class TestConfigService: """Test suite for ConfigService.""" def test_init_with_default_config(self): """Test initialization with default configuration.""" service = ConfigService(config_path="/nonexistent/path.yaml", auto_reload=False) assert service.config.output_token_threshold == 4000 assert service.config.hard_output_token_cap == 12000 assert service.config.default_page_size == 50 assert service.config.max_page_size == 200 assert service.config.enable_summarization is True assert service.config.enable_pagination is True assert service.endpoint_overrides == {} def test_load_config_from_yaml(self, tmp_path): """Test loading configuration from YAML file.""" config_file = tmp_path / "config.yaml" config_data = { "context_protection": { "output_token_threshold": 5000, "hard_output_token_cap": 15000, "default_page_size": 100, "max_page_size": 500, "enable_summarization": False, "enable_pagination": True, } } with config_file.open("w") as f: yaml.dump(config_data, f) service = ConfigService(config_path=config_file, auto_reload=False) assert service.config.output_token_threshold == 5000 assert service.config.hard_output_token_cap == 15000 assert service.config.default_page_size == 100 assert service.config.max_page_size == 500 assert service.config.enable_summarization is False assert service.config.enable_pagination is True def test_load_config_with_endpoint_overrides(self, tmp_path): """Test loading endpoint-specific overrides.""" config_file = tmp_path / "config.yaml" config_data = { "context_protection": { "output_token_threshold": 4000, "endpoints": { "/api/v1/listings": { "threshold": 8000, "hard_cap": 20000, "page_size": 25, "summarization_enabled": False, }, "/api/v1/bookings": { "threshold": 6000, "pagination_enabled": True, }, }, } } with config_file.open("w") as f: yaml.dump(config_data, f) service = ConfigService(config_path=config_file, auto_reload=False) assert "/api/v1/listings" in service.endpoint_overrides assert "/api/v1/bookings" in service.endpoint_overrides listings_override = service.endpoint_overrides["/api/v1/listings"] assert listings_override.threshold == 8000 assert listings_override.hard_cap == 20000 assert listings_override.page_size == 25 assert listings_override.summarization_enabled is False def test_get_endpoint_config_with_override(self, tmp_path): """Test getting endpoint configuration with override.""" config_file = tmp_path / "config.yaml" config_data = { "context_protection": { "output_token_threshold": 4000, "hard_output_token_cap": 12000, "default_page_size": 50, "endpoints": { "/api/v1/listings": { "threshold": 8000, "page_size": 25, }, }, } } with config_file.open("w") as f: yaml.dump(config_data, f) service = ConfigService(config_path=config_file, auto_reload=False) threshold, hard_cap, page_size, summarization, pagination = service.get_endpoint_config( "/api/v1/listings" ) assert threshold == 8000 # Override assert hard_cap == 12000 # Default assert page_size == 25 # Override assert summarization is True # Default assert pagination is True # Default def test_get_endpoint_config_without_override(self, tmp_path): """Test getting endpoint configuration without override (uses defaults).""" config_file = tmp_path / "config.yaml" config_data = { "context_protection": { "output_token_threshold": 4000, "hard_output_token_cap": 12000, "default_page_size": 50, } } with config_file.open("w") as f: yaml.dump(config_data, f) service = ConfigService(config_path=config_file, auto_reload=False) threshold, hard_cap, page_size, summarization, pagination = service.get_endpoint_config( "/api/v1/unknown" ) assert threshold == 4000 assert hard_cap == 12000 assert page_size == 50 assert summarization is True assert pagination is True def test_load_config_empty_file(self, tmp_path): """Test loading from empty YAML file.""" config_file = tmp_path / "empty.yaml" config_file.write_text("") service = ConfigService(config_path=config_file, auto_reload=False) # Should use defaults assert service.config.output_token_threshold == 4000 def test_load_config_invalid_yaml(self, tmp_path): """Test loading from invalid YAML file.""" config_file = tmp_path / "invalid.yaml" config_file.write_text("invalid: yaml: content: {{") service = ConfigService(config_path=config_file, auto_reload=False) # Should use defaults on error assert service.config.output_token_threshold == 4000 @pytest.mark.asyncio async def test_reload_config(self, tmp_path): """Test manual config reload.""" config_file = tmp_path / "config.yaml" # Initial config config_data = { "context_protection": { "output_token_threshold": 4000, } } with config_file.open("w") as f: yaml.dump(config_data, f) service = ConfigService(config_path=config_file, auto_reload=False) assert service.config.output_token_threshold == 4000 # Update config config_data["context_protection"]["output_token_threshold"] = 6000 with config_file.open("w") as f: yaml.dump(config_data, f) # Reload await service.reload_config() assert service.config.output_token_threshold == 6000 def test_watcher_not_started_when_auto_reload_false(self, tmp_path): """Test file watcher is not started when auto_reload=False.""" config_file = tmp_path / "config.yaml" config_file.write_text("context_protection: {}") service = ConfigService(config_path=config_file, auto_reload=False) assert service._observer is None def test_stop_watcher(self, tmp_path): """Test stopping file watcher.""" config_file = tmp_path / "config.yaml" config_file.write_text("context_protection: {}") service = ConfigService(config_path=config_file, auto_reload=True) assert service._observer is not None service.stop_watcher() assert service._observer is None def test_stop_watcher_when_not_started(self): """Test stopping watcher when it was never started.""" service = ConfigService(config_path="/nonexistent/path.yaml", auto_reload=False) # Should not raise error service.stop_watcher() assert service._observer is None class TestGetConfigService: """Test suite for get_config_service singleton function.""" def test_singleton_pattern(self, tmp_path): """Test that get_config_service returns same instance.""" config_file = tmp_path / "config.yaml" config_file.write_text("context_protection: {}") # Reset global singleton import src.services.config_service src.services.config_service._config_service = None service1 = get_config_service(config_path=config_file, auto_reload=False) service2 = get_config_service(config_path=config_file, auto_reload=False) assert service1 is service2 def test_singleton_initialization(self, tmp_path): """Test singleton is initialized on first call.""" config_file = tmp_path / "config.yaml" config_file.write_text("context_protection: {}") # Reset global singleton import src.services.config_service src.services.config_service._config_service = None service = get_config_service(config_path=config_file, auto_reload=False) assert service is not None assert isinstance(service, ConfigService)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/darrentmorgan/hostaway-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server