""" Coverage tests for local_deep_research/mcp/server.py Focuses on branches NOT covered by existing tests/mcp/test_server.py and tests/mcp/test_validation.py: - _classify_error() for each error-type keyword - _validate_iterations max_val enforcement - _validate_questions_per_iteration upper bound - _validate_max_results boundaries - _build_settings_overrides with various parameter combinations - analyze_documents validation (empty collection_name) - generate_report searches_per_section validation - list_strategies / get_configuration exception paths """ import pytest try: import mcp # noqa: F401 MCP_AVAILABLE = True except ImportError: MCP_AVAILABLE = False pytestmark = pytest.mark.skipif( not MCP_AVAILABLE, reason="MCP package not installed" ) # --------------------------------------------------------------------------- # _classify_error # --------------------------------------------------------------------------- class TestClassifyError: def _classify(self, msg): from local_deep_research.mcp.server import _classify_error return _classify_error(msg) def test_service_unavailable_503(self): assert self._classify("503 service error") == "service_unavailable" def test_service_unavailable_keyword(self): assert self._classify("service unavailable") == "service_unavailable" def test_model_not_found_404(self): assert self._classify("404 error") == "model_not_found" def test_model_not_found_keyword(self): assert self._classify("model not found") == "model_not_found" def test_auth_error_api_key(self): assert self._classify("invalid api key") == "auth_error" def test_auth_error_401(self): assert self._classify("401 unauthorized") == "auth_error" def test_timeout(self): assert self._classify("request timed out") == "timeout" def test_rate_limit_429(self): assert self._classify("429 too many requests") == "rate_limit" def test_rate_limit_keyword(self): assert self._classify("rate limit exceeded") == "rate_limit" def test_connection_error(self): assert self._classify("connection refused") == "connection_error" def test_validation_error(self): assert self._classify("invalid parameter") == "validation_error" def test_unknown(self): assert self._classify("some random error") == "unknown" # --------------------------------------------------------------------------- # _validate_iterations # --------------------------------------------------------------------------- class TestValidateIterations: def _vi(self, val, max_val=20): from local_deep_research.mcp.server import _validate_iterations return _validate_iterations(val, max_val) def test_none_returns_none(self): assert self._vi(None) is None def test_valid_value(self): assert self._vi(5) == 5 def test_exceeds_max_raises(self): from local_deep_research.mcp.server import ValidationError with pytest.raises(ValidationError, match="cannot exceed"): self._vi(21, max_val=20) def test_zero_raises(self): from local_deep_research.mcp.server import ValidationError with pytest.raises(ValidationError, match="positive integer"): self._vi(0) def test_negative_raises(self): from local_deep_research.mcp.server import ValidationError with pytest.raises(ValidationError): self._vi(-3) def test_non_integer_raises(self): from local_deep_research.mcp.server import ValidationError with pytest.raises(ValidationError): self._vi(2.5) def test_exact_max_allowed(self): assert self._vi(20, max_val=20) == 20 # --------------------------------------------------------------------------- # _validate_questions_per_iteration # --------------------------------------------------------------------------- class TestValidateQPI: def _vqpi(self, val): from local_deep_research.mcp.server import ( _validate_questions_per_iteration, ) return _validate_questions_per_iteration(val) def test_none_returns_none(self): assert self._vqpi(None) is None def test_valid(self): assert self._vqpi(3) == 3 def test_zero_raises(self): from local_deep_research.mcp.server import ValidationError with pytest.raises(ValidationError): self._vqpi(0) def test_exceeds_10_raises(self): from local_deep_research.mcp.server import ValidationError with pytest.raises(ValidationError, match="cannot exceed 10"): self._vqpi(11) def test_exactly_10_allowed(self): assert self._vqpi(10) == 10 # --------------------------------------------------------------------------- # _validate_max_results # --------------------------------------------------------------------------- class TestValidateMaxResults: def _vmr(self, val): from local_deep_research.mcp.server import _validate_max_results return _validate_max_results(val) def test_valid(self): assert self._vmr(10) == 10 def test_zero_raises(self): from local_deep_research.mcp.server import ValidationError with pytest.raises(ValidationError): self._vmr(0) def test_exceeds_100_raises(self): from local_deep_research.mcp.server import ValidationError with pytest.raises(ValidationError, match="cannot exceed 100"): self._vmr(101) def test_exactly_100_allowed(self): assert self._vmr(100) == 100 # --------------------------------------------------------------------------- # _build_settings_overrides # --------------------------------------------------------------------------- class TestBuildSettingsOverrides: def test_empty_params_returns_empty_dict(self): from local_deep_research.mcp.server import _build_settings_overrides result = _build_settings_overrides() assert result == {} def test_iterations_added(self): from local_deep_research.mcp.server import _build_settings_overrides result = _build_settings_overrides(iterations=3) assert result.get("search.iterations") == 3 def test_temperature_added(self): from local_deep_research.mcp.server import _build_settings_overrides result = _build_settings_overrides(temperature=0.5) assert result.get("llm.temperature") == pytest.approx(0.5) def test_qpi_added(self): from local_deep_research.mcp.server import _build_settings_overrides result = _build_settings_overrides(questions_per_iteration=4) assert result.get("search.questions_per_iteration") == 4 # --------------------------------------------------------------------------- # analyze_documents – empty collection_name # --------------------------------------------------------------------------- class TestAnalyzeDocumentsValidation: def test_empty_collection_name_returns_error(self): from local_deep_research.mcp.server import analyze_documents result = analyze_documents(query="test query", collection_name="") assert result["status"] == "error" assert result["error_type"] == "validation_error" def test_whitespace_collection_name_returns_error(self): from local_deep_research.mcp.server import analyze_documents result = analyze_documents(query="test query", collection_name=" ") assert result["status"] == "error" assert result["error_type"] == "validation_error" # --------------------------------------------------------------------------- # generate_report – searches_per_section validation # --------------------------------------------------------------------------- class TestGenerateReportValidation: def test_searches_per_section_zero_returns_error(self): from local_deep_research.mcp.server import generate_report result = generate_report(query="test", searches_per_section=0) assert result["status"] == "error" assert result["error_type"] == "validation_error" def test_searches_per_section_over_10_returns_error(self): from local_deep_research.mcp.server import generate_report result = generate_report(query="test", searches_per_section=11) assert result["status"] == "error" assert result["error_type"] == "validation_error"