Files
MoviePilot/tests/test_transfer_mark_torrent_completed.py

194 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
from types import SimpleNamespace
from app.chain.transfer import JobManager, TransferChain
from app.core.config import settings
from app.schemas import FileItem, TransferTask
from app.schemas.types import MediaType
class _FakeMeta:
"""构造最小可用的剧集元数据。"""
def __init__(self, episode: int, season: int = 1):
"""初始化剧集编号相关字段。"""
self.name = "Test Show"
self.title = f"Test Show S{season:02d}E{episode:02d}"
self.year = "2026"
self.type = MediaType.TV
self.begin_season = season
self.end_season = None
self.total_season = 1
self.begin_episode = episode
self.end_episode = None
self.total_episode = 1
self.episode_list = [episode]
self.season_episode = f"S{season:02d}E{episode:02d}"
self.part = None
@property
def season(self):
"""返回季字符串。"""
return f"S{self.begin_season:02d}"
@property
def episode(self):
"""返回集字符串。"""
return f"E{self.begin_episode:02d}"
def to_dict(self):
"""返回元数据字典。"""
return {
"title": self.title,
"name": self.name,
"year": self.year,
"type": self.type.value,
"begin_season": self.begin_season,
"end_season": self.end_season,
"total_season": self.total_season,
"begin_episode": self.begin_episode,
"end_episode": self.end_episode,
"total_episode": self.total_episode,
"season_episode": self.season_episode,
"episode_list": self.episode_list,
"part": self.part,
}
def _make_chain() -> TransferChain:
"""构造跳过初始化的 TransferChain仅带作业视图。"""
chain = object.__new__(TransferChain)
chain.jobview = JobManager()
chain._media_exts = settings.RMT_MEDIAEXT
chain._subtitle_exts = settings.RMT_SUBEXT
chain._audio_exts = settings.RMT_AUDIOEXT
chain._allowed_exts = (
chain._media_exts + chain._audio_exts + chain._subtitle_exts
)
chain._success_target_files = {}
chain._scrape_batches = {}
return chain
def _make_task(episode: int, download_hash: str, downloader: str) -> TransferTask:
"""构造带下载器信息的整理任务。"""
name = f"Test.Show.S01E{episode:02d}.mkv"
task = TransferTask(
fileitem=FileItem(
storage="local",
path=f"/downloads/Test Show/{name}",
type="file",
name=name,
basename=name.removesuffix(".mkv"),
extension="mkv",
size=1024,
),
meta=_FakeMeta(episode),
)
task.download_hash = download_hash
task.downloader = downloader
return task
def _mark(chain: TransferChain, download_hash: str, downloader: str):
"""调用私有的打标签方法。"""
chain._TransferChain__mark_torrent_completed_if_done(download_hash, downloader)
def _finish_task(chain: TransferChain, task: TransferTask):
"""将任务登记并流转到完成状态。"""
assert chain.jobview.add_task(task)
chain.jobview.running_task(task)
chain.jobview.finish_task(task)
def test_mark_skips_tag_when_torrent_still_downloading():
"""种子未下载完成时(多集种子先完成单集),不得设置已整理标签(#6009"""
chain = _make_chain()
completed = []
chain.transfer_completed = lambda **kwargs: completed.append(kwargs)
chain.list_torrents = lambda **kwargs: [SimpleNamespace(progress=52.3)]
_finish_task(chain, _make_task(1, "hash1", "qbittorrent"))
_mark(chain, "hash1", "qbittorrent")
assert completed == []
def test_mark_tags_when_torrent_completed():
"""种子已下载完成且任务全部结束时,正常设置已整理标签。"""
chain = _make_chain()
completed = []
chain.transfer_completed = lambda **kwargs: completed.append(kwargs)
chain.list_torrents = lambda **kwargs: [SimpleNamespace(progress=100)]
_finish_task(chain, _make_task(1, "hash1", "qbittorrent"))
_mark(chain, "hash1", "qbittorrent")
assert completed == [{"hashs": "hash1", "downloader": "qbittorrent"}]
def test_mark_short_circuits_downloader_query_when_jobview_not_done():
"""作业视图还有未结束任务时,不应产生任何下载器查询。"""
chain = _make_chain()
queries = []
chain.transfer_completed = lambda **kwargs: None
chain.list_torrents = lambda **kwargs: queries.append(kwargs) or []
task = _make_task(1, "hash1", "qbittorrent")
assert chain.jobview.add_task(task)
chain.jobview.running_task(task)
_mark(chain, "hash1", "qbittorrent")
assert queries == []
def test_mark_skips_tag_when_torrent_not_found():
"""下载器中查不到种子时不打标签,留待定时轮询兜底。"""
chain = _make_chain()
completed = []
chain.transfer_completed = lambda **kwargs: completed.append(kwargs)
chain.list_torrents = lambda **kwargs: []
_finish_task(chain, _make_task(1, "hash1", "qbittorrent"))
_mark(chain, "hash1", "qbittorrent")
assert completed == []
def test_mark_skips_tag_when_list_torrents_raises():
"""查询下载器异常时不打标签且不向上抛出。"""
chain = _make_chain()
completed = []
chain.transfer_completed = lambda **kwargs: completed.append(kwargs)
def _raise(**_kwargs):
raise RuntimeError("downloader unreachable")
chain.list_torrents = _raise
_finish_task(chain, _make_task(1, "hash1", "qbittorrent"))
_mark(chain, "hash1", "qbittorrent")
assert completed == []
def test_multi_episode_torrent_tags_only_after_last_episode():
"""#6009 回归E01 先整理完不打标签,种子整体下载完成后才打标签。"""
chain = _make_chain()
completed = []
chain.transfer_completed = lambda **kwargs: completed.append(kwargs)
progress = {"value": 60}
chain.list_torrents = lambda **kwargs: [SimpleNamespace(progress=progress["value"])]
# E01 下载完成并整理,此时种子整体仍在下载
_finish_task(chain, _make_task(1, "hash1", "qbittorrent"))
_mark(chain, "hash1", "qbittorrent")
assert completed == []
# E02 下载完成并整理,种子整体到 100%
progress["value"] = 100
_finish_task(chain, _make_task(2, "hash1", "qbittorrent"))
_mark(chain, "hash1", "qbittorrent")
assert completed == [{"hashs": "hash1", "downloader": "qbittorrent"}]