Files
hermes-agent/tests/pm/test_download_progress.py
ethernet bdb52ce711 fix(local-models): use pm pins and resumable component downloads
Use PM for engine binaries, dependent runtime archives, and model files.
Keep one operation-owned pause event through installation and download.
Report whole-plan bytes and retain paused jobs across desktop remounts.

Preserve the completed lm-pm worktree as its own integration parent.
The owning session verified focused Python and desktop tests, actual
Windows ARM64 CUDA downloads, and rendered pause/resume controls.
Combined verification with the safety repairs follows in the merge.
2026-09-09 15:17:09 -04:00

44 lines
2.1 KiB
Python

"""Download progress describes actual whole-plan bytes on fresh and resumed runs."""
from __future__ import annotations
from pm.downloader import Download, Source
from tests.pm._range_server import RangeHandler, dl_server, url # noqa: F401
def test_progress_counts_cached_files_and_distinguishes_equal_basenames(tmp_path, dl_server):
bodies = {"/a": b"first", "/b": b"second-file"}
RangeHandler.payloads = bodies
sources = [Source(url(dl_server, path), tmp_path / path[1:] / "model.bin") for path in bodies]
expected = sum(map(len, bodies.values()))
for attempt in range(2):
ticks = []
Download(sources, partials_dir=tmp_path / "partials").run(
progress=lambda done, total, ranges: ticks.append((done, total, ranges)))
assert ticks, f"attempt {attempt} did not report its completed files"
done, total, ranges = ticks[-1]
assert done == total == expected
assert len(ranges) == len(sources)
assert sum(end - start for rows in ranges.values() for start, end in rows) == done
def test_unknown_length_sources_do_not_lose_completed_bytes(tmp_path, dl_server, monkeypatch):
RangeHandler.payloads = {"/a": b"first", "/b": b"second-file"}
RangeHandler.no_range = True
send_header = RangeHandler.send_header
def without_length(self, name, value):
if name.lower() != "content-length":
send_header(self, name, value)
monkeypatch.setattr(RangeHandler, "send_header", without_length)
ticks = []
sources = [Source(url(dl_server, path), tmp_path / path[1:]) for path in RangeHandler.payloads]
Download(sources, partials_dir=tmp_path / "partials").run(
progress=lambda done, total, ranges: ticks.append((done, total, ranges)))
expected = sum(source.dest.stat().st_size for source in sources)
assert ticks[-1][:2] == (expected, expected)
assert all(sum(end - start for rows in ranges.values() for start, end in rows) == done
for done, _, ranges in ticks)
assert [done for done, _, _ in ticks] == sorted(done for done, _, _ in ticks)