7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
259 lines
8.3 KiB
Python
259 lines
8.3 KiB
Python
"""
|
||
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"
|