mirror of
https://github.com/esphome/esphome.git
synced 2026-10-02 14:22:58 +08:00
CI / Create common environment (push) Canceled after 0s
CI / Seed apt package cache (push) Canceled after 0s
CI / Determine which jobs to run (push) Canceled after 0s
CI / Run script/ci-custom (push) Canceled after 0s
CI / Check pylint (push) Canceled after 0s
CI / Check lint and formatting (push) Canceled after 0s
CI / Run pytest (macOS-latest, 3.12) (push) Canceled after 0s
CI / Run pytest (macOS-latest, 3.14) (push) Canceled after 0s
CI / Run pytest (ubuntu-latest, 3.12) (push) Canceled after 0s
CI / Run pytest (ubuntu-latest, 3.13) (push) Canceled after 0s
CI / Run pytest (ubuntu-latest, 3.14) (push) Canceled after 0s
CI / Run pytest (windows-latest, 3.12) (push) Canceled after 0s
CI / Run pytest (windows-latest, 3.14) (push) Canceled after 0s
CI / Report no coverage to Codecov (push) Canceled after 0s
CI / Run integration tests () (push) Canceled after 0s
CI / Check import esphome.__main__ time (push) Canceled after 0s
CI / Run CodSpeed benchmarks (push) Canceled after 0s
CI / Run C++ unit tests (push) Canceled after 0s
CI / Run script/clang-tidy for LibreTiny (push) Canceled after 0s
CI / Run script/clang-tidy for ESP8266 (push) Canceled after 0s
CI / Run script/clang-tidy for RP2 (push) Canceled after 0s
CI / Run script/clang-tidy for ESP32 Arduino (push) Canceled after 0s
CI / Run script/clang-tidy for ZEPHYR (push) Canceled after 0s
CI / Run script/clang-tidy for ESP32 IDF (push) Canceled after 0s
CI / Run script/clang-tidy for ESP32 IDF 1/3 (push) Canceled after 0s
CI / Run script/clang-tidy for ESP32 IDF 2/3 (push) Canceled after 0s
CI / Run script/clang-tidy for ESP32 IDF 3/3 (push) Canceled after 0s
CI / Run script/clang-tidy for ESP32 C6 (push) Canceled after 0s
CI / Run script/clang-tidy for ESP32 P4 (push) Canceled after 0s
CI / Run script/clang-tidy for ESP32 S3 (push) Canceled after 0s
CI / Test components batch () (push) Canceled after 0s
CI / Test esp32 components with PlatformIO (push) Canceled after 0s
CI / Test downstream esphome/device-builder (push) Canceled after 0s
CI / Build target branch for memory impact (push) Canceled after 0s
CI / Build PR branch for memory impact (push) Canceled after 0s
CI / Comment memory impact (push) Canceled after 0s
CI / CI Status (push) Canceled after 0s
175 lines
6.2 KiB
Python
175 lines
6.2 KiB
Python
"""Unit tests for esphome.config_helpers module."""
|
|
|
|
from collections.abc import Callable
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from esphome.config_helpers import (
|
|
filter_source_files_from_defines,
|
|
filter_source_files_from_platform,
|
|
frameworks_for_platforms,
|
|
get_logger_level,
|
|
)
|
|
from esphome.const import (
|
|
CONF_LEVEL,
|
|
CONF_LOGGER,
|
|
KEY_CORE,
|
|
KEY_TARGET_FRAMEWORK,
|
|
KEY_TARGET_PLATFORM,
|
|
PlatformFramework,
|
|
)
|
|
from esphome.core import Define
|
|
|
|
|
|
def test_filter_source_files_from_platform_esp32() -> None:
|
|
"""Test that filter_source_files_from_platform correctly filters files for ESP32 platform."""
|
|
# Define test file mappings
|
|
files_map: dict[str, set[PlatformFramework]] = {
|
|
"logger_esp32.cpp": {
|
|
PlatformFramework.ESP32_ARDUINO,
|
|
PlatformFramework.ESP32_IDF,
|
|
},
|
|
"logger_esp8266.cpp": {PlatformFramework.ESP8266_ARDUINO},
|
|
"logger_host.cpp": {PlatformFramework.HOST_NATIVE},
|
|
"logger_common.cpp": {
|
|
PlatformFramework.ESP32_ARDUINO,
|
|
PlatformFramework.ESP32_IDF,
|
|
PlatformFramework.ESP8266_ARDUINO,
|
|
PlatformFramework.HOST_NATIVE,
|
|
},
|
|
}
|
|
|
|
# Create the filter function
|
|
filter_func: Callable[[], list[str]] = filter_source_files_from_platform(files_map)
|
|
|
|
# Test ESP32 with Arduino framework
|
|
mock_core_data: dict[str, dict[str, str]] = {
|
|
KEY_CORE: {
|
|
KEY_TARGET_PLATFORM: "esp32",
|
|
KEY_TARGET_FRAMEWORK: "arduino",
|
|
}
|
|
}
|
|
|
|
with patch("esphome.config_helpers.CORE.data", mock_core_data):
|
|
excluded: list[str] = filter_func()
|
|
# ESP32 Arduino should exclude ESP8266 and HOST files
|
|
assert "logger_esp8266.cpp" in excluded
|
|
assert "logger_host.cpp" in excluded
|
|
# But not ESP32 or common files
|
|
assert "logger_esp32.cpp" not in excluded
|
|
assert "logger_common.cpp" not in excluded
|
|
|
|
|
|
def test_filter_source_files_from_platform_host() -> None:
|
|
"""Test that filter_source_files_from_platform correctly filters files for HOST platform."""
|
|
# Define test file mappings
|
|
files_map: dict[str, set[PlatformFramework]] = {
|
|
"logger_esp32.cpp": {
|
|
PlatformFramework.ESP32_ARDUINO,
|
|
PlatformFramework.ESP32_IDF,
|
|
},
|
|
"logger_esp8266.cpp": {PlatformFramework.ESP8266_ARDUINO},
|
|
"logger_host.cpp": {PlatformFramework.HOST_NATIVE},
|
|
"logger_common.cpp": {
|
|
PlatformFramework.ESP32_ARDUINO,
|
|
PlatformFramework.ESP32_IDF,
|
|
PlatformFramework.ESP8266_ARDUINO,
|
|
PlatformFramework.HOST_NATIVE,
|
|
},
|
|
}
|
|
|
|
# Create the filter function
|
|
filter_func: Callable[[], list[str]] = filter_source_files_from_platform(files_map)
|
|
|
|
# Test Host platform
|
|
mock_core_data: dict[str, dict[str, str]] = {
|
|
KEY_CORE: {
|
|
KEY_TARGET_PLATFORM: "host",
|
|
KEY_TARGET_FRAMEWORK: "host", # Framework.NATIVE is "host"
|
|
}
|
|
}
|
|
|
|
with patch("esphome.config_helpers.CORE.data", mock_core_data):
|
|
excluded: list[str] = filter_func()
|
|
# Host should exclude ESP32 and ESP8266 files
|
|
assert "logger_esp32.cpp" in excluded
|
|
assert "logger_esp8266.cpp" in excluded
|
|
# But not host or common files
|
|
assert "logger_host.cpp" not in excluded
|
|
assert "logger_common.cpp" not in excluded
|
|
|
|
|
|
def test_filter_source_files_from_platform_handles_missing_data() -> None:
|
|
"""Test that filter_source_files_from_platform returns empty list when platform/framework data is missing."""
|
|
# Define test file mappings
|
|
files_map: dict[str, set[PlatformFramework]] = {
|
|
"logger_esp32.cpp": {PlatformFramework.ESP32_ARDUINO},
|
|
"logger_host.cpp": {PlatformFramework.HOST_NATIVE},
|
|
}
|
|
|
|
# Create the filter function
|
|
filter_func: Callable[[], list[str]] = filter_source_files_from_platform(files_map)
|
|
|
|
# Test case: Missing platform/framework data
|
|
mock_core_data: dict[str, dict[str, str]] = {KEY_CORE: {}}
|
|
|
|
with patch("esphome.config_helpers.CORE.data", mock_core_data):
|
|
excluded: list[str] = filter_func()
|
|
# Should return empty list when platform/framework not set
|
|
assert excluded == []
|
|
|
|
|
|
def test_get_logger_level() -> None:
|
|
"""Test get_logger_level helper function."""
|
|
# Test no logger config - should return default DEBUG
|
|
mock_config = {}
|
|
with patch("esphome.config_helpers.CORE.config", mock_config):
|
|
assert get_logger_level() == "DEBUG"
|
|
|
|
# Test with logger set to INFO
|
|
mock_config = {CONF_LOGGER: {CONF_LEVEL: "INFO"}}
|
|
with patch("esphome.config_helpers.CORE.config", mock_config):
|
|
assert get_logger_level() == "INFO"
|
|
|
|
# Test with VERY_VERBOSE
|
|
mock_config = {CONF_LOGGER: {CONF_LEVEL: "VERY_VERBOSE"}}
|
|
with patch("esphome.config_helpers.CORE.config", mock_config):
|
|
assert get_logger_level() == "VERY_VERBOSE"
|
|
|
|
# Test with logger missing level (uses default DEBUG)
|
|
mock_config = {CONF_LOGGER: {}}
|
|
with patch("esphome.config_helpers.CORE.config", mock_config):
|
|
assert get_logger_level() == "DEBUG"
|
|
|
|
|
|
def test_frameworks_for_platforms_derives_and_rejects_unknown() -> None:
|
|
assert frameworks_for_platforms(["esp32"]) == {
|
|
PlatformFramework.ESP32_ARDUINO,
|
|
PlatformFramework.ESP32_IDF,
|
|
}
|
|
with pytest.raises(ValueError, match="unknown platform"):
|
|
frameworks_for_platforms(["esp32", "not_a_platform"])
|
|
|
|
|
|
def test_filter_source_files_from_defines() -> None:
|
|
"""Files are excluded unless one of their defines is set."""
|
|
files_map: dict[str, str | tuple[str, ...]] = {
|
|
"filter.cpp": "USE_SENSOR_FILTER",
|
|
"automation.cpp": ("USE_CLICK", "USE_MULTI_CLICK"),
|
|
}
|
|
filter_func: Callable[[], list[str]] = filter_source_files_from_defines(files_map)
|
|
|
|
with patch("esphome.config_helpers.CORE") as mock_core:
|
|
mock_core.defines = {Define("USE_SENSOR_FILTER")}
|
|
assert filter_func() == ["automation.cpp"]
|
|
|
|
mock_core.defines = {Define("USE_MULTI_CLICK")}
|
|
assert filter_func() == ["filter.cpp"]
|
|
|
|
mock_core.defines = {Define("USE_SENSOR_FILTER"), Define("USE_CLICK")}
|
|
assert filter_func() == []
|
|
|
|
mock_core.defines = set()
|
|
assert sorted(filter_func()) == ["automation.cpp", "filter.cpp"]
|