diff --git a/esphome/config_helpers.py b/esphome/config_helpers.py index 3c866f6d31..73ad4caff0 100644 --- a/esphome/config_helpers.py +++ b/esphome/config_helpers.py @@ -10,7 +10,9 @@ from esphome.const import ( from esphome.core import CORE # Pre-build lookup map from (platform, framework) tuples to PlatformFramework enum -_PLATFORM_FRAMEWORK_LOOKUP = {pf.value: pf for pf in PlatformFramework} +_PLATFORM_FRAMEWORK_LOOKUP = { + (pf.value[0].value, pf.value[1].value): pf for pf in PlatformFramework +} class Extend: diff --git a/tests/unit_tests/test_config_helpers.py b/tests/unit_tests/test_config_helpers.py new file mode 100644 index 0000000000..8b51a8adcd --- /dev/null +++ b/tests/unit_tests/test_config_helpers.py @@ -0,0 +1,75 @@ +"""Unit tests for esphome.config_helpers module.""" + +from unittest.mock import patch + +from esphome.config_helpers import filter_source_files_from_platform +from esphome.const import ( + KEY_CORE, + KEY_TARGET_FRAMEWORK, + KEY_TARGET_PLATFORM, + PlatformFramework, +) + + +def test_filter_source_files_from_platform(): + """Test that filter_source_files_from_platform correctly filters files based on platform.""" + # Define test file mappings + files_map = { + "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 = filter_source_files_from_platform(files_map) + + # Test case 1: ESP32 with Arduino framework + mock_core_data = { + KEY_CORE: { + KEY_TARGET_PLATFORM: "esp32", + KEY_TARGET_FRAMEWORK: "arduino", + } + } + + with patch("esphome.config_helpers.CORE.data", mock_core_data): + excluded = 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 + + # Test case 2: Host platform + mock_core_data = { + 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 = 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 + + # Test case 3: Missing platform/framework data + mock_core_data = {KEY_CORE: {}} + + with patch("esphome.config_helpers.CORE.data", mock_core_data): + excluded = filter_func() + # Should return empty list when platform/framework not set + assert excluded == [] diff --git a/tests/unit_tests/test_loader.py b/tests/unit_tests/test_loader.py new file mode 100644 index 0000000000..24c8464aa4 --- /dev/null +++ b/tests/unit_tests/test_loader.py @@ -0,0 +1,63 @@ +"""Unit tests for esphome.loader module.""" + +from unittest.mock import MagicMock, patch + +from esphome.loader import ComponentManifest + + +def test_component_manifest_resources_with_filter_source_files(): + """Test that ComponentManifest.resources correctly filters out excluded files.""" + # Create a mock module with FILTER_SOURCE_FILES function + mock_module = MagicMock() + mock_module.FILTER_SOURCE_FILES = lambda: [ + "platform_esp32.cpp", + "platform_esp8266.cpp", + ] + mock_module.__package__ = "esphome.components.test_component" + + # Create ComponentManifest instance + manifest = ComponentManifest(mock_module) + + # Mock the files in the package + def create_mock_file(filename): + mock_file = MagicMock() + mock_file.name = filename + mock_file.is_file.return_value = True + return mock_file + + mock_files = [ + create_mock_file("test.cpp"), + create_mock_file("test.h"), + create_mock_file("platform_esp32.cpp"), + create_mock_file("platform_esp8266.cpp"), + create_mock_file("common.cpp"), + create_mock_file("README.md"), # Should be excluded by extension + ] + + # Mock importlib.resources + with patch("importlib.resources.files") as mock_files_func: + mock_package_files = MagicMock() + mock_package_files.iterdir.return_value = mock_files + mock_package_files.joinpath = lambda name: MagicMock(is_file=lambda: True) + mock_files_func.return_value = mock_package_files + + # Get resources + resources = manifest.resources + + # Convert to list of filenames for easier testing + resource_names = [r.resource for r in resources] + + # Check that platform files are excluded + assert "platform_esp32.cpp" not in resource_names + assert "platform_esp8266.cpp" not in resource_names + + # Check that other source files are included + assert "test.cpp" in resource_names + assert "test.h" in resource_names + assert "common.cpp" in resource_names + + # Check that non-source files are excluded + assert "README.md" not in resource_names + + # Verify the correct number of resources + assert len(resources) == 3 # test.cpp, test.h, common.cpp