"""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")