test: add live marker, CI coverage gate, rust bridge boundary tests (#256)

This commit is contained in:
Andrew Park
2026-04-17 11:02:21 -07:00
committed by GitHub
parent 28e913f706
commit 88a7ebcaa3
3 changed files with 135 additions and 1 deletions
+14 -1
View File
@@ -63,7 +63,20 @@ jobs:
run: uv run maturin develop --manifest-path rust/crates/openjarvis-python/Cargo.toml
- name: Run tests
run: uv run pytest tests/ -v --tb=short -m "not live and not cloud"
run: |
uv run pytest tests/ -v --tb=short -m "not live and not cloud" \
--cov=openjarvis \
--cov-report=term-missing \
--cov-report=xml \
--cov-fail-under=60
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-xml
path: coverage.xml
if-no-files-found: warn
rust:
runs-on: ubuntu-latest
+3
View File
@@ -9,6 +9,8 @@ from __future__ import annotations
import tempfile
from pathlib import Path
import pytest
from openjarvis.connectors.obsidian import ObsidianConnector
from openjarvis.connectors.pipeline import IngestionPipeline
from openjarvis.connectors.store import KnowledgeStore
@@ -19,6 +21,7 @@ from openjarvis.tools.knowledge_search import KnowledgeSearchTool
DOCS_DIR = Path(__file__).resolve().parents[2] / "docs"
@pytest.mark.live
def test_live_obsidian_full_pipeline() -> None:
"""Smoke test: index real .md files, then search them."""
assert DOCS_DIR.is_dir(), f"Docs dir not found: {DOCS_DIR}"
+118
View File
@@ -4,6 +4,8 @@ from __future__ import annotations
import json
import pytest
class TestGetRustModule:
"""Test get_rust_module() returns the Rust extension module."""
@@ -127,6 +129,122 @@ class TestRetrievalResultsFromJson:
assert results[0].metadata == {"nested": True}
class TestConverterInvalidInputs:
"""Boundary behavior: malformed JSON and missing/unexpected fields."""
def test_scan_result_malformed_json_raises(self):
from openjarvis._rust_bridge import scan_result_from_json
with pytest.raises(json.JSONDecodeError):
scan_result_from_json("{not json")
def test_scan_result_missing_findings_key_is_clean(self):
from openjarvis._rust_bridge import scan_result_from_json
result = scan_result_from_json("{}")
assert result.clean
assert result.findings == []
def test_scan_result_unknown_threat_level_raises(self):
from openjarvis._rust_bridge import scan_result_from_json
data = {
"findings": [
{
"pattern_name": "x",
"matched_text": "y",
"threat_level": "not-a-level",
"start": 0,
"end": 1,
"description": "",
},
],
}
with pytest.raises(ValueError):
scan_result_from_json(json.dumps(data))
def test_scan_result_finding_missing_fields_uses_defaults(self):
from openjarvis._rust_bridge import scan_result_from_json
result = scan_result_from_json('{"findings": [{}]}')
assert not result.clean
finding = result.findings[0]
assert finding.pattern_name == ""
assert finding.matched_text == ""
assert finding.threat_level.value == "low"
assert finding.start == 0
assert finding.end == 0
def test_injection_result_malformed_json_raises(self):
from openjarvis._rust_bridge import injection_result_from_json
with pytest.raises(json.JSONDecodeError):
injection_result_from_json("")
def test_injection_result_unknown_top_level_threat_defaults_to_low(self):
from openjarvis._rust_bridge import injection_result_from_json
data = {
"is_clean": True,
"findings": [],
"threat_level": "bogus",
}
result = injection_result_from_json(json.dumps(data))
assert result.threat_level.value == "low"
def test_injection_result_missing_keys_uses_defaults(self):
from openjarvis._rust_bridge import injection_result_from_json
result = injection_result_from_json("{}")
assert result.is_clean is True
assert result.findings == []
assert result.threat_level.value == "low"
def test_retrieval_results_malformed_json_raises(self):
from openjarvis._rust_bridge import retrieval_results_from_json
with pytest.raises(json.JSONDecodeError):
retrieval_results_from_json("not-json")
def test_retrieval_results_metadata_invalid_json_string_falls_back_to_empty(self):
from openjarvis._rust_bridge import retrieval_results_from_json
data = [
{
"content": "c",
"score": 0.1,
"source": "s",
"metadata": "{not valid json",
},
]
results = retrieval_results_from_json(json.dumps(data))
assert results[0].metadata == {}
def test_retrieval_results_missing_fields_uses_defaults(self):
from openjarvis._rust_bridge import retrieval_results_from_json
results = retrieval_results_from_json("[{}]")
assert len(results) == 1
assert results[0].content == ""
assert results[0].score == 0.0
assert results[0].source == ""
assert results[0].metadata == {}
def test_retrieval_results_score_string_coerced_to_float(self):
from openjarvis._rust_bridge import retrieval_results_from_json
data = [{"content": "x", "score": "2.5", "source": "", "metadata": {}}]
results = retrieval_results_from_json(json.dumps(data))
assert results[0].score == 2.5
def test_retrieval_results_non_iterable_top_level_raises(self):
from openjarvis._rust_bridge import retrieval_results_from_json
# Top-level must be a list; a bare number has no iteration.
with pytest.raises(TypeError):
retrieval_results_from_json("42")
class TestRustBackedModules:
"""Test that Rust-backed modules work correctly."""