[i2c] Let host unit tests with I2C build on macOS (#20738)

This commit is contained in:
Panoplian
2026-10-15 07:47:52 -10:00
committed by GitHub
parent 1947c3d355
commit bf67b49104
2 changed files with 70 additions and 2 deletions
+19 -2
View File
@@ -144,10 +144,15 @@ def validate_config(config: ConfigType) -> ConfigType:
return config
def _host_is_linux() -> bool:
"""The host I2C bus needs Linux i2c-dev."""
return sys.platform.lower().startswith("linux")
def validate_host_config(config: ConfigType) -> ConfigType:
if CORE.is_host:
# Host I2C is currently only supported on Linux
if not sys.platform.lower().startswith("linux"):
if not _host_is_linux():
raise cv.Invalid(
"I2C is only supported on Linux for the host platform. "
f"Current platform: {sys.platform}"
@@ -446,7 +451,7 @@ def final_validate_device_schema(
)
FILTER_SOURCE_FILES = filter_source_files_from_platform(
_platform_filter = filter_source_files_from_platform(
{
"i2c_bus_arduino.cpp": {
PlatformFramework.ESP8266_ARDUINO,
@@ -463,3 +468,15 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform(
"i2c_bus_host.cpp": {PlatformFramework.HOST_NATIVE},
}
)
def FILTER_SOURCE_FILES() -> list[str]:
excluded = _platform_filter()
# An empty list means the target isn't known yet. Otherwise the host bus is
# only kept for the host platform, and it needs Linux i2c-dev
# (validate_host_config rejects host I2C elsewhere). Leaving it out lets host
# builds without a bus, like the C++ unit tests with their fake bus, build on
# macOS too.
if excluded and "i2c_bus_host.cpp" not in excluded and not _host_is_linux():
excluded.append("i2c_bus_host.cpp")
return excluded
+51
View File
@@ -0,0 +1,51 @@
"""I2C backend source selection."""
from unittest.mock import patch
import pytest
from esphome.components import i2c
from esphome.const import KEY_CORE, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM
@pytest.mark.parametrize(
"build_os, host_bus_built",
[
("linux", True),
("darwin", False),
],
)
def test_host_bus_is_only_built_on_linux(build_os: str, host_bus_built: bool) -> None:
core_data = {KEY_CORE: {KEY_TARGET_PLATFORM: "host", KEY_TARGET_FRAMEWORK: "host"}}
with (
patch("esphome.config_helpers.CORE.data", core_data),
patch.object(i2c.sys, "platform", build_os),
):
excluded = i2c.FILTER_SOURCE_FILES()
assert ("i2c_bus_host.cpp" not in excluded) is host_bus_built
assert {"i2c_bus_arduino.cpp", "i2c_bus_esp_idf.cpp", "i2c_bus_zephyr.cpp"} <= set(
excluded
)
@pytest.mark.parametrize("build_os", ["linux", "darwin"])
def test_nothing_excluded_before_the_target_is_known(build_os: str) -> None:
with (
patch("esphome.config_helpers.CORE.data", {}),
patch.object(i2c.sys, "platform", build_os),
):
assert i2c.FILTER_SOURCE_FILES() == []
@pytest.mark.parametrize("build_os", ["linux", "darwin"])
def test_host_bus_left_out_for_other_targets(build_os: str) -> None:
core_data = {
KEY_CORE: {KEY_TARGET_PLATFORM: "esp32", KEY_TARGET_FRAMEWORK: "esp-idf"}
}
with (
patch("esphome.config_helpers.CORE.data", core_data),
patch.object(i2c.sys, "platform", build_os),
):
excluded = i2c.FILTER_SOURCE_FILES()
assert excluded.count("i2c_bus_host.cpp") == 1
assert "i2c_bus_esp_idf.cpp" not in excluded