1195 lines
34 KiB
Python
1195 lines
34 KiB
Python
"""Test the addon manager."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from collections.abc import Generator
|
|
import logging
|
|
from typing import Any
|
|
from unittest.mock import AsyncMock, call, patch
|
|
|
|
import pytest
|
|
|
|
from homeassistant.components.hassio.addon_manager import (
|
|
AddonError,
|
|
AddonInfo,
|
|
AddonManager,
|
|
AddonState,
|
|
)
|
|
from homeassistant.components.hassio.handler import HassioAPIError
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
@pytest.fixture(name="addon_manager")
|
|
def addon_manager_fixture(hass: HomeAssistant) -> AddonManager:
|
|
"""Return an AddonManager instance."""
|
|
return AddonManager(hass, LOGGER, "Test", "test_addon")
|
|
|
|
|
|
@pytest.fixture(name="addon_not_installed")
|
|
def addon_not_installed_fixture(
|
|
addon_store_info: AsyncMock, addon_info: AsyncMock
|
|
) -> AsyncMock:
|
|
"""Mock add-on not installed."""
|
|
addon_store_info.return_value["available"] = True
|
|
return addon_info
|
|
|
|
|
|
@pytest.fixture(name="addon_installed")
|
|
def mock_addon_installed(
|
|
addon_store_info: AsyncMock, addon_info: AsyncMock
|
|
) -> AsyncMock:
|
|
"""Mock add-on already installed but not running."""
|
|
addon_store_info.return_value = {
|
|
"available": True,
|
|
"installed": "1.0.0",
|
|
"state": "stopped",
|
|
"version": "1.0.0",
|
|
}
|
|
addon_info.return_value["available"] = True
|
|
addon_info.return_value["hostname"] = "core-test-addon"
|
|
addon_info.return_value["state"] = "stopped"
|
|
addon_info.return_value["version"] = "1.0.0"
|
|
return addon_info
|
|
|
|
|
|
@pytest.fixture(name="get_addon_discovery_info")
|
|
def get_addon_discovery_info_fixture() -> Generator[AsyncMock, None, None]:
|
|
"""Mock get add-on discovery info."""
|
|
with patch(
|
|
"homeassistant.components.hassio.addon_manager.async_get_addon_discovery_info"
|
|
) as get_addon_discovery_info:
|
|
yield get_addon_discovery_info
|
|
|
|
|
|
@pytest.fixture(name="addon_store_info")
|
|
def addon_store_info_fixture() -> Generator[AsyncMock, None, None]:
|
|
"""Mock Supervisor add-on store info."""
|
|
with patch(
|
|
"homeassistant.components.hassio.addon_manager.async_get_addon_store_info"
|
|
) as addon_store_info:
|
|
addon_store_info.return_value = {
|
|
"available": False,
|
|
"installed": None,
|
|
"state": None,
|
|
"version": "1.0.0",
|
|
}
|
|
yield addon_store_info
|
|
|
|
|
|
@pytest.fixture(name="addon_info")
|
|
def addon_info_fixture() -> Generator[AsyncMock, None, None]:
|
|
"""Mock Supervisor add-on info."""
|
|
with patch(
|
|
"homeassistant.components.hassio.addon_manager.async_get_addon_info",
|
|
) as addon_info:
|
|
addon_info.return_value = {
|
|
"available": False,
|
|
"hostname": None,
|
|
"options": {},
|
|
"state": None,
|
|
"update_available": False,
|
|
"version": None,
|
|
}
|
|
yield addon_info
|
|
|
|
|
|
@pytest.fixture(name="set_addon_options")
|
|
def set_addon_options_fixture() -> Generator[AsyncMock, None, None]:
|
|
"""Mock set add-on options."""
|
|
with patch(
|
|
"homeassistant.components.hassio.addon_manager.async_set_addon_options"
|
|
) as set_options:
|
|
yield set_options
|
|
|
|
|
|
@pytest.fixture(name="install_addon")
|
|
def install_addon_fixture() -> Generator[AsyncMock, None, None]:
|
|
"""Mock install add-on."""
|
|
with patch(
|
|
"homeassistant.components.hassio.addon_manager.async_install_addon"
|
|
) as install_addon:
|
|
yield install_addon
|
|
|
|
|
|
@pytest.fixture(name="uninstall_addon")
|
|
def uninstall_addon_fixture() -> Generator[AsyncMock, None, None]:
|
|
"""Mock uninstall add-on."""
|
|
with patch(
|
|
"homeassistant.components.hassio.addon_manager.async_uninstall_addon"
|
|
) as uninstall_addon:
|
|
yield uninstall_addon
|
|
|
|
|
|
@pytest.fixture(name="start_addon")
|
|
def start_addon_fixture() -> Generator[AsyncMock, None, None]:
|
|
"""Mock start add-on."""
|
|
with patch(
|
|
"homeassistant.components.hassio.addon_manager.async_start_addon"
|
|
) as start_addon:
|
|
yield start_addon
|
|
|
|
|
|
@pytest.fixture(name="restart_addon")
|
|
def restart_addon_fixture() -> Generator[AsyncMock, None, None]:
|
|
"""Mock restart add-on."""
|
|
with patch(
|
|
"homeassistant.components.hassio.addon_manager.async_restart_addon"
|
|
) as restart_addon:
|
|
yield restart_addon
|
|
|
|
|
|
@pytest.fixture(name="stop_addon")
|
|
def stop_addon_fixture() -> Generator[AsyncMock, None, None]:
|
|
"""Mock stop add-on."""
|
|
with patch(
|
|
"homeassistant.components.hassio.addon_manager.async_stop_addon"
|
|
) as stop_addon:
|
|
yield stop_addon
|
|
|
|
|
|
@pytest.fixture(name="create_backup")
|
|
def create_backup_fixture() -> Generator[AsyncMock, None, None]:
|
|
"""Mock create backup."""
|
|
with patch(
|
|
"homeassistant.components.hassio.addon_manager.async_create_backup"
|
|
) as create_backup:
|
|
yield create_backup
|
|
|
|
|
|
@pytest.fixture(name="update_addon")
|
|
def mock_update_addon() -> Generator[AsyncMock, None, None]:
|
|
"""Mock update add-on."""
|
|
with patch(
|
|
"homeassistant.components.hassio.addon_manager.async_update_addon"
|
|
) as update_addon:
|
|
yield update_addon
|
|
|
|
|
|
async def test_not_installed_raises_exception(
|
|
addon_manager: AddonManager,
|
|
addon_not_installed: dict[str, Any],
|
|
) -> None:
|
|
"""Test addon not installed raises exception."""
|
|
addon_config = {"test_key": "test"}
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_configure_addon(addon_config)
|
|
|
|
assert str(err.value) == "Test add-on is not installed"
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_update_addon()
|
|
|
|
assert str(err.value) == "Test add-on is not installed"
|
|
|
|
|
|
async def test_not_available_raises_exception(
|
|
addon_manager: AddonManager,
|
|
addon_store_info: AsyncMock,
|
|
addon_info: AsyncMock,
|
|
) -> None:
|
|
"""Test addon not available raises exception."""
|
|
addon_store_info.return_value["available"] = False
|
|
addon_info.return_value["available"] = False
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_install_addon()
|
|
|
|
assert str(err.value) == "Test add-on is not available"
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_update_addon()
|
|
|
|
assert str(err.value) == "Test add-on is not available"
|
|
|
|
|
|
async def test_get_addon_discovery_info(
|
|
addon_manager: AddonManager, get_addon_discovery_info: AsyncMock
|
|
) -> None:
|
|
"""Test get addon discovery info."""
|
|
get_addon_discovery_info.return_value = {"config": {"test_key": "test"}}
|
|
|
|
assert await addon_manager.async_get_addon_discovery_info() == {"test_key": "test"}
|
|
|
|
assert get_addon_discovery_info.call_count == 1
|
|
|
|
|
|
async def test_missing_addon_discovery_info(
|
|
addon_manager: AddonManager, get_addon_discovery_info: AsyncMock
|
|
) -> None:
|
|
"""Test missing addon discovery info."""
|
|
get_addon_discovery_info.return_value = None
|
|
|
|
with pytest.raises(AddonError):
|
|
await addon_manager.async_get_addon_discovery_info()
|
|
|
|
assert get_addon_discovery_info.call_count == 1
|
|
|
|
|
|
async def test_get_addon_discovery_info_error(
|
|
addon_manager: AddonManager, get_addon_discovery_info: AsyncMock
|
|
) -> None:
|
|
"""Test get addon discovery info raises error."""
|
|
get_addon_discovery_info.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
assert await addon_manager.async_get_addon_discovery_info()
|
|
|
|
assert str(err.value) == "Failed to get the Test add-on discovery info: Boom"
|
|
|
|
assert get_addon_discovery_info.call_count == 1
|
|
|
|
|
|
async def test_get_addon_info_not_installed(
|
|
addon_manager: AddonManager, addon_not_installed: AsyncMock
|
|
) -> None:
|
|
"""Test get addon info when addon is not installed.."""
|
|
assert await addon_manager.async_get_addon_info() == AddonInfo(
|
|
available=True,
|
|
hostname=None,
|
|
options={},
|
|
state=AddonState.NOT_INSTALLED,
|
|
update_available=False,
|
|
version=None,
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("addon_info_state", "addon_state"),
|
|
[("started", AddonState.RUNNING), ("stopped", AddonState.NOT_RUNNING)],
|
|
)
|
|
async def test_get_addon_info(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
addon_info_state: str,
|
|
addon_state: AddonState,
|
|
) -> None:
|
|
"""Test get addon info when addon is installed."""
|
|
addon_installed.return_value["state"] = addon_info_state
|
|
assert await addon_manager.async_get_addon_info() == AddonInfo(
|
|
available=True,
|
|
hostname="core-test-addon",
|
|
options={},
|
|
state=addon_state,
|
|
update_available=False,
|
|
version="1.0.0",
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
(
|
|
"addon_info_error",
|
|
"addon_info_calls",
|
|
"addon_store_info_error",
|
|
"addon_store_info_calls",
|
|
),
|
|
[(HassioAPIError("Boom"), 1, None, 1), (None, 0, HassioAPIError("Boom"), 1)],
|
|
)
|
|
async def test_get_addon_info_error(
|
|
addon_manager: AddonManager,
|
|
addon_info: AsyncMock,
|
|
addon_store_info: AsyncMock,
|
|
addon_installed: AsyncMock,
|
|
addon_info_error: Exception | None,
|
|
addon_info_calls: int,
|
|
addon_store_info_error: Exception | None,
|
|
addon_store_info_calls: int,
|
|
) -> None:
|
|
"""Test get addon info raises error."""
|
|
addon_info.side_effect = addon_info_error
|
|
addon_store_info.side_effect = addon_store_info_error
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_get_addon_info()
|
|
|
|
assert str(err.value) == "Failed to get the Test add-on info: Boom"
|
|
|
|
assert addon_info.call_count == addon_info_calls
|
|
assert addon_store_info.call_count == addon_store_info_calls
|
|
|
|
|
|
async def test_set_addon_options(
|
|
hass: HomeAssistant, addon_manager: AddonManager, set_addon_options: AsyncMock
|
|
) -> None:
|
|
"""Test set addon options."""
|
|
await addon_manager.async_set_addon_options({"test_key": "test"})
|
|
|
|
assert set_addon_options.call_count == 1
|
|
assert set_addon_options.call_args == call(
|
|
hass, "test_addon", {"options": {"test_key": "test"}}
|
|
)
|
|
|
|
|
|
async def test_set_addon_options_error(
|
|
hass: HomeAssistant, addon_manager: AddonManager, set_addon_options: AsyncMock
|
|
) -> None:
|
|
"""Test set addon options raises error."""
|
|
set_addon_options.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_set_addon_options({"test_key": "test"})
|
|
|
|
assert str(err.value) == "Failed to set the Test add-on options: Boom"
|
|
|
|
assert set_addon_options.call_count == 1
|
|
assert set_addon_options.call_args == call(
|
|
hass, "test_addon", {"options": {"test_key": "test"}}
|
|
)
|
|
|
|
|
|
async def test_install_addon(
|
|
addon_manager: AddonManager,
|
|
install_addon: AsyncMock,
|
|
addon_store_info: AsyncMock,
|
|
addon_info: AsyncMock,
|
|
) -> None:
|
|
"""Test install addon."""
|
|
addon_store_info.return_value["available"] = True
|
|
addon_info.return_value["available"] = True
|
|
|
|
await addon_manager.async_install_addon()
|
|
|
|
assert install_addon.call_count == 1
|
|
|
|
|
|
async def test_install_addon_error(
|
|
addon_manager: AddonManager,
|
|
install_addon: AsyncMock,
|
|
addon_store_info: AsyncMock,
|
|
addon_info: AsyncMock,
|
|
) -> None:
|
|
"""Test install addon raises error."""
|
|
addon_store_info.return_value["available"] = True
|
|
addon_info.return_value["available"] = True
|
|
install_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_install_addon()
|
|
|
|
assert str(err.value) == "Failed to install the Test add-on: Boom"
|
|
|
|
assert install_addon.call_count == 1
|
|
|
|
|
|
async def test_schedule_install_addon(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
install_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test schedule install addon."""
|
|
install_task = addon_manager.async_schedule_install_addon()
|
|
|
|
assert addon_manager.task_in_progress() is True
|
|
|
|
assert await addon_manager.async_get_addon_info() == AddonInfo(
|
|
available=True,
|
|
hostname="core-test-addon",
|
|
options={},
|
|
state=AddonState.INSTALLING,
|
|
update_available=False,
|
|
version="1.0.0",
|
|
)
|
|
|
|
# Make sure that actually only one install task is running.
|
|
install_task_two = addon_manager.async_schedule_install_addon()
|
|
|
|
await asyncio.gather(install_task, install_task_two)
|
|
|
|
assert addon_manager.task_in_progress() is False
|
|
assert install_addon.call_count == 1
|
|
|
|
install_addon.reset_mock()
|
|
|
|
# Test that another call can be made after the install is done.
|
|
await addon_manager.async_schedule_install_addon()
|
|
|
|
assert install_addon.call_count == 1
|
|
|
|
|
|
async def test_schedule_install_addon_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
install_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test schedule install addon raises error."""
|
|
install_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_schedule_install_addon()
|
|
|
|
assert str(err.value) == "Failed to install the Test add-on: Boom"
|
|
|
|
assert install_addon.call_count == 1
|
|
|
|
|
|
async def test_schedule_install_addon_logs_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
install_addon: AsyncMock,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test schedule install addon logs error."""
|
|
install_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
await addon_manager.async_schedule_install_addon(catch_error=True)
|
|
|
|
assert "Failed to install the Test add-on: Boom" in caplog.text
|
|
assert install_addon.call_count == 1
|
|
|
|
|
|
async def test_uninstall_addon(
|
|
addon_manager: AddonManager, uninstall_addon: AsyncMock
|
|
) -> None:
|
|
"""Test uninstall addon."""
|
|
await addon_manager.async_uninstall_addon()
|
|
|
|
assert uninstall_addon.call_count == 1
|
|
|
|
|
|
async def test_uninstall_addon_error(
|
|
addon_manager: AddonManager, uninstall_addon: AsyncMock
|
|
) -> None:
|
|
"""Test uninstall addon raises error."""
|
|
uninstall_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_uninstall_addon()
|
|
|
|
assert str(err.value) == "Failed to uninstall the Test add-on: Boom"
|
|
|
|
assert uninstall_addon.call_count == 1
|
|
|
|
|
|
async def test_start_addon(addon_manager: AddonManager, start_addon: AsyncMock) -> None:
|
|
"""Test start addon."""
|
|
await addon_manager.async_start_addon()
|
|
|
|
assert start_addon.call_count == 1
|
|
|
|
|
|
async def test_start_addon_error(
|
|
addon_manager: AddonManager, start_addon: AsyncMock
|
|
) -> None:
|
|
"""Test start addon raises error."""
|
|
start_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_start_addon()
|
|
|
|
assert str(err.value) == "Failed to start the Test add-on: Boom"
|
|
|
|
assert start_addon.call_count == 1
|
|
|
|
|
|
async def test_schedule_start_addon(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
start_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test schedule start addon."""
|
|
start_task = addon_manager.async_schedule_start_addon()
|
|
|
|
assert addon_manager.task_in_progress() is True
|
|
|
|
# Make sure that actually only one start task is running.
|
|
start_task_two = addon_manager.async_schedule_start_addon()
|
|
|
|
await asyncio.gather(start_task, start_task_two)
|
|
|
|
assert addon_manager.task_in_progress() is False
|
|
assert start_addon.call_count == 1
|
|
|
|
start_addon.reset_mock()
|
|
|
|
# Test that another call can be made after the start is done.
|
|
await addon_manager.async_schedule_start_addon()
|
|
|
|
assert start_addon.call_count == 1
|
|
|
|
|
|
async def test_schedule_start_addon_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
start_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test schedule start addon raises error."""
|
|
start_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_schedule_start_addon()
|
|
|
|
assert str(err.value) == "Failed to start the Test add-on: Boom"
|
|
|
|
assert start_addon.call_count == 1
|
|
|
|
|
|
async def test_schedule_start_addon_logs_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
start_addon: AsyncMock,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test schedule start addon logs error."""
|
|
start_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
await addon_manager.async_schedule_start_addon(catch_error=True)
|
|
|
|
assert "Failed to start the Test add-on: Boom" in caplog.text
|
|
assert start_addon.call_count == 1
|
|
|
|
|
|
async def test_restart_addon(
|
|
addon_manager: AddonManager, restart_addon: AsyncMock
|
|
) -> None:
|
|
"""Test restart addon."""
|
|
await addon_manager.async_restart_addon()
|
|
|
|
assert restart_addon.call_count == 1
|
|
|
|
|
|
async def test_restart_addon_error(
|
|
addon_manager: AddonManager, restart_addon: AsyncMock
|
|
) -> None:
|
|
"""Test restart addon raises error."""
|
|
restart_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_restart_addon()
|
|
|
|
assert str(err.value) == "Failed to restart the Test add-on: Boom"
|
|
|
|
assert restart_addon.call_count == 1
|
|
|
|
|
|
async def test_schedule_restart_addon(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
restart_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test schedule restart addon."""
|
|
restart_task = addon_manager.async_schedule_restart_addon()
|
|
|
|
assert addon_manager.task_in_progress() is True
|
|
|
|
# Make sure that actually only one start task is running.
|
|
restart_task_two = addon_manager.async_schedule_restart_addon()
|
|
|
|
await asyncio.gather(restart_task, restart_task_two)
|
|
|
|
assert addon_manager.task_in_progress() is False
|
|
assert restart_addon.call_count == 1
|
|
|
|
restart_addon.reset_mock()
|
|
|
|
# Test that another call can be made after the restart is done.
|
|
await addon_manager.async_schedule_restart_addon()
|
|
|
|
assert restart_addon.call_count == 1
|
|
|
|
|
|
async def test_schedule_restart_addon_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
restart_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test schedule restart addon raises error."""
|
|
restart_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_schedule_restart_addon()
|
|
|
|
assert str(err.value) == "Failed to restart the Test add-on: Boom"
|
|
|
|
assert restart_addon.call_count == 1
|
|
|
|
|
|
async def test_schedule_restart_addon_logs_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
restart_addon: AsyncMock,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test schedule restart addon logs error."""
|
|
restart_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
await addon_manager.async_schedule_restart_addon(catch_error=True)
|
|
|
|
assert "Failed to restart the Test add-on: Boom" in caplog.text
|
|
assert restart_addon.call_count == 1
|
|
|
|
|
|
async def test_stop_addon(addon_manager: AddonManager, stop_addon: AsyncMock) -> None:
|
|
"""Test stop addon."""
|
|
await addon_manager.async_stop_addon()
|
|
|
|
assert stop_addon.call_count == 1
|
|
|
|
|
|
async def test_stop_addon_error(
|
|
addon_manager: AddonManager, stop_addon: AsyncMock
|
|
) -> None:
|
|
"""Test stop addon raises error."""
|
|
stop_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_stop_addon()
|
|
|
|
assert str(err.value) == "Failed to stop the Test add-on: Boom"
|
|
|
|
assert stop_addon.call_count == 1
|
|
|
|
|
|
async def test_update_addon(
|
|
hass: HomeAssistant,
|
|
addon_manager: AddonManager,
|
|
addon_info: AsyncMock,
|
|
addon_installed: AsyncMock,
|
|
create_backup: AsyncMock,
|
|
update_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test update addon."""
|
|
addon_info.return_value["update_available"] = True
|
|
|
|
await addon_manager.async_update_addon()
|
|
|
|
assert addon_info.call_count == 2
|
|
assert create_backup.call_count == 1
|
|
assert create_backup.call_args == call(
|
|
hass, {"name": "addon_test_addon_1.0.0", "addons": ["test_addon"]}, partial=True
|
|
)
|
|
assert update_addon.call_count == 1
|
|
|
|
|
|
async def test_update_addon_no_update(
|
|
addon_manager: AddonManager,
|
|
addon_info: AsyncMock,
|
|
addon_installed: AsyncMock,
|
|
create_backup: AsyncMock,
|
|
update_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test update addon without update available."""
|
|
addon_info.return_value["update_available"] = False
|
|
|
|
await addon_manager.async_update_addon()
|
|
|
|
assert addon_info.call_count == 1
|
|
assert create_backup.call_count == 0
|
|
assert update_addon.call_count == 0
|
|
|
|
|
|
async def test_update_addon_error(
|
|
hass: HomeAssistant,
|
|
addon_manager: AddonManager,
|
|
addon_info: AsyncMock,
|
|
addon_installed: AsyncMock,
|
|
create_backup: AsyncMock,
|
|
update_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test update addon raises error."""
|
|
addon_info.return_value["update_available"] = True
|
|
update_addon.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_update_addon()
|
|
|
|
assert str(err.value) == "Failed to update the Test add-on: Boom"
|
|
|
|
assert addon_info.call_count == 2
|
|
assert create_backup.call_count == 1
|
|
assert create_backup.call_args == call(
|
|
hass, {"name": "addon_test_addon_1.0.0", "addons": ["test_addon"]}, partial=True
|
|
)
|
|
assert update_addon.call_count == 1
|
|
|
|
|
|
async def test_schedule_update_addon(
|
|
hass: HomeAssistant,
|
|
addon_manager: AddonManager,
|
|
addon_info: AsyncMock,
|
|
addon_installed: AsyncMock,
|
|
create_backup: AsyncMock,
|
|
update_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test schedule update addon."""
|
|
addon_info.return_value["update_available"] = True
|
|
|
|
update_task = addon_manager.async_schedule_update_addon()
|
|
|
|
assert addon_manager.task_in_progress() is True
|
|
|
|
assert await addon_manager.async_get_addon_info() == AddonInfo(
|
|
available=True,
|
|
hostname="core-test-addon",
|
|
options={},
|
|
state=AddonState.UPDATING,
|
|
update_available=True,
|
|
version="1.0.0",
|
|
)
|
|
|
|
# Make sure that actually only one update task is running.
|
|
update_task_two = addon_manager.async_schedule_update_addon()
|
|
|
|
await asyncio.gather(update_task, update_task_two)
|
|
|
|
assert addon_manager.task_in_progress() is False
|
|
assert addon_info.call_count == 3
|
|
assert create_backup.call_count == 1
|
|
assert create_backup.call_args == call(
|
|
hass, {"name": "addon_test_addon_1.0.0", "addons": ["test_addon"]}, partial=True
|
|
)
|
|
assert update_addon.call_count == 1
|
|
|
|
update_addon.reset_mock()
|
|
|
|
# Test that another call can be made after the update is done.
|
|
await addon_manager.async_schedule_update_addon()
|
|
|
|
assert update_addon.call_count == 1
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
(
|
|
"create_backup_error",
|
|
"create_backup_calls",
|
|
"update_addon_error",
|
|
"update_addon_calls",
|
|
"error_message",
|
|
),
|
|
[
|
|
(
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
None,
|
|
0,
|
|
"Failed to create a backup of the Test add-on: Boom",
|
|
),
|
|
(
|
|
None,
|
|
1,
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
"Failed to update the Test add-on: Boom",
|
|
),
|
|
],
|
|
)
|
|
async def test_schedule_update_addon_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
create_backup: AsyncMock,
|
|
update_addon: AsyncMock,
|
|
create_backup_error: Exception | None,
|
|
create_backup_calls: int,
|
|
update_addon_error: Exception | None,
|
|
update_addon_calls: int,
|
|
error_message: str,
|
|
) -> None:
|
|
"""Test schedule update addon raises error."""
|
|
addon_installed.return_value["update_available"] = True
|
|
create_backup.side_effect = create_backup_error
|
|
update_addon.side_effect = update_addon_error
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_schedule_update_addon()
|
|
|
|
assert str(err.value) == error_message
|
|
|
|
assert create_backup.call_count == create_backup_calls
|
|
assert update_addon.call_count == update_addon_calls
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
(
|
|
"create_backup_error",
|
|
"create_backup_calls",
|
|
"update_addon_error",
|
|
"update_addon_calls",
|
|
"error_log",
|
|
),
|
|
[
|
|
(
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
None,
|
|
0,
|
|
"Failed to create a backup of the Test add-on: Boom",
|
|
),
|
|
(
|
|
None,
|
|
1,
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
"Failed to update the Test add-on: Boom",
|
|
),
|
|
],
|
|
)
|
|
async def test_schedule_update_addon_logs_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
create_backup: AsyncMock,
|
|
update_addon: AsyncMock,
|
|
create_backup_error: Exception | None,
|
|
create_backup_calls: int,
|
|
update_addon_error: Exception | None,
|
|
update_addon_calls: int,
|
|
error_log: str,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test schedule update addon logs error."""
|
|
addon_installed.return_value["update_available"] = True
|
|
create_backup.side_effect = create_backup_error
|
|
update_addon.side_effect = update_addon_error
|
|
|
|
await addon_manager.async_schedule_update_addon(catch_error=True)
|
|
|
|
assert error_log in caplog.text
|
|
assert create_backup.call_count == create_backup_calls
|
|
assert update_addon.call_count == update_addon_calls
|
|
|
|
|
|
async def test_create_backup(
|
|
hass: HomeAssistant,
|
|
addon_manager: AddonManager,
|
|
addon_info: AsyncMock,
|
|
addon_installed: AsyncMock,
|
|
create_backup: AsyncMock,
|
|
) -> None:
|
|
"""Test creating a backup of the addon."""
|
|
await addon_manager.async_create_backup()
|
|
|
|
assert addon_info.call_count == 1
|
|
assert create_backup.call_count == 1
|
|
assert create_backup.call_args == call(
|
|
hass, {"name": "addon_test_addon_1.0.0", "addons": ["test_addon"]}, partial=True
|
|
)
|
|
|
|
|
|
async def test_create_backup_error(
|
|
hass: HomeAssistant,
|
|
addon_manager: AddonManager,
|
|
addon_info: AsyncMock,
|
|
addon_installed: AsyncMock,
|
|
create_backup: AsyncMock,
|
|
) -> None:
|
|
"""Test creating a backup of the addon raises error."""
|
|
create_backup.side_effect = HassioAPIError("Boom")
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_create_backup()
|
|
|
|
assert str(err.value) == "Failed to create a backup of the Test add-on: Boom"
|
|
|
|
assert addon_info.call_count == 1
|
|
assert create_backup.call_count == 1
|
|
assert create_backup.call_args == call(
|
|
hass, {"name": "addon_test_addon_1.0.0", "addons": ["test_addon"]}, partial=True
|
|
)
|
|
|
|
|
|
async def test_schedule_install_setup_addon(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
install_addon: AsyncMock,
|
|
set_addon_options: AsyncMock,
|
|
start_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test schedule install setup addon."""
|
|
install_task = addon_manager.async_schedule_install_setup_addon(
|
|
{"test_key": "test"}
|
|
)
|
|
|
|
assert addon_manager.task_in_progress() is True
|
|
|
|
# Make sure that actually only one install task is running.
|
|
install_task_two = addon_manager.async_schedule_install_setup_addon(
|
|
{"test_key": "test"}
|
|
)
|
|
|
|
await asyncio.gather(install_task, install_task_two)
|
|
|
|
assert addon_manager.task_in_progress() is False
|
|
assert install_addon.call_count == 1
|
|
assert set_addon_options.call_count == 1
|
|
assert start_addon.call_count == 1
|
|
|
|
install_addon.reset_mock()
|
|
set_addon_options.reset_mock()
|
|
start_addon.reset_mock()
|
|
|
|
# Test that another call can be made after the install is done.
|
|
await addon_manager.async_schedule_install_setup_addon({"test_key": "test"})
|
|
|
|
assert install_addon.call_count == 1
|
|
assert set_addon_options.call_count == 1
|
|
assert start_addon.call_count == 1
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
(
|
|
"install_addon_error",
|
|
"install_addon_calls",
|
|
"set_addon_options_error",
|
|
"set_addon_options_calls",
|
|
"start_addon_error",
|
|
"start_addon_calls",
|
|
"error_message",
|
|
),
|
|
[
|
|
(
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
None,
|
|
0,
|
|
None,
|
|
0,
|
|
"Failed to install the Test add-on: Boom",
|
|
),
|
|
(
|
|
None,
|
|
1,
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
None,
|
|
0,
|
|
"Failed to set the Test add-on options: Boom",
|
|
),
|
|
(
|
|
None,
|
|
1,
|
|
None,
|
|
1,
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
"Failed to start the Test add-on: Boom",
|
|
),
|
|
],
|
|
)
|
|
async def test_schedule_install_setup_addon_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
install_addon: AsyncMock,
|
|
set_addon_options: AsyncMock,
|
|
start_addon: AsyncMock,
|
|
install_addon_error: Exception | None,
|
|
install_addon_calls: int,
|
|
set_addon_options_error: Exception | None,
|
|
set_addon_options_calls: int,
|
|
start_addon_error: Exception | None,
|
|
start_addon_calls: int,
|
|
error_message: str,
|
|
) -> None:
|
|
"""Test schedule install setup addon raises error."""
|
|
install_addon.side_effect = install_addon_error
|
|
set_addon_options.side_effect = set_addon_options_error
|
|
start_addon.side_effect = start_addon_error
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_schedule_install_setup_addon({"test_key": "test"})
|
|
|
|
assert str(err.value) == error_message
|
|
|
|
assert install_addon.call_count == install_addon_calls
|
|
assert set_addon_options.call_count == set_addon_options_calls
|
|
assert start_addon.call_count == start_addon_calls
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
(
|
|
"install_addon_error",
|
|
"install_addon_calls",
|
|
"set_addon_options_error",
|
|
"set_addon_options_calls",
|
|
"start_addon_error",
|
|
"start_addon_calls",
|
|
"error_log",
|
|
),
|
|
[
|
|
(
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
None,
|
|
0,
|
|
None,
|
|
0,
|
|
"Failed to install the Test add-on: Boom",
|
|
),
|
|
(
|
|
None,
|
|
1,
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
None,
|
|
0,
|
|
"Failed to set the Test add-on options: Boom",
|
|
),
|
|
(
|
|
None,
|
|
1,
|
|
None,
|
|
1,
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
"Failed to start the Test add-on: Boom",
|
|
),
|
|
],
|
|
)
|
|
async def test_schedule_install_setup_addon_logs_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
install_addon: AsyncMock,
|
|
set_addon_options: AsyncMock,
|
|
start_addon: AsyncMock,
|
|
install_addon_error: Exception | None,
|
|
install_addon_calls: int,
|
|
set_addon_options_error: Exception | None,
|
|
set_addon_options_calls: int,
|
|
start_addon_error: Exception | None,
|
|
start_addon_calls: int,
|
|
error_log: str,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test schedule install setup addon logs error."""
|
|
install_addon.side_effect = install_addon_error
|
|
set_addon_options.side_effect = set_addon_options_error
|
|
start_addon.side_effect = start_addon_error
|
|
|
|
await addon_manager.async_schedule_install_setup_addon(
|
|
{"test_key": "test"}, catch_error=True
|
|
)
|
|
|
|
assert error_log in caplog.text
|
|
assert install_addon.call_count == install_addon_calls
|
|
assert set_addon_options.call_count == set_addon_options_calls
|
|
assert start_addon.call_count == start_addon_calls
|
|
|
|
|
|
async def test_schedule_setup_addon(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
set_addon_options: AsyncMock,
|
|
start_addon: AsyncMock,
|
|
) -> None:
|
|
"""Test schedule setup addon."""
|
|
start_task = addon_manager.async_schedule_setup_addon({"test_key": "test"})
|
|
|
|
assert addon_manager.task_in_progress() is True
|
|
|
|
# Make sure that actually only one start task is running.
|
|
start_task_two = addon_manager.async_schedule_setup_addon({"test_key": "test"})
|
|
|
|
await asyncio.gather(start_task, start_task_two)
|
|
|
|
assert addon_manager.task_in_progress() is False
|
|
assert set_addon_options.call_count == 1
|
|
assert start_addon.call_count == 1
|
|
|
|
set_addon_options.reset_mock()
|
|
start_addon.reset_mock()
|
|
|
|
# Test that another call can be made after the start is done.
|
|
await addon_manager.async_schedule_setup_addon({"test_key": "test"})
|
|
|
|
assert set_addon_options.call_count == 1
|
|
assert start_addon.call_count == 1
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
(
|
|
"set_addon_options_error",
|
|
"set_addon_options_calls",
|
|
"start_addon_error",
|
|
"start_addon_calls",
|
|
"error_message",
|
|
),
|
|
[
|
|
(
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
None,
|
|
0,
|
|
"Failed to set the Test add-on options: Boom",
|
|
),
|
|
(
|
|
None,
|
|
1,
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
"Failed to start the Test add-on: Boom",
|
|
),
|
|
],
|
|
)
|
|
async def test_schedule_setup_addon_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
set_addon_options: AsyncMock,
|
|
start_addon: AsyncMock,
|
|
set_addon_options_error: Exception | None,
|
|
set_addon_options_calls: int,
|
|
start_addon_error: Exception | None,
|
|
start_addon_calls: int,
|
|
error_message: str,
|
|
) -> None:
|
|
"""Test schedule setup addon raises error."""
|
|
set_addon_options.side_effect = set_addon_options_error
|
|
start_addon.side_effect = start_addon_error
|
|
|
|
with pytest.raises(AddonError) as err:
|
|
await addon_manager.async_schedule_setup_addon({"test_key": "test"})
|
|
|
|
assert str(err.value) == error_message
|
|
|
|
assert set_addon_options.call_count == set_addon_options_calls
|
|
assert start_addon.call_count == start_addon_calls
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
(
|
|
"set_addon_options_error",
|
|
"set_addon_options_calls",
|
|
"start_addon_error",
|
|
"start_addon_calls",
|
|
"error_log",
|
|
),
|
|
[
|
|
(
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
None,
|
|
0,
|
|
"Failed to set the Test add-on options: Boom",
|
|
),
|
|
(
|
|
None,
|
|
1,
|
|
HassioAPIError("Boom"),
|
|
1,
|
|
"Failed to start the Test add-on: Boom",
|
|
),
|
|
],
|
|
)
|
|
async def test_schedule_setup_addon_logs_error(
|
|
addon_manager: AddonManager,
|
|
addon_installed: AsyncMock,
|
|
set_addon_options: AsyncMock,
|
|
start_addon: AsyncMock,
|
|
set_addon_options_error: Exception | None,
|
|
set_addon_options_calls: int,
|
|
start_addon_error: Exception | None,
|
|
start_addon_calls: int,
|
|
error_log: str,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test schedule setup addon logs error."""
|
|
set_addon_options.side_effect = set_addon_options_error
|
|
start_addon.side_effect = start_addon_error
|
|
|
|
await addon_manager.async_schedule_setup_addon(
|
|
{"test_key": "test"}, catch_error=True
|
|
)
|
|
|
|
assert error_log in caplog.text
|
|
assert set_addon_options.call_count == set_addon_options_calls
|
|
assert start_addon.call_count == start_addon_calls
|