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

333 lines
12 KiB
Python

"""Comprehensive tests for DatabaseWithFileBackupStorage."""
from unittest.mock import MagicMock, patch
from local_deep_research.storage.database_with_file_backup import (
DatabaseWithFileBackupStorage,
)
MODULE = "local_deep_research.storage.database_with_file_backup"
# ---------------------------------------------------------------------------
# __init__
# ---------------------------------------------------------------------------
class TestInit:
"""Tests for __init__."""
@patch(f"{MODULE}.DatabaseReportStorage")
def test_without_file_storage_file_storage_is_none(
self, mock_db_cls, mock_session
):
"""file_storage should be None when enable_file_storage is False."""
storage = DatabaseWithFileBackupStorage(mock_session)
assert storage.file_storage is None
assert storage.enable_file_storage is False
@patch(f"{MODULE}.FileReportStorage")
@patch(f"{MODULE}.DatabaseReportStorage")
def test_with_file_storage_creates_file_report_storage(
self, mock_db_cls, mock_file_cls, mock_session
):
"""file_storage should be a FileReportStorage when enabled."""
storage = DatabaseWithFileBackupStorage(
mock_session, enable_file_storage=True
)
assert storage.enable_file_storage is True
mock_file_cls.assert_called_once_with()
assert storage.file_storage is mock_file_cls.return_value
@patch(f"{MODULE}.DatabaseReportStorage")
def test_db_storage_created_with_session(self, mock_db_cls, mock_session):
"""db_storage should be created by passing session to DatabaseReportStorage."""
storage = DatabaseWithFileBackupStorage(mock_session)
mock_db_cls.assert_called_once_with(mock_session)
assert storage.db_storage is mock_db_cls.return_value
# ---------------------------------------------------------------------------
# save_report
# ---------------------------------------------------------------------------
class TestSaveReport:
"""Tests for save_report."""
def test_db_success_no_file_storage_returns_true(
self, mock_session, sample_report_content
):
"""Should return True and only call db_storage when file storage disabled."""
storage = DatabaseWithFileBackupStorage(mock_session)
storage.db_storage = MagicMock()
storage.db_storage.save_report.return_value = True
result = storage.save_report("r1", sample_report_content)
assert result is True
storage.db_storage.save_report.assert_called_once()
# file_storage is None, nothing else should happen
def test_db_fails_returns_false_immediately(
self, mock_session, sample_report_content
):
"""Should return False immediately when db save fails; no file attempt."""
storage = DatabaseWithFileBackupStorage(
mock_session, enable_file_storage=True
)
storage.db_storage = MagicMock()
storage.db_storage.save_report.return_value = False
storage.file_storage = MagicMock()
result = storage.save_report("r1", sample_report_content)
assert result is False
storage.file_storage.save_report.assert_not_called()
def test_db_success_file_success_returns_true(
self, mock_session, sample_report_content
):
"""Should return True when both db and file saves succeed."""
storage = DatabaseWithFileBackupStorage(
mock_session, enable_file_storage=True
)
storage.db_storage = MagicMock()
storage.db_storage.save_report.return_value = True
storage.file_storage = MagicMock()
storage.file_storage.save_report.return_value = True
result = storage.save_report("r1", sample_report_content)
assert result is True
storage.file_storage.save_report.assert_called_once()
def test_db_success_file_returns_false_still_returns_true(
self, mock_session, sample_report_content
):
"""Should return True even when file save returns False (db succeeded)."""
storage = DatabaseWithFileBackupStorage(
mock_session, enable_file_storage=True
)
storage.db_storage = MagicMock()
storage.db_storage.save_report.return_value = True
storage.file_storage = MagicMock()
storage.file_storage.save_report.return_value = False
result = storage.save_report("r1", sample_report_content)
assert result is True
def test_db_success_file_raises_exception_still_returns_true(
self, mock_session, sample_report_content
):
"""Should return True even when file save raises an exception."""
storage = DatabaseWithFileBackupStorage(
mock_session, enable_file_storage=True
)
storage.db_storage = MagicMock()
storage.db_storage.save_report.return_value = True
storage.file_storage = MagicMock()
storage.file_storage.save_report.side_effect = OSError("disk full")
result = storage.save_report("r1", sample_report_content)
assert result is True
def test_passes_all_arguments_to_db_storage(
self, mock_session, sample_report_content, sample_metadata
):
"""Should forward research_id, content, metadata, username to db_storage."""
storage = DatabaseWithFileBackupStorage(mock_session)
storage.db_storage = MagicMock()
storage.db_storage.save_report.return_value = True
storage.save_report(
"r1", sample_report_content, sample_metadata, "alice"
)
storage.db_storage.save_report.assert_called_once_with(
"r1", sample_report_content, sample_metadata, "alice"
)
# ---------------------------------------------------------------------------
# get_report
# ---------------------------------------------------------------------------
class TestGetReport:
"""Tests for get_report."""
def test_delegates_to_db_storage(self, mock_session, sample_report_content):
"""Should delegate to db_storage.get_report and return its result."""
storage = DatabaseWithFileBackupStorage(mock_session)
storage.db_storage = MagicMock()
storage.db_storage.get_report.return_value = sample_report_content
result = storage.get_report("r1", username="bob")
assert result == sample_report_content
storage.db_storage.get_report.assert_called_once_with("r1", "bob")
def test_never_calls_file_storage_even_when_enabled(
self, mock_session, sample_report_content
):
"""Should never read from file storage, even when it is enabled."""
storage = DatabaseWithFileBackupStorage(
mock_session, enable_file_storage=True
)
storage.db_storage = MagicMock()
storage.db_storage.get_report.return_value = sample_report_content
storage.file_storage = MagicMock()
storage.get_report("r1")
storage.file_storage.get_report.assert_not_called()
# ---------------------------------------------------------------------------
# delete_report
# ---------------------------------------------------------------------------
class TestDeleteReport:
"""Tests for delete_report."""
def test_db_success_no_file_storage_returns_true(self, mock_session):
"""Should return True when db delete succeeds and no file storage."""
storage = DatabaseWithFileBackupStorage(mock_session)
storage.db_storage = MagicMock()
storage.db_storage.delete_report.return_value = True
result = storage.delete_report("r1")
assert result is True
storage.db_storage.delete_report.assert_called_once()
def test_db_success_file_storage_calls_file_delete(self, mock_session):
"""Should call file_storage.delete_report when db delete succeeds."""
storage = DatabaseWithFileBackupStorage(
mock_session, enable_file_storage=True
)
storage.db_storage = MagicMock()
storage.db_storage.delete_report.return_value = True
storage.file_storage = MagicMock()
storage.delete_report("r1", username="carol")
storage.file_storage.delete_report.assert_called_once_with(
"r1", "carol"
)
def test_db_fails_returns_false_file_not_called(self, mock_session):
"""Should return False and skip file delete when db delete fails."""
storage = DatabaseWithFileBackupStorage(
mock_session, enable_file_storage=True
)
storage.db_storage = MagicMock()
storage.db_storage.delete_report.return_value = False
storage.file_storage = MagicMock()
result = storage.delete_report("r1")
assert result is False
storage.file_storage.delete_report.assert_not_called()
def test_db_success_file_raises_exception_still_returns_true(
self, mock_session
):
"""Should return True even when file delete raises an exception."""
storage = DatabaseWithFileBackupStorage(
mock_session, enable_file_storage=True
)
storage.db_storage = MagicMock()
storage.db_storage.delete_report.return_value = True
storage.file_storage = MagicMock()
storage.file_storage.delete_report.side_effect = OSError(
"permission denied"
)
result = storage.delete_report("r1")
assert result is True
# ---------------------------------------------------------------------------
# list_reports
# ---------------------------------------------------------------------------
class TestListReports:
"""Tests for list_reports."""
def test_delegates_to_db_storage(self, mock_session):
"""Should delegate to db_storage.list_reports and return its result."""
storage = DatabaseWithFileBackupStorage(mock_session)
storage.db_storage = MagicMock()
expected = [{"id": "r1"}, {"id": "r2"}]
storage.db_storage.list_reports.return_value = expected
result = storage.list_reports(username="dave")
assert result == expected
storage.db_storage.list_reports.assert_called_once_with("dave")
def test_delegates_without_username(self, mock_session):
"""Should delegate with None username when not provided."""
storage = DatabaseWithFileBackupStorage(mock_session)
storage.db_storage = MagicMock()
storage.db_storage.list_reports.return_value = []
result = storage.list_reports()
assert result == []
storage.db_storage.list_reports.assert_called_once_with(None)
# ---------------------------------------------------------------------------
# get_report_with_metadata
# ---------------------------------------------------------------------------
class TestGetReportWithMetadata:
"""Tests for get_report_with_metadata."""
def test_delegates_to_db_storage(self, mock_session):
"""Should delegate to db_storage.get_report_with_metadata."""
storage = DatabaseWithFileBackupStorage(mock_session)
storage.db_storage = MagicMock()
expected = {"content": "report text", "metadata": {"key": "value"}}
storage.db_storage.get_report_with_metadata.return_value = expected
result = storage.get_report_with_metadata("r1", username="eve")
assert result == expected
storage.db_storage.get_report_with_metadata.assert_called_once_with(
"r1", "eve"
)
# ---------------------------------------------------------------------------
# report_exists
# ---------------------------------------------------------------------------
class TestReportExists:
"""Tests for report_exists."""
def test_delegates_to_db_storage(self, mock_session):
"""Should delegate to db_storage.report_exists and return its result."""
storage = DatabaseWithFileBackupStorage(mock_session)
storage.db_storage = MagicMock()
storage.db_storage.report_exists.return_value = True
result = storage.report_exists("r1", username="frank")
assert result is True
storage.db_storage.report_exists.assert_called_once_with("r1", "frank")