mirror of
https://github.com/esphome/esphome.git
synced 2026-10-01 00:40:21 +00:00
Merge branch 'esp8266-native-build-spec' into esp8266-native-ninja-emission
This commit is contained in:
@@ -716,6 +716,30 @@ def test_bundled_dependency_dict_shorthand_prefers_bundled(tmp_path: Path) -> No
|
||||
assert "Wire" in [lib.name for lib in libs]
|
||||
|
||||
|
||||
def test_unfulfilled_provides_promise_warns(
|
||||
tmp_path: Path, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""The walk records every provides()-skipped dependency; one nothing
|
||||
added must warn instead of surfacing as link errors, while satisfied
|
||||
ones stay silent."""
|
||||
component._warn_unfulfilled_provides(["Wire", "Hash"], {"Hash"})
|
||||
assert "provides() skipped dependency Wire but nothing added it" in caplog.text
|
||||
assert "Hash" not in caplog.text
|
||||
|
||||
|
||||
def test_fulfilled_provides_promise_is_silent_end_to_end(
|
||||
tmp_path: Path, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""The normal path: the walk records the skip and the backend adds the
|
||||
bundled copy, so the reconciliation stays quiet."""
|
||||
framework = _make_framework(tmp_path)
|
||||
converted = _webserver(tmp_path, {"build": {}, "dependencies": {"Wire": "*"}})
|
||||
with _emitting_converter(converted):
|
||||
libs = _resolve(framework)
|
||||
assert "Wire" in [lib.name for lib in libs]
|
||||
assert "provides() skipped dependency" not in caplog.text
|
||||
|
||||
|
||||
def test_bundled_dependency_platform_rejection_is_debug(
|
||||
tmp_path: Path, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
|
||||
@@ -940,6 +940,26 @@ def test_prefetch_all_entries_unverifiable_is_a_noop(tmp_path: Path) -> None:
|
||||
download.assert_not_called()
|
||||
|
||||
|
||||
def test_prefetch_dedupes_entries_by_dest(tmp_path: Path) -> None:
|
||||
"""Two entries resolving to one dest would interleave writes into the
|
||||
same .part file; only the first downloads."""
|
||||
entries = json.loads(_PREFETCH_JSON)
|
||||
dup = dict(entries[0]) | {"name": "cmake-alias@3.30.2"}
|
||||
entries.append(dup)
|
||||
with (
|
||||
patch(
|
||||
"esphome.espidf.framework.run_command",
|
||||
return_value=(True, json.dumps(entries), ""),
|
||||
),
|
||||
patch("esphome.espidf.framework.download_with_resume") as download,
|
||||
patch("esphome.espidf.framework.get_system_python_path", return_value="python"),
|
||||
patch("esphome.espidf.framework.BatchDownloadProgress"),
|
||||
):
|
||||
_prefetch_idf_tool_archives(tmp_path, "esp32", ["required"], None)
|
||||
dests = [call[0][1].name for call in download.call_args_list]
|
||||
assert dests.count("cmake-3.30.2.tar.gz") == 1
|
||||
|
||||
|
||||
def test_prefetch_downloads_each_archive_with_resume(tmp_path: Path) -> None:
|
||||
with (
|
||||
patch(
|
||||
|
||||
@@ -169,6 +169,30 @@ def test_apply_extra_script_callable_target_and_str_flags(tmp_path) -> None:
|
||||
assert c.data["build"]["flags"] == ["-DBASE=1", "-lesp8266"]
|
||||
|
||||
|
||||
def test_captured_nonstring_buckets_warn_and_skip(tmp_path, caplog) -> None:
|
||||
"""Non-string LIBS/LINKFLAGS/CPPFLAGS/LIBPATH entries (legal SCons
|
||||
nodes) are skipped by name instead of stringified into garbage flags."""
|
||||
(tmp_path / "src").mkdir()
|
||||
script = tmp_path / "extra.py"
|
||||
script.write_text(
|
||||
"env.Append(LIBS=['m', 42], LINKFLAGS=['-Wl,-x', {'no': 1}], "
|
||||
"CPPFLAGS=['-Os', 3.5], LIBPATH=['libs', 7])\n"
|
||||
)
|
||||
(tmp_path / "libs").mkdir()
|
||||
|
||||
c = IDFComponent("owner/name", "1.0", source=URLSource("http://dummy"))
|
||||
c.path = tmp_path
|
||||
c.data = {"build": {"extraScript": "extra.py"}}
|
||||
|
||||
apply_extra_script(c, board_mcu=lambda: "esp8266", pio_platform="espressif8266")
|
||||
|
||||
flags = c.data["build"]["flags"]
|
||||
assert "-lm" in flags and "-Wl,-x" in flags and "-Os" in flags
|
||||
assert not any("42" in f or "no" in f or "3.5" in f for f in flags)
|
||||
assert "Ignoring unsupported LIBS entry 42" in caplog.text
|
||||
assert "Ignoring unsupported LIBPATH entry 7" in caplog.text
|
||||
|
||||
|
||||
def test_captured_dict_cppdefines_warn_and_skip(tmp_path, caplog) -> None:
|
||||
"""A dict CPPDEFINES entry (legal SCons) must warn and skip; formatting
|
||||
it blind would hand the compiler -D{'FOO': '1'} garbage."""
|
||||
|
||||
@@ -259,6 +259,37 @@ def _patch_download_with_manifests(monkeypatch, tmp_path, manifests, *, properti
|
||||
_patch_registry_resolve(monkeypatch)
|
||||
|
||||
|
||||
def test_wave_requirement_growth_defers_the_superseded_download(tmp_path, monkeypatch):
|
||||
"""A's manifest constrains B while B sits in the same wave: B's
|
||||
drain-time resolution is superseded, so its download defers to the
|
||||
next wave instead of fetching a version that is immediately replaced."""
|
||||
download_names: list[str] = []
|
||||
manifests = {
|
||||
"esphome/A": {
|
||||
"name": "A",
|
||||
"build": {},
|
||||
"dependencies": {"esphome/B": ">=1.0"},
|
||||
},
|
||||
"esphome/B": {"name": "B", "build": {}},
|
||||
}
|
||||
|
||||
def fake_download(self, force=False, salt="", namespace="", progress=None):
|
||||
download_names.append(self.name)
|
||||
self.path = tmp_path / self.get_require_name()
|
||||
self.path.mkdir(parents=True, exist_ok=True)
|
||||
(self.path / "library.json").write_text(json.dumps(manifests[self.name]))
|
||||
|
||||
monkeypatch.setattr(ConvertedLibrary, "download", fake_download)
|
||||
_patch_registry_resolve(monkeypatch)
|
||||
top = convert_libraries(
|
||||
[Library("esphome/A", "1.0.0", None), Library("esphome/B", None, None)],
|
||||
_backend(),
|
||||
)
|
||||
assert sorted(c.name for c in top) == ["esphome/A", "esphome/B"]
|
||||
# B downloads exactly once, after its requirement set stabilized
|
||||
assert download_names.count("esphome/B") == 1
|
||||
|
||||
|
||||
def test_convert_libraries_parses_library_properties(tmp_path, monkeypatch):
|
||||
# A manifest provided as library.properties (Arduino style) instead of
|
||||
# library.json must still be parsed and converted.
|
||||
@@ -848,6 +879,7 @@ def test_walk_warns_for_properties_only_depends(
|
||||
{"esphome/A": "name=A\nversion=1.0\ndepends=Wire, SPI\n"},
|
||||
properties=("esphome/A",),
|
||||
)
|
||||
caplog.set_level("INFO")
|
||||
convert_libraries([Library("esphome/A", "1.0.0", None)], _backend())
|
||||
assert "declares dependencies via library.properties" in caplog.text
|
||||
|
||||
|
||||
Reference in New Issue
Block a user