- Modified status messages and stage labels in `test_addon.py` for clarity and consistency. - Added tests to ensure proper host termination and command execution in `test_addon.py`. - Enhanced `test_bootstrap_runtime.py` with additional tests for installation behavior, including handling of CUDA and MPS devices, and improved error handling for disk space and network checks. - Updated download progress reporting in `test_download_progress.py` to include download speed and improved message formatting. - Added new tests in `test_worker.py` for device selection, NPZ file validation, and model downloading behavior with Hugging Face endpoints. - Bumped version in `uv.lock` to 0.9.30.
193 lines
6.1 KiB
Python
193 lines
6.1 KiB
Python
import importlib.util
|
|
import json
|
|
import os
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def load_worker():
|
|
specification = importlib.util.spec_from_file_location(
|
|
"snapform_download_worker",
|
|
PROJECT_ROOT / "src" / "snapform" / "worker.py",
|
|
)
|
|
module = importlib.util.module_from_spec(specification)
|
|
specification.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
class FakeTqdm:
|
|
def __init__(self, *args, **kwargs):
|
|
self.n = kwargs.get("initial", 0)
|
|
self.total = kwargs.get("total", 0)
|
|
|
|
def update(self, amount=1):
|
|
self.n += amount
|
|
return True
|
|
|
|
def refresh(self, *args, **kwargs):
|
|
return True
|
|
|
|
|
|
class DownloadProgressTest(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.worker = load_worker()
|
|
|
|
def test_reports_aggregated_download_bytes(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
status_path = Path(directory) / "status.json"
|
|
progress_class = self.worker.create_download_progress_class(
|
|
status_path,
|
|
"owner/model",
|
|
tqdm_type=FakeTqdm,
|
|
clock=lambda: 1.0,
|
|
)
|
|
progress = progress_class(
|
|
desc="Downloading bytes",
|
|
total=100,
|
|
initial=0,
|
|
unit="B",
|
|
)
|
|
|
|
progress.update(25)
|
|
|
|
status = json.loads(status_path.read_text(encoding="utf-8"))
|
|
self.assertAlmostEqual(status["progress"], 0.275)
|
|
self.assertEqual(status["message"], "downloading owner/model")
|
|
|
|
def test_reports_download_speed(self):
|
|
class FakeTqdmWithRate(FakeTqdm):
|
|
@property
|
|
def format_dict(self):
|
|
return {"rate": 14_000_000}
|
|
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
status_path = Path(directory) / "status.json"
|
|
progress_class = self.worker.create_download_progress_class(
|
|
status_path,
|
|
"owner/model",
|
|
tqdm_type=FakeTqdmWithRate,
|
|
clock=lambda: 1.0,
|
|
label="da3 small",
|
|
)
|
|
progress = progress_class(
|
|
desc="Downloading bytes",
|
|
total=100,
|
|
initial=0,
|
|
unit="B",
|
|
)
|
|
|
|
progress.update(50)
|
|
|
|
status = json.loads(status_path.read_text(encoding="utf-8"))
|
|
self.assertEqual(
|
|
status["message"],
|
|
"downloading da3 small 13.4 MB/s",
|
|
)
|
|
|
|
def test_staged_download_prefixes_speed_with_downloading(self):
|
|
class FakeTqdmWithRate(FakeTqdm):
|
|
@property
|
|
def format_dict(self):
|
|
return {"rate": 14_000_000}
|
|
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
status_path = Path(directory) / "status.json"
|
|
progress_class = self.worker.create_download_progress_class(
|
|
status_path,
|
|
"owner/model",
|
|
tqdm_type=FakeTqdmWithRate,
|
|
clock=lambda: 1.0,
|
|
label="da3 small",
|
|
stage=6,
|
|
stages=8,
|
|
stage_label="da3 small",
|
|
)
|
|
progress = progress_class(
|
|
desc="Downloading bytes",
|
|
total=100,
|
|
initial=0,
|
|
unit="B",
|
|
)
|
|
|
|
progress.update(50)
|
|
|
|
status = json.loads(status_path.read_text(encoding="utf-8"))
|
|
self.assertEqual(status["message"], "downloading 13.4 MB/s")
|
|
self.assertEqual(status["stage"], 6)
|
|
self.assertEqual(status["stages"], 8)
|
|
self.assertEqual(status["stage_label"], "da3 small")
|
|
|
|
def test_ignores_unrelated_progress_bars(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
status_path = Path(directory) / "status.json"
|
|
progress_class = self.worker.create_download_progress_class(
|
|
status_path,
|
|
"owner/model",
|
|
tqdm_type=FakeTqdm,
|
|
clock=lambda: 1.0,
|
|
)
|
|
progress = progress_class(
|
|
desc="Reconstructing",
|
|
total=100,
|
|
initial=0,
|
|
unit="B",
|
|
)
|
|
|
|
progress.update(25)
|
|
|
|
self.assertFalse(status_path.exists())
|
|
|
|
def test_resolve_hf_endpoint_keeps_direct_endpoint(self):
|
|
with patch.dict(os.environ, {"HF_ENDPOINT": ""}), patch.object(
|
|
self.worker,
|
|
"reachable",
|
|
return_value=True,
|
|
):
|
|
endpoint, used_mirror = self.worker.resolve_hf_endpoint()
|
|
|
|
self.assertEqual(endpoint, "https://huggingface.co/")
|
|
self.assertFalse(used_mirror)
|
|
|
|
def test_resolve_hf_endpoint_falls_back_to_mirror(self):
|
|
with patch.dict(os.environ, {"HF_ENDPOINT": ""}), patch.object(
|
|
self.worker,
|
|
"reachable",
|
|
side_effect=lambda url, timeout=None: "hf-mirror" in url,
|
|
):
|
|
endpoint, used_mirror = self.worker.resolve_hf_endpoint()
|
|
|
|
self.assertEqual(endpoint, "https://hf-mirror.com")
|
|
self.assertTrue(used_mirror)
|
|
|
|
def test_resolve_hf_endpoint_respects_environment_override(self):
|
|
with patch.dict(os.environ, {"HF_ENDPOINT": "https://hf.example"}), patch.object(
|
|
self.worker,
|
|
"reachable",
|
|
) as mocked_reachable:
|
|
endpoint, used_mirror = self.worker.resolve_hf_endpoint()
|
|
|
|
self.assertEqual(endpoint, "https://hf.example")
|
|
self.assertFalse(used_mirror)
|
|
mocked_reachable.assert_not_called()
|
|
|
|
def test_resolve_hf_endpoint_keeps_direct_when_mirrors_unreachable(self):
|
|
with patch.dict(os.environ, {"HF_ENDPOINT": ""}), patch.object(
|
|
self.worker,
|
|
"reachable",
|
|
return_value=False,
|
|
):
|
|
endpoint, used_mirror = self.worker.resolve_hf_endpoint()
|
|
|
|
self.assertEqual(endpoint, "https://huggingface.co/")
|
|
self.assertFalse(used_mirror)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|