Small speed up to arch is_supported (#4674)

* Small speed up to arch is_supported

* update tests

* mocking

* mocking
This commit is contained in:
J. Nick Koston 2023-11-11 04:58:16 -06:00 committed by GitHub
parent d7d34d36c8
commit 68d86b3b7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 19 deletions

View File

@ -28,6 +28,7 @@ class CpuArch(CoreSysAttributes):
"""Initialize CPU Architecture handler.""" """Initialize CPU Architecture handler."""
self.coresys = coresys self.coresys = coresys
self._supported_arch: list[str] = [] self._supported_arch: list[str] = []
self._supported_set: set[str] = set()
self._default_arch: str self._default_arch: str
@property @property
@ -70,9 +71,11 @@ class CpuArch(CoreSysAttributes):
if native_support not in self._supported_arch: if native_support not in self._supported_arch:
self._supported_arch.append(native_support) self._supported_arch.append(native_support)
self._supported_set = set(self._supported_arch)
def is_supported(self, arch_list: list[str]) -> bool: def is_supported(self, arch_list: list[str]) -> bool:
"""Return True if there is a supported arch by this platform.""" """Return True if there is a supported arch by this platform."""
return not set(self.supported).isdisjoint(set(arch_list)) return not self._supported_set.isdisjoint(arch_list)
def match(self, arch_list: list[str]) -> str: def match(self, arch_list: list[str]) -> str:
"""Return best match for this CPU/Platform.""" """Return best match for this CPU/Platform."""

View File

@ -12,7 +12,6 @@ from securetar import SecureTarFile
from supervisor.addons.addon import Addon from supervisor.addons.addon import Addon
from supervisor.addons.const import AddonBackupMode from supervisor.addons.const import AddonBackupMode
from supervisor.addons.model import AddonModel from supervisor.addons.model import AddonModel
from supervisor.arch import CpuArch
from supervisor.const import AddonState, BusEvent from supervisor.const import AddonState, BusEvent
from supervisor.coresys import CoreSys from supervisor.coresys import CoreSys
from supervisor.docker.addon import DockerAddon from supervisor.docker.addon import DockerAddon
@ -197,19 +196,17 @@ async def test_watchdog_on_stop(coresys: CoreSys, install_addon_ssh: Addon) -> N
restart.assert_called_once() restart.assert_called_once()
async def test_listener_attached_on_install(coresys: CoreSys, repository): async def test_listener_attached_on_install(
coresys: CoreSys, mock_amd64_arch_supported: None, repository
):
"""Test events listener attached on addon install.""" """Test events listener attached on addon install."""
coresys.hardware.disk.get_disk_free_space = lambda x: 5000 coresys.hardware.disk.get_disk_free_space = lambda x: 5000
container_collection = MagicMock() container_collection = MagicMock()
container_collection.get.side_effect = DockerException() container_collection.get.side_effect = DockerException()
with patch( with patch(
"supervisor.arch.CpuArch.supported", new=PropertyMock(return_value=["amd64"])
), patch(
"supervisor.docker.manager.DockerAPI.containers", "supervisor.docker.manager.DockerAPI.containers",
new=PropertyMock(return_value=container_collection), new=PropertyMock(return_value=container_collection),
), patch( ), patch("pathlib.Path.is_dir", return_value=True), patch(
"pathlib.Path.is_dir", return_value=True
), patch(
"supervisor.addons.addon.Addon.need_build", new=PropertyMock(return_value=False) "supervisor.addons.addon.Addon.need_build", new=PropertyMock(return_value=False)
), patch( ), patch(
"supervisor.addons.model.AddonModel.with_ingress", "supervisor.addons.model.AddonModel.with_ingress",
@ -556,6 +553,7 @@ async def test_restore(
status: str, status: str,
tmp_supervisor_data, tmp_supervisor_data,
path_extern, path_extern,
mock_aarch64_arch_supported: None,
) -> None: ) -> None:
"""Test restoring an addon.""" """Test restoring an addon."""
coresys.hardware.disk.get_disk_free_space = lambda x: 5000 coresys.hardware.disk.get_disk_free_space = lambda x: 5000
@ -563,9 +561,7 @@ async def test_restore(
await install_addon_ssh.load() await install_addon_ssh.load()
tarfile = SecureTarFile(get_fixture_path(f"backup_local_ssh_{status}.tar.gz"), "r") tarfile = SecureTarFile(get_fixture_path(f"backup_local_ssh_{status}.tar.gz"), "r")
with patch.object(DockerAddon, "is_running", return_value=False), patch.object( with patch.object(DockerAddon, "is_running", return_value=False):
CpuArch, "supported", new=PropertyMock(return_value=["aarch64"])
):
start_task = await coresys.addons.restore(TEST_ADDON_SLUG, tarfile) start_task = await coresys.addons.restore(TEST_ADDON_SLUG, tarfile)
assert bool(start_task) is (status == "running") assert bool(start_task) is (status == "running")
@ -577,6 +573,7 @@ async def test_restore_while_running(
container: MagicMock, container: MagicMock,
tmp_supervisor_data, tmp_supervisor_data,
path_extern, path_extern,
mock_aarch64_arch_supported: None,
): ):
"""Test restore of a running addon.""" """Test restore of a running addon."""
container.status = "running" container.status = "running"
@ -586,8 +583,8 @@ async def test_restore_while_running(
tarfile = SecureTarFile(get_fixture_path("backup_local_ssh_stopped.tar.gz"), "r") tarfile = SecureTarFile(get_fixture_path("backup_local_ssh_stopped.tar.gz"), "r")
with patch.object(DockerAddon, "is_running", return_value=True), patch.object( with patch.object(DockerAddon, "is_running", return_value=True), patch.object(
CpuArch, "supported", new=PropertyMock(return_value=["aarch64"]) Ingress, "update_hass_panel"
), patch.object(Ingress, "update_hass_panel"): ):
start_task = await coresys.addons.restore(TEST_ADDON_SLUG, tarfile) start_task = await coresys.addons.restore(TEST_ADDON_SLUG, tarfile)
assert bool(start_task) is False assert bool(start_task) is False
@ -600,6 +597,7 @@ async def test_restore_while_running_with_watchdog(
container: MagicMock, container: MagicMock,
tmp_supervisor_data, tmp_supervisor_data,
path_extern, path_extern,
mock_aarch64_arch_supported: None,
): ):
"""Test restore of a running addon with watchdog interference.""" """Test restore of a running addon with watchdog interference."""
container.status = "running" container.status = "running"
@ -619,8 +617,6 @@ async def test_restore_while_running_with_watchdog(
with patch.object(Addon, "start") as start, patch.object( with patch.object(Addon, "start") as start, patch.object(
Addon, "restart" Addon, "restart"
) as restart, patch.object(DockerAddon, "stop", new=mock_stop), patch.object( ) as restart, patch.object(DockerAddon, "stop", new=mock_stop), patch.object(
CpuArch, "supported", new=PropertyMock(return_value=["aarch64"])
), patch.object(
Ingress, "update_hass_panel" Ingress, "update_hass_panel"
): ):
await coresys.addons.restore(TEST_ADDON_SLUG, tarfile) await coresys.addons.restore(TEST_ADDON_SLUG, tarfile)
@ -650,16 +646,18 @@ async def test_start_when_running(
async def test_local_example_install( async def test_local_example_install(
coresys: CoreSys, container: MagicMock, tmp_supervisor_data: Path, repository coresys: CoreSys,
container: MagicMock,
tmp_supervisor_data: Path,
repository,
mock_aarch64_arch_supported: None,
): ):
"""Test install of an addon.""" """Test install of an addon."""
assert not ( assert not (
data_dir := tmp_supervisor_data / "addons" / "data" / "local_example" data_dir := tmp_supervisor_data / "addons" / "data" / "local_example"
).exists() ).exists()
with patch.object( with patch.object(DockerAddon, "install") as install:
CpuArch, "supported", new=PropertyMock(return_value=["aarch64"])
), patch.object(DockerAddon, "install") as install:
await coresys.addons.install("local_example") await coresys.addons.install("local_example")
install.assert_called_once() install.assert_called_once()

View File

@ -320,6 +320,7 @@ async def coresys(
# Mock test client # Mock test client
coresys_obj.arch._default_arch = "amd64" coresys_obj.arch._default_arch = "amd64"
coresys_obj.arch._supported_set = {"amd64"}
coresys_obj._machine = "qemux86-64" coresys_obj._machine = "qemux86-64"
coresys_obj._machine_id = uuid4() coresys_obj._machine_id = uuid4()
@ -695,3 +696,17 @@ async def container(docker: DockerAPI) -> MagicMock:
addon.status = "stopped" addon.status = "stopped"
addon.attrs = {"State": {"ExitCode": 0}} addon.attrs = {"State": {"ExitCode": 0}}
yield addon yield addon
@pytest.fixture
def mock_amd64_arch_supported(coresys: CoreSys) -> None:
"""Mock amd64 arch as supported."""
with patch.object(coresys.arch, "_supported_set", {"amd64"}):
yield
@pytest.fixture
def mock_aarch64_arch_supported(coresys: CoreSys) -> None:
"""Mock aarch64 arch as supported."""
with patch.object(coresys.arch, "_supported_set", {"aarch64"}):
yield

View File

@ -111,6 +111,10 @@ async def test_yellow_arch(coresys, sys_machine, sys_supervisor):
assert coresys.arch.default == "aarch64" assert coresys.arch.default == "aarch64"
assert coresys.arch.supported == ["aarch64", "armv7", "armhf"] assert coresys.arch.supported == ["aarch64", "armv7", "armhf"]
assert coresys.arch.is_supported(["aarch64"]) is True
assert coresys.arch.is_supported(["armv7"]) is True
assert coresys.arch.is_supported(["armhf"]) is True
assert coresys.arch.is_supported(["x86_64", "i386"]) is False
async def test_green_arch(coresys, sys_machine, sys_supervisor): async def test_green_arch(coresys, sys_machine, sys_supervisor):