mirror of
https://github.com/esphome/esphome.git
synced 2026-10-07 11:26:39 +00:00
[nrf52] Stream the SDK clone and resume it after an interruption (#19731)
This commit is contained in:
@@ -5,7 +5,7 @@ import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import ANY, call, patch
|
||||
|
||||
import platformdirs
|
||||
import pytest
|
||||
@@ -129,6 +129,12 @@ def mock_nrf52_ops():
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _mark_west_initialized(framework: Path) -> None:
|
||||
"""What a finished ``west init`` leaves behind."""
|
||||
(framework / ".west").mkdir()
|
||||
(framework / ".west" / "config").touch()
|
||||
|
||||
|
||||
def _touch_penv_python(penv: Path) -> None:
|
||||
"""Create the interpreter file so the rebuild gate sees a live venv."""
|
||||
python = get_python_env_executable_path(penv, "python")
|
||||
@@ -250,6 +256,92 @@ class TestCheckAndInstall:
|
||||
assert "-o=--depth=1" in init_cmd
|
||||
assert "update" in update_cmd
|
||||
assert "--fetch-opt=--depth=1" in update_cmd
|
||||
# Streamed, so the long clone's progress reaches the log
|
||||
for west_call in mock_nrf52_ops.run_command_ok.call_args_list[:2]:
|
||||
assert west_call.kwargs["stream_output"] is True
|
||||
|
||||
def test_interrupted_download_resumes(
|
||||
self,
|
||||
nrf52_dirs: SimpleNamespace,
|
||||
mock_nrf52_ops: SimpleNamespace,
|
||||
) -> None:
|
||||
"""A workspace left by a cut-short download is updated in place, not
|
||||
wiped and cloned again."""
|
||||
_mark_venv_ready(nrf52_dirs.python_env)
|
||||
_mark_west_initialized(nrf52_dirs.framework)
|
||||
|
||||
# A marker left by an earlier failed resume
|
||||
(nrf52_dirs.framework / ".resume_failed").touch()
|
||||
|
||||
check_and_install()
|
||||
|
||||
assert (
|
||||
call(nrf52_dirs.framework, msg=ANY)
|
||||
not in mock_nrf52_ops.rmdir.call_args_list
|
||||
)
|
||||
assert not (nrf52_dirs.framework / ".resume_failed").exists()
|
||||
# west update (no init), then pip install zephyr reqs
|
||||
first = mock_nrf52_ops.run_command_ok.call_args_list[0]
|
||||
assert "update" in first.args[0]
|
||||
assert "init" not in first.args[0]
|
||||
assert first.kwargs["cwd"] == nrf52_dirs.framework
|
||||
assert mock_nrf52_ops.run_command_ok.call_count == 2
|
||||
assert (nrf52_dirs.framework / ".ready").exists()
|
||||
|
||||
def test_failed_resume_keeps_the_download_once(
|
||||
self,
|
||||
nrf52_dirs: SimpleNamespace,
|
||||
mock_nrf52_ops: SimpleNamespace,
|
||||
) -> None:
|
||||
"""A first failed resume keeps what was fetched (the network likely
|
||||
dropped again) and is retried on the next build."""
|
||||
_mark_venv_ready(nrf52_dirs.python_env)
|
||||
_mark_west_initialized(nrf52_dirs.framework)
|
||||
mock_nrf52_ops.run_command_ok.return_value = False
|
||||
|
||||
with pytest.raises(EsphomeError, match="Can't resume"):
|
||||
check_and_install()
|
||||
|
||||
assert (
|
||||
call(nrf52_dirs.framework, msg=ANY)
|
||||
not in mock_nrf52_ops.rmdir.call_args_list
|
||||
)
|
||||
assert (nrf52_dirs.framework / ".resume_failed").exists()
|
||||
|
||||
def test_cut_short_init_starts_over(
|
||||
self,
|
||||
nrf52_dirs: SimpleNamespace,
|
||||
mock_nrf52_ops: SimpleNamespace,
|
||||
) -> None:
|
||||
"""A ``.west`` without its config (init cut short) clones clean."""
|
||||
_mark_venv_ready(nrf52_dirs.python_env)
|
||||
(nrf52_dirs.framework / ".west").mkdir()
|
||||
|
||||
check_and_install()
|
||||
|
||||
mock_nrf52_ops.rmdir.assert_any_call(nrf52_dirs.framework, msg=ANY)
|
||||
first = mock_nrf52_ops.run_command_ok.call_args_list[0]
|
||||
assert "init" in first.args[0]
|
||||
|
||||
def test_second_failed_resume_starts_over(
|
||||
self,
|
||||
nrf52_dirs: SimpleNamespace,
|
||||
mock_nrf52_ops: SimpleNamespace,
|
||||
) -> None:
|
||||
"""A resume failing twice in a row wipes the workspace and clones clean."""
|
||||
_mark_venv_ready(nrf52_dirs.python_env)
|
||||
_mark_west_initialized(nrf52_dirs.framework)
|
||||
(nrf52_dirs.framework / ".resume_failed").touch()
|
||||
# resumed update fails; clean init, update and zephyr reqs succeed
|
||||
mock_nrf52_ops.run_command_ok.side_effect = [False, True, True, True]
|
||||
|
||||
check_and_install()
|
||||
|
||||
mock_nrf52_ops.rmdir.assert_any_call(nrf52_dirs.framework, msg=ANY)
|
||||
commands = [c.args[0] for c in mock_nrf52_ops.run_command_ok.call_args_list]
|
||||
assert "update" in commands[0]
|
||||
assert "init" in commands[1]
|
||||
assert "update" in commands[2]
|
||||
|
||||
def test_requirements_install_failure_raises(
|
||||
self,
|
||||
|
||||
Reference in New Issue
Block a user