supervisor/tests/api/test_homeassistant.py

191 lines
6.6 KiB
Python

"""Test homeassistant api."""
from pathlib import Path
from unittest.mock import MagicMock, patch
from aiohttp.test_utils import TestClient
from awesomeversion import AwesomeVersion
import pytest
from supervisor.coresys import CoreSys
from supervisor.homeassistant.api import APIState
from supervisor.homeassistant.core import HomeAssistantCore
from supervisor.homeassistant.module import HomeAssistant
from tests.api import common_test_api_advanced_logs
from tests.common import load_json_fixture
@pytest.mark.parametrize("legacy_route", [True, False])
async def test_api_core_logs(
api_client: TestClient, journald_logs: MagicMock, legacy_route: bool
):
"""Test core logs."""
await common_test_api_advanced_logs(
f"/{'homeassistant' if legacy_route else 'core'}",
"homeassistant",
api_client,
journald_logs,
)
async def test_api_stats(api_client: TestClient, coresys: CoreSys):
"""Test stats."""
coresys.docker.containers.get.return_value.status = "running"
coresys.docker.containers.get.return_value.stats.return_value = load_json_fixture(
"container_stats.json"
)
resp = await api_client.get("/homeassistant/stats")
assert resp.status == 200
result = await resp.json()
assert result["data"]["cpu_percent"] == 90.0
assert result["data"]["memory_usage"] == 59700000
assert result["data"]["memory_limit"] == 4000000000
assert result["data"]["memory_percent"] == 1.49
async def test_api_set_options(api_client: TestClient, coresys: CoreSys):
"""Test setting options for homeassistant."""
resp = await api_client.get("/homeassistant/info")
assert resp.status == 200
result = await resp.json()
assert result["data"]["watchdog"] is True
assert result["data"]["backups_exclude_database"] is False
with patch.object(HomeAssistant, "save_data") as save_data:
resp = await api_client.post(
"/homeassistant/options",
json={"backups_exclude_database": True, "watchdog": False},
)
assert resp.status == 200
save_data.assert_called_once()
resp = await api_client.get("/homeassistant/info")
assert resp.status == 200
result = await resp.json()
assert result["data"]["watchdog"] is False
assert result["data"]["backups_exclude_database"] is True
async def test_api_set_image(api_client: TestClient, coresys: CoreSys):
"""Test changing the image for homeassistant."""
assert (
coresys.homeassistant.image == "ghcr.io/home-assistant/qemux86-64-homeassistant"
)
assert coresys.homeassistant.override_image is False
with patch.object(HomeAssistant, "save_data"):
resp = await api_client.post(
"/homeassistant/options",
json={"image": "test_image"},
)
assert resp.status == 200
assert coresys.homeassistant.image == "test_image"
assert coresys.homeassistant.override_image is True
with patch.object(HomeAssistant, "save_data"):
resp = await api_client.post(
"/homeassistant/options",
json={"image": "ghcr.io/home-assistant/qemux86-64-homeassistant"},
)
assert resp.status == 200
assert (
coresys.homeassistant.image == "ghcr.io/home-assistant/qemux86-64-homeassistant"
)
assert coresys.homeassistant.override_image is False
async def test_api_restart(
api_client: TestClient,
container: MagicMock,
tmp_supervisor_data: Path,
):
"""Test restarting homeassistant."""
safe_mode_marker = tmp_supervisor_data / "homeassistant" / "safe-mode"
with patch.object(HomeAssistantCore, "_block_till_run"):
await api_client.post("/homeassistant/restart")
container.restart.assert_called_once()
assert not safe_mode_marker.exists()
with patch.object(HomeAssistantCore, "_block_till_run"):
await api_client.post("/homeassistant/restart", json={"safe_mode": True})
assert container.restart.call_count == 2
assert safe_mode_marker.exists()
async def test_api_rebuild(
api_client: TestClient,
coresys: CoreSys,
container: MagicMock,
tmp_supervisor_data: Path,
path_extern,
):
"""Test rebuilding homeassistant."""
coresys.homeassistant.version = AwesomeVersion("2023.09.0")
safe_mode_marker = tmp_supervisor_data / "homeassistant" / "safe-mode"
with patch.object(HomeAssistantCore, "_block_till_run"):
await api_client.post("/homeassistant/rebuild")
assert container.remove.call_count == 2
container.start.assert_called_once()
assert not safe_mode_marker.exists()
with patch.object(HomeAssistantCore, "_block_till_run"):
await api_client.post("/homeassistant/rebuild", json={"safe_mode": True})
assert container.remove.call_count == 4
assert container.start.call_count == 2
assert safe_mode_marker.exists()
@pytest.mark.parametrize("action", ["rebuild", "restart", "stop", "update"])
async def test_migration_blocks_stopping_core(
api_client: TestClient,
coresys: CoreSys,
action: str,
):
"""Test that an offline db migration in progress stops users from stopping/restarting core."""
coresys.homeassistant.api.get_api_state.return_value = APIState("NOT_RUNNING", True)
resp = await api_client.post(f"/homeassistant/{action}")
assert resp.status == 503
result = await resp.json()
assert (
result["message"]
== "Offline database migration in progress, try again after it has completed"
)
async def test_force_rebuild_during_migration(api_client: TestClient, coresys: CoreSys):
"""Test force option rebuilds even during a migration."""
coresys.homeassistant.api.get_api_state.return_value = APIState("NOT_RUNNING", True)
with patch.object(HomeAssistantCore, "rebuild") as rebuild:
await api_client.post("/homeassistant/rebuild", json={"force": True})
rebuild.assert_called_once()
async def test_force_restart_during_migration(api_client: TestClient, coresys: CoreSys):
"""Test force option restarts even during a migration."""
coresys.homeassistant.api.get_api_state.return_value = APIState("NOT_RUNNING", True)
with patch.object(HomeAssistantCore, "restart") as restart:
await api_client.post("/homeassistant/restart", json={"force": True})
restart.assert_called_once()
async def test_force_stop_during_migration(api_client: TestClient, coresys: CoreSys):
"""Test force option stops even during a migration."""
coresys.homeassistant.api.get_api_state.return_value = APIState("NOT_RUNNING", True)
with patch.object(HomeAssistantCore, "stop") as stop:
await api_client.post("/homeassistant/stop", json={"force": True})
stop.assert_called_once()