From 5e8007453f98f57fa2b1f948711235edfe243b91 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Wed, 5 Jun 2019 16:59:43 +0200 Subject: [PATCH] detect native arch (#1114) --- hassio/arch.py | 30 +++++++++++++++++++--- tests/test_arch.py | 63 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 77 insertions(+), 16 deletions(-) diff --git a/hassio/arch.py b/hassio/arch.py index 7fe7b8d07..eba9af344 100644 --- a/hassio/arch.py +++ b/hassio/arch.py @@ -1,14 +1,24 @@ """Handle Arch for underlay maschine/platforms.""" import logging -from typing import List from pathlib import Path +import platform +from typing import List -from .coresys import CoreSysAttributes, CoreSys +from .coresys import CoreSys, CoreSysAttributes from .exceptions import HassioArchNotFound, JsonFileError from .utils.json import read_json_file _LOGGER = logging.getLogger(__name__) +MAP_CPU = { + "armv7": "armv7", + "armv6": "armhf", + "armv8": "aarch64", + "aarch64": "aarch64", + "i686": "i386", + "x86_64": "amd64", +} + class CpuArch(CoreSysAttributes): """Manage available architectures.""" @@ -42,10 +52,12 @@ class CpuArch(CoreSysAttributes): _LOGGER.warning("Can't read arch json") return + native_support = self.detect_cpu() + # Evaluate current CPU/Platform if not self.sys_machine or self.sys_machine not in arch_data: _LOGGER.warning("Can't detect underlay machine type!") - self._default_arch = self.sys_supervisor.arch + self._default_arch = native_support self._supported_arch.append(self.default) return @@ -53,6 +65,10 @@ class CpuArch(CoreSysAttributes): self._supported_arch.extend(arch_data[self.sys_machine]) self._default_arch = self.supported[0] + # Make sure native support is in supported list + if native_support not in self._supported_arch: + self._supported_arch.append(native_support) + def is_supported(self, arch_list: List[str]) -> bool: """Return True if there is a supported arch by this platform.""" return not set(self.supported).isdisjoint(set(arch_list)) @@ -63,3 +79,11 @@ class CpuArch(CoreSysAttributes): if self_arch in arch_list: return self_arch raise HassioArchNotFound() + + def detect_cpu(self) -> str: + """Return the arch type of local CPU.""" + cpu = platform.machine() + for check, value in MAP_CPU.items(): + if cpu.startswith(check): + return value + return self.sys_supervisor.arch diff --git a/tests/test_arch.py b/tests/test_arch.py index e847e0deb..602ac969d 100644 --- a/tests/test_arch.py +++ b/tests/test_arch.py @@ -1,4 +1,15 @@ """Test arch object.""" +from unittest.mock import patch + +import pytest + + +@pytest.fixture(autouse=True) +def mock_detect_cpu(): + """Mock cpu detection.""" + with patch("platform.machine") as detect_mock: + detect_mock.return_value = "Unknown" + yield detect_mock async def test_machine_not_exits(coresys, sys_machine, sys_supervisor): @@ -32,118 +43,144 @@ async def test_supervisor_arch(coresys, sys_machine, sys_supervisor): assert coresys.arch.supervisor == "amd64" -async def test_raspberrypi_arch(coresys, sys_machine): +async def test_raspberrypi_arch(coresys, sys_machine, sys_supervisor): """Test arch for raspberrypi.""" sys_machine.return_value = "raspberrypi" + sys_supervisor.arch = "armhf" await coresys.arch.load() assert coresys.arch.default == "armhf" assert coresys.arch.supported == ["armhf"] -async def test_raspberrypi2_arch(coresys, sys_machine): +async def test_raspberrypi2_arch(coresys, sys_machine, sys_supervisor): """Test arch for raspberrypi2.""" sys_machine.return_value = "raspberrypi2" + sys_supervisor.arch = "armv7" await coresys.arch.load() assert coresys.arch.default == "armv7" assert coresys.arch.supported == ["armv7", "armhf"] -async def test_raspberrypi3_arch(coresys, sys_machine): +async def test_raspberrypi3_arch(coresys, sys_machine, sys_supervisor): """Test arch for raspberrypi3.""" sys_machine.return_value = "raspberrypi3" + sys_supervisor.arch = "armv7" await coresys.arch.load() assert coresys.arch.default == "armv7" assert coresys.arch.supported == ["armv7", "armhf"] -async def test_raspberrypi3_64_arch(coresys, sys_machine): +async def test_raspberrypi3_64_arch(coresys, sys_machine, sys_supervisor): """Test arch for raspberrypi3_64.""" sys_machine.return_value = "raspberrypi3-64" + sys_supervisor.arch = "aarch64" await coresys.arch.load() assert coresys.arch.default == "aarch64" assert coresys.arch.supported == ["aarch64", "armv7", "armhf"] -async def test_tinker_arch(coresys, sys_machine): +async def test_tinker_arch(coresys, sys_machine, sys_supervisor): """Test arch for tinker.""" sys_machine.return_value = "tinker" + sys_supervisor.arch = "armv7" await coresys.arch.load() assert coresys.arch.default == "armv7" assert coresys.arch.supported == ["armv7", "armhf"] -async def test_odroid_c2_arch(coresys, sys_machine): +async def test_odroid_c2_arch(coresys, sys_machine, sys_supervisor): """Test arch for odroid-c2.""" sys_machine.return_value = "odroid-c2" + sys_supervisor.arch = "aarch64" await coresys.arch.load() assert coresys.arch.default == "aarch64" assert coresys.arch.supported == ["aarch64"] -async def test_odroid_xu_arch(coresys, sys_machine): +async def test_odroid_xu_arch(coresys, sys_machine, sys_supervisor): """Test arch for odroid-xu.""" sys_machine.return_value = "odroid-xu" + sys_supervisor.arch = "armv7" await coresys.arch.load() assert coresys.arch.default == "armv7" assert coresys.arch.supported == ["armv7", "armhf"] -async def test_orangepi_prime_arch(coresys, sys_machine): +async def test_orangepi_prime_arch(coresys, sys_machine, sys_supervisor): """Test arch for orangepi_prime.""" sys_machine.return_value = "orangepi-prime" + sys_supervisor.arch = "aarch64" await coresys.arch.load() assert coresys.arch.default == "aarch64" assert coresys.arch.supported == ["aarch64"] -async def test_intel_nuc_arch(coresys, sys_machine): +async def test_intel_nuc_arch(coresys, sys_machine, sys_supervisor): """Test arch for intel-nuc.""" sys_machine.return_value = "intel-nuc" + sys_supervisor.arch = "amd64" await coresys.arch.load() assert coresys.arch.default == "amd64" assert coresys.arch.supported == ["amd64", "i386"] -async def test_qemux86_arch(coresys, sys_machine): +async def test_qemux86_arch(coresys, sys_machine, sys_supervisor): """Test arch for qemux86.""" sys_machine.return_value = "qemux86" + sys_supervisor.arch = "i386" await coresys.arch.load() assert coresys.arch.default == "i386" assert coresys.arch.supported == ["i386"] -async def test_qemux86_64_arch(coresys, sys_machine): +async def test_qemux86_64_arch(coresys, sys_machine, sys_supervisor): """Test arch for qemux86-64.""" sys_machine.return_value = "qemux86-64" + sys_supervisor.arch = "amd64" await coresys.arch.load() assert coresys.arch.default == "amd64" assert coresys.arch.supported == ["amd64", "i386"] -async def test_qemuarm_arch(coresys, sys_machine): +async def test_qemuarm_arch(coresys, sys_machine, sys_supervisor): """Test arch for qemuarm.""" sys_machine.return_value = "qemuarm" + sys_supervisor.arch = "armhf" await coresys.arch.load() assert coresys.arch.default == "armhf" assert coresys.arch.supported == ["armhf"] -async def test_qemuarm_64_arch(coresys, sys_machine): +async def test_qemuarm_64_arch(coresys, sys_machine, sys_supervisor): """Test arch for qemuarm-64.""" sys_machine.return_value = "qemuarm-64" + sys_supervisor.arch = "aarch64" await coresys.arch.load() assert coresys.arch.default == "aarch64" assert coresys.arch.supported == ["aarch64"] + + +async def test_qemuarm_arch_native_armv7( + coresys, sys_machine, mock_detect_cpu, sys_supervisor +): + """Test arch for qemuarm.""" + sys_machine.return_value = "qemuarm" + sys_supervisor.arch = "armhf" + mock_detect_cpu.return_value = "armv7l" + await coresys.arch.load() + + assert coresys.arch.default == "armhf" + assert coresys.arch.supported == ["armhf", "armv7"]