mirror of
https://github.com/Comfy-Org/ComfyUI.git
synced 2026-08-24 10:03:55 +08:00
Add delete and clear all downloads funcitonalities.
This commit is contained in:
136
tests-unit/model_downloader_test/test_delete.py
Normal file
136
tests-unit/model_downloader_test/test_delete.py
Normal file
@@ -0,0 +1,136 @@
|
||||
"""Unit tests for ``DownloadManager.delete`` and ``DownloadManager.clear``.
|
||||
|
||||
Deleting a terminal row must remove it from history for good (so it does not
|
||||
reappear on the next ``list``), leave live rows untouched, and clean up any
|
||||
leftover ``.part`` temp file without touching the finished model file.
|
||||
|
||||
``clear()`` is the bulk variant: it removes all terminal rows atomically, skips
|
||||
live ones, and returns the count of rows deleted.
|
||||
|
||||
Async methods are driven via ``asyncio.run`` so no pytest-asyncio plugin is
|
||||
required.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from app.model_downloader.constants import DownloadStatus
|
||||
from app.model_downloader.database import queries
|
||||
from app.model_downloader.manager import DOWNLOAD_MANAGER, DownloadError
|
||||
|
||||
|
||||
def _insert(download_id: str, status: str, *, temp_path: str = "/tmp/none.part") -> None:
|
||||
queries.insert_download(
|
||||
{
|
||||
"id": download_id,
|
||||
"url": "https://huggingface.co/org/model.safetensors",
|
||||
"model_id": "loras/model.safetensors",
|
||||
"dest_path": "/tmp/model.safetensors",
|
||||
"temp_path": temp_path,
|
||||
"status": status,
|
||||
"priority": 0,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_delete_removes_terminal_row_from_history():
|
||||
_insert("done", DownloadStatus.COMPLETED)
|
||||
|
||||
asyncio.run(DOWNLOAD_MANAGER.delete("done"))
|
||||
|
||||
assert queries.get_download("done") is None
|
||||
|
||||
|
||||
def test_delete_refuses_live_row():
|
||||
_insert("live", DownloadStatus.QUEUED)
|
||||
|
||||
with pytest.raises(DownloadError) as excinfo:
|
||||
asyncio.run(DOWNLOAD_MANAGER.delete("live"))
|
||||
|
||||
assert excinfo.value.code == "DOWNLOAD_ACTIVE"
|
||||
assert queries.get_download("live") is not None
|
||||
|
||||
|
||||
def test_delete_missing_row_raises_not_found():
|
||||
with pytest.raises(DownloadError) as excinfo:
|
||||
asyncio.run(DOWNLOAD_MANAGER.delete("nope"))
|
||||
|
||||
assert excinfo.value.code == "NOT_FOUND"
|
||||
|
||||
|
||||
def test_delete_removes_leftover_temp_file(tmp_path):
|
||||
partial = tmp_path / "model.safetensors.part"
|
||||
partial.write_bytes(b"partial")
|
||||
_insert("failed", DownloadStatus.FAILED, temp_path=str(partial))
|
||||
|
||||
asyncio.run(DOWNLOAD_MANAGER.delete("failed"))
|
||||
|
||||
assert not os.path.exists(partial)
|
||||
assert queries.get_download("failed") is None
|
||||
|
||||
|
||||
# ----- clear -----
|
||||
|
||||
|
||||
def test_clear_removes_all_terminal_rows():
|
||||
_insert("c-done", DownloadStatus.COMPLETED)
|
||||
_insert("c-fail", DownloadStatus.FAILED)
|
||||
_insert("c-canc", DownloadStatus.CANCELLED)
|
||||
|
||||
deleted = asyncio.run(DOWNLOAD_MANAGER.clear())
|
||||
|
||||
assert deleted == 3
|
||||
assert queries.get_download("c-done") is None
|
||||
assert queries.get_download("c-fail") is None
|
||||
assert queries.get_download("c-canc") is None
|
||||
|
||||
|
||||
def test_clear_skips_live_rows():
|
||||
_insert("cl-queued", DownloadStatus.QUEUED)
|
||||
_insert("cl-paused", DownloadStatus.PAUSED)
|
||||
_insert("cl-done", DownloadStatus.COMPLETED)
|
||||
|
||||
deleted = asyncio.run(DOWNLOAD_MANAGER.clear())
|
||||
|
||||
assert deleted == 1
|
||||
assert queries.get_download("cl-queued") is not None
|
||||
assert queries.get_download("cl-paused") is not None
|
||||
assert queries.get_download("cl-done") is None
|
||||
|
||||
|
||||
def test_clear_returns_zero_when_nothing_to_delete():
|
||||
_insert("cl-only-live", DownloadStatus.QUEUED)
|
||||
|
||||
deleted = asyncio.run(DOWNLOAD_MANAGER.clear())
|
||||
|
||||
assert deleted == 0
|
||||
assert queries.get_download("cl-only-live") is not None
|
||||
|
||||
|
||||
def test_clear_removes_leftover_temp_files(tmp_path):
|
||||
partial = tmp_path / "clear_partial.part"
|
||||
partial.write_bytes(b"partial data")
|
||||
finished = tmp_path / "finished.safetensors"
|
||||
finished.write_bytes(b"real model weights")
|
||||
|
||||
_insert("cl-part", DownloadStatus.FAILED, temp_path=str(partial))
|
||||
# The finished file is not the temp_path; temp_path for a completed download
|
||||
# no longer exists (already renamed), so use a non-existent path here to
|
||||
# verify clear() tolerates a missing temp file without raising.
|
||||
_insert("cl-comp", DownloadStatus.COMPLETED, temp_path=str(tmp_path / "gone.part"))
|
||||
|
||||
asyncio.run(DOWNLOAD_MANAGER.clear())
|
||||
|
||||
# Leftover .part from the failed download is cleaned up.
|
||||
assert not partial.exists()
|
||||
# Finished model file is never touched.
|
||||
assert finished.exists()
|
||||
|
||||
|
||||
def test_clear_empty_db_returns_zero():
|
||||
deleted = asyncio.run(DOWNLOAD_MANAGER.clear())
|
||||
assert deleted == 0
|
||||
Reference in New Issue
Block a user