"""Coverage tests for storage/base.py targeting ~5 missing statements. Uncovered functions/branches: - ReportStorage abstract methods (save_report, get_report, etc.) - Verifying ABC contract - Partial implementation raises TypeError - Abstractmethods set matches exactly 5 methods - save_report metadata=None default handling - report_exists user isolation """ import pytest from local_deep_research.storage.base import ReportStorage MODULE = "local_deep_research.storage.base" class ConcreteStorage(ReportStorage): """Minimal concrete implementation for testing ABC contract.""" def __init__(self): self._store = {} def save_report(self, research_id, content, metadata=None, username=None): self._store[research_id] = { "content": content, "metadata": metadata or {}, } return True def get_report(self, research_id, username=None): entry = self._store.get(research_id) return entry["content"] if entry else None def get_report_with_metadata(self, research_id, username=None): return self._store.get(research_id) def delete_report(self, research_id, username=None): if research_id in self._store: del self._store[research_id] return True return False def list_reports(self, username=None): return [] def report_exists(self, research_id, username=None): return research_id in self._store class TestReportStorageABC: """Tests for the abstract base class contract.""" def test_cannot_instantiate_abc_directly(self): """ReportStorage cannot be instantiated without implementing all methods.""" with pytest.raises(TypeError): ReportStorage() def test_concrete_storage_works(self): """Concrete implementation round-trips data.""" s = ConcreteStorage() assert s.save_report("r1", "# Report") is True assert s.get_report("r1") == "# Report" assert s.report_exists("r1") is True def test_get_report_missing(self): """get_report returns None for missing report.""" s = ConcreteStorage() assert s.get_report("missing") is None def test_delete_report(self): """delete_report removes the report.""" s = ConcreteStorage() s.save_report("r2", "content") assert s.delete_report("r2") is True assert s.report_exists("r2") is False def test_delete_nonexistent(self): """delete_report returns False for missing report.""" s = ConcreteStorage() assert s.delete_report("nope") is False # --------------------------------------------------------------------------- # Additional deep-coverage tests # --------------------------------------------------------------------------- from abc import ABC # noqa: E402 class TestAbstractMethodsSetExact: """Verify the exact set of abstract methods declared on ReportStorage.""" def test_abstract_methods_match_documented_interface(self): expected = { "save_report", "get_report", "get_report_with_metadata", "delete_report", "list_reports", "report_exists", } assert ReportStorage.__abstractmethods__ == expected def test_report_storage_is_abc_subclass(self): assert issubclass(ReportStorage, ABC) class TestPartialImplementationRaisesTypeError: """Any missing abstract method must prevent instantiation.""" def test_missing_save_report_raises(self): class Incomplete(ReportStorage): def get_report(self, rid, username=None): return None def get_report_with_metadata(self, rid, username=None): return None def delete_report(self, rid, username=None): return False def list_reports(self, username=None): return [] def report_exists(self, rid, username=None): return False with pytest.raises(TypeError): Incomplete() def test_missing_report_exists_raises(self): class Incomplete(ReportStorage): def save_report(self, rid, content, metadata=None, username=None): return True def get_report(self, rid, username=None): return None def get_report_with_metadata(self, rid, username=None): return None def delete_report(self, rid, username=None): return False def list_reports(self, username=None): return [] with pytest.raises(TypeError): Incomplete() class TestConcreteStorageEdgeCases: """Edge cases not covered in the base tests.""" def test_metadata_none_stored_as_empty_dict(self): s = ConcreteStorage() s.save_report("r1", "text", metadata=None) result = s.get_report_with_metadata("r1") assert result is not None assert result.get("metadata") == {} def test_delete_twice_second_returns_false(self): s = ConcreteStorage() s.save_report("r1", "data") assert s.delete_report("r1") is True assert s.delete_report("r1") is False def test_get_report_with_metadata_returns_none_for_missing(self): s = ConcreteStorage() assert s.get_report_with_metadata("no-such") is None def test_save_overwrite_replaces_content(self): s = ConcreteStorage() s.save_report("r1", "v1") s.save_report("r1", "v2") assert s.get_report("r1") == "v2"