"""Test backup platform for the Recorder integration.""" from contextlib import AbstractContextManager, nullcontext as does_not_raise from unittest.mock import patch import pytest from homeassistant.components.recorder.backup import async_post_backup, async_pre_backup from homeassistant.core import CoreState, HomeAssistant from homeassistant.exceptions import HomeAssistantError @pytest.mark.usefixtures("recorder_mock") async def test_async_pre_backup(hass: HomeAssistant) -> None: """Test pre backup.""" with patch( "homeassistant.components.recorder.core.Recorder.lock_database" ) as lock_mock: await async_pre_backup(hass) assert lock_mock.called RAISES_HASS_NOT_RUNNING = pytest.raises( HomeAssistantError, match="Home Assistant is not running" ) @pytest.mark.parametrize( ("core_state", "expected_result", "lock_calls"), [ (CoreState.final_write, RAISES_HASS_NOT_RUNNING, 0), (CoreState.not_running, RAISES_HASS_NOT_RUNNING, 0), (CoreState.running, does_not_raise(), 1), (CoreState.starting, RAISES_HASS_NOT_RUNNING, 0), (CoreState.stopped, RAISES_HASS_NOT_RUNNING, 0), (CoreState.stopping, RAISES_HASS_NOT_RUNNING, 0), ], ) @pytest.mark.usefixtures("recorder_mock") async def test_async_pre_backup_core_state( hass: HomeAssistant, core_state: CoreState, expected_result: AbstractContextManager, lock_calls: int, ) -> None: """Test pre backup in different core states.""" hass.set_state(core_state) with ( # pylint: disable=confusing-with-statement patch( "homeassistant.components.recorder.core.Recorder.lock_database" ) as lock_mock, expected_result, ): await async_pre_backup(hass) assert len(lock_mock.mock_calls) == lock_calls @pytest.mark.usefixtures("recorder_mock") async def test_async_pre_backup_with_timeout(hass: HomeAssistant) -> None: """Test pre backup with timeout.""" with ( patch( "homeassistant.components.recorder.core.Recorder.lock_database", side_effect=TimeoutError(), ) as lock_mock, pytest.raises(TimeoutError), ): await async_pre_backup(hass) assert lock_mock.called @pytest.mark.usefixtures("recorder_mock") async def test_async_pre_backup_with_migration(hass: HomeAssistant) -> None: """Test pre backup with migration.""" with ( patch( "homeassistant.components.recorder.core.Recorder.lock_database" ) as lock_mock, patch( "homeassistant.components.recorder.backup.async_migration_in_progress", return_value=True, ), pytest.raises(HomeAssistantError, match="Database migration in progress"), ): await async_pre_backup(hass) assert not lock_mock.called @pytest.mark.usefixtures("recorder_mock") async def test_async_post_backup(hass: HomeAssistant) -> None: """Test post backup.""" with patch( "homeassistant.components.recorder.core.Recorder.unlock_database" ) as unlock_mock: await async_post_backup(hass) assert unlock_mock.called @pytest.mark.usefixtures("recorder_mock") async def test_async_post_backup_failure(hass: HomeAssistant) -> None: """Test post backup failure.""" with ( patch( "homeassistant.components.recorder.core.Recorder.unlock_database", return_value=False, ) as unlock_mock, pytest.raises( HomeAssistantError, match="Could not release database write lock" ), ): await async_post_backup(hass) assert unlock_mock.called