"""Lazy download and SHA256 pinning, exercised with local file:// URLs.""" from __future__ import annotations import hashlib from pathlib import Path import pytest from app.errors import Unsupported from app.models import Backend, BackendSpec, ModelFile, Registry from .conftest import make_settings def _backend(source: Path, sha256: str, size: int, loads: list[dict[str, str]]) -> Backend: spec = BackendSpec( id="test-model", model="test-model", license="MIT", commercialUse=True, experimental=False, source=None, files=(ModelFile("weights.bin", source.as_uri(), sha256, size),), ) return Backend(spec, lambda files, _settings: loads.append(files) or "runtime") def test_downloads_once_and_verifies(media_root: Path, tmp_path: Path) -> None: source = tmp_path / "upstream.bin" source.write_bytes(b"weights" * 100) digest = hashlib.sha256(source.read_bytes()).hexdigest() loads: list[dict[str, str]] = [] settings = make_settings(media_root, tmp_path, allow_model_download=True) registry = Registry(settings, backends={"embedFrames": _backend(source, digest, 700, loads)}) assert registry.runtime("embedFrames") == "runtime" assert registry.runtime("embedFrames") == "runtime" assert len(loads) == 1 cached = Path(loads[0]["weights.bin"]) assert cached == tmp_path / "models" / "test-model" / "weights.bin" assert cached.read_bytes() == source.read_bytes() def test_hash_mismatch_deletes_file_and_reports_unsupported(media_root: Path, tmp_path: Path) -> None: source = tmp_path / "tampered.bin" source.write_bytes(b"tampered") settings = make_settings(media_root, tmp_path, allow_model_download=True) backend = _backend(source, "0" * 64, 8, []) registry = Registry(settings, backends={"embedFrames": backend}) with pytest.raises(Unsupported) as error: registry.runtime("embedFrames") assert "SHA256" in error.value.message assert not (tmp_path / "models" / "test-model" / "weights.bin").exists() assert registry.unavailable_reason(backend, "embedFrames") == error.value.message def test_oversized_download_is_aborted(media_root: Path, tmp_path: Path) -> None: source = tmp_path / "big.bin" source.write_bytes(b"x" * 5000) settings = make_settings(media_root, tmp_path, allow_model_download=True) registry = Registry(settings, backends={"embedFrames": _backend(source, "0" * 64, 10, [])}) with pytest.raises(Unsupported): registry.runtime("embedFrames") assert not list((tmp_path / "models" / "test-model").iterdir()) def test_offline_without_weights_is_unsupported(media_root: Path, tmp_path: Path) -> None: source = tmp_path / "w.bin" source.write_bytes(b"w") registry = Registry( make_settings(media_root, tmp_path), backends={"embedFrames": _backend(source, "0" * 64, 1, [])} ) with pytest.raises(Unsupported) as error: registry.runtime("embedFrames") assert "MEDIA_MODEL_DOWNLOAD=0" in error.value.message