Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

259 lines
8.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
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"