1
0
mirror of https://github.com/esphome/esphome.git synced 2026-02-08 08:41:59 +00:00

Add test for build_info regeneration behaviour

Test verifies that:
- When source files change, build_info is regenerated with new timestamp
- When no files change, build_info is preserved with same timestamp

The test runs copy_src_tree() three times in the same environment:
1. Initial run creates build_info
2. Second run with no changes preserves the timestamp
3. Third run with changed source file regenerates with new timestamp
This commit is contained in:
David Woodhouse
2025-12-15 16:59:51 +00:00
parent 87a125f303
commit 0a63c50e1e

View File

@@ -1643,3 +1643,125 @@ def test_copy_src_tree_handles_invalid_build_info_json(
assert build_info_h_path.exists()
new_json = json.loads(build_info_json_path.read_text())
assert new_json["config_hash"] == 0xDEADBEEF
@patch("esphome.writer.CORE")
@patch("esphome.writer.iter_components")
@patch("esphome.writer.walk_files")
def test_copy_src_tree_build_info_timestamp_behavior(
mock_walk_files: MagicMock,
mock_iter_components: MagicMock,
mock_core: MagicMock,
tmp_path: Path,
) -> None:
"""Test build_info behaviour: regenerated on change, preserved when unchanged."""
# Setup directory structure
src_path = tmp_path / "src"
src_path.mkdir()
esphome_core_path = src_path / "esphome" / "core"
esphome_core_path.mkdir(parents=True)
esphome_components_path = src_path / "esphome" / "components"
esphome_components_path.mkdir(parents=True)
build_path = tmp_path / "build"
build_path.mkdir()
# Create a source file
source_file = tmp_path / "source" / "test.cpp"
source_file.parent.mkdir()
source_file.write_text("// version 1")
# Create destination file in build tree
dest_file = esphome_components_path / "test.cpp"
# Create mock FileResource
@dataclass(frozen=True)
class MockFileResource:
package: str
resource: str
_path: Path
@contextmanager
def path(self):
yield self._path
mock_resources = [
MockFileResource(
package="esphome.components",
resource="test.cpp",
_path=source_file,
),
]
mock_component = MagicMock()
mock_component.resources = mock_resources
# Setup mocks
mock_core.relative_src_path.side_effect = lambda *args: src_path.joinpath(*args)
mock_core.relative_build_path.side_effect = lambda *args: build_path.joinpath(*args)
mock_core.defines = []
mock_core.config_hash = 0xDEADBEEF
mock_core.target_platform = "test_platform"
mock_core.config = {}
mock_iter_components.return_value = [("test", mock_component)]
build_info_json_path = build_path / "build_info.json"
# First run: initial setup, should create build_info
mock_walk_files.return_value = []
with (
patch("esphome.writer.__version__", "2025.1.0-dev"),
patch("esphome.writer.importlib.import_module") as mock_import,
):
mock_import.side_effect = AttributeError
copy_src_tree()
# Manually set an old timestamp for testing
old_timestamp = 1700000000
old_timestamp_str = "2023-11-14 22:13:20 +0000"
build_info_json_path.write_text(
json.dumps(
{
"config_hash": 0xDEADBEEF,
"build_time": old_timestamp,
"build_time_str": old_timestamp_str,
"esphome_version": "2025.1.0-dev",
}
)
)
# Second run: no changes, should NOT regenerate build_info
mock_walk_files.return_value = [str(dest_file)]
with (
patch("esphome.writer.__version__", "2025.1.0-dev"),
patch("esphome.writer.importlib.import_module") as mock_import,
):
mock_import.side_effect = AttributeError
copy_src_tree()
second_json = json.loads(build_info_json_path.read_text())
second_timestamp = second_json["build_time"]
# Verify timestamp was NOT changed
assert second_timestamp == old_timestamp, (
f"build_info should not be regenerated when no files change: "
f"{old_timestamp} != {second_timestamp}"
)
# Third run: change source file, should regenerate build_info with new timestamp
source_file.write_text("// version 2")
with (
patch("esphome.writer.__version__", "2025.1.0-dev"),
patch("esphome.writer.importlib.import_module") as mock_import,
):
mock_import.side_effect = AttributeError
copy_src_tree()
third_json = json.loads(build_info_json_path.read_text())
third_timestamp = third_json["build_time"]
# Verify timestamp WAS changed
assert third_timestamp != old_timestamp, (
f"build_info should be regenerated when source file changes: "
f"{old_timestamp} == {third_timestamp}"
)
assert third_timestamp > old_timestamp