Files
MoviePilot/tests/test_transfer_stale_tasks.py

129 lines
4.2 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.
"""整理任务失活收敛行为测试。"""
from app.chain import transfer
from app.chain.transfer import JobManager
from app.domain.meta.metabase import MetaBase
from app.schemas import FileItem
from app.application.transfer import TransferTask
from app.schemas.types import MediaType
class _FakeMeta(MetaBase):
"""
提供整理任务分组需要的最小元数据。
继承 MetaBase 而非鸭子类型TransferTask.meta 已标注为 MetaBasepydantic 会做
isinstance 校验。三个类级属性用来遮蔽 MetaBase 上的同名 property。
"""
name = None
episode_list = None
season_episode = None
def __init__(self):
super().__init__(title="Test Show S01E01")
self.name = "Test Show"
self.title = "Test Show S01E01"
self.year = "2026"
self.type = MediaType.TV
self.begin_season = 1
self.end_season = None
self.total_season = 1
self.begin_episode = 1
self.end_episode = None
self.total_episode = 1
self.episode_list = [1]
self.season_episode = "S01E01"
self.part = None
def to_dict(self):
"""返回 TransferJobTask 所需的元数据字典。"""
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_task(name: str = "Test.Show.S01E01.mkv") -> TransferTask:
"""创建失活检测使用的整理任务。"""
return TransferTask(
fileitem=FileItem(
storage="local",
path=f"/downloads/{name}",
type="file",
name=name,
basename=name.removesuffix(".mkv"),
extension="mkv",
size=1024,
),
meta=_FakeMeta(),
)
def test_external_running_task_expires_without_heartbeat(monkeypatch):
"""外部接管的运行中任务超过心跳期限后应被标记失败并清理。"""
clock = [100.0]
monkeypatch.setattr(transfer, "monotonic", lambda: clock[0])
manager = JobManager()
task = _make_task()
assert manager.add_task(task)
manager.running_task(task)
clock[0] = 221.0
expired = manager.expire_stale_running_tasks(timeout_seconds=120)
assert expired == [(task.fileitem, 121)]
assert manager.list_jobs() == []
def test_main_thread_execution_is_not_expired(monkeypatch):
"""主程序整理线程仍在执行的任务不应被失活检测伪清理。"""
clock = [100.0]
monkeypatch.setattr(transfer, "monotonic", lambda: clock[0])
manager = JobManager()
task = _make_task()
assert manager.add_task(task)
manager.start_execution(task)
manager.running_task(task)
clock[0] = 500.0
assert manager.expire_stale_running_tasks(timeout_seconds=120) == []
assert manager.total() == 1
manager.finish_execution(task)
expired = manager.expire_stale_running_tasks(timeout_seconds=120)
assert expired == [(task.fileitem, 400)]
assert manager.list_jobs() == []
def test_waiting_task_and_refreshed_heartbeat_do_not_expire(monkeypatch):
"""等待中任务不受失活期限影响,重复运行状态更新可刷新外部心跳。"""
clock = [100.0]
monkeypatch.setattr(transfer, "monotonic", lambda: clock[0])
manager = JobManager()
waiting_task = _make_task("Test.Show.S01E01.waiting.mkv")
running_task = _make_task("Test.Show.S01E02.running.mkv")
running_task.meta.begin_episode = 2
running_task.meta.episode_list = [2]
assert manager.add_task(waiting_task)
assert manager.add_task(running_task)
manager.running_task(running_task)
clock[0] = 180.0
manager.running_task(running_task)
clock[0] = 250.0
assert manager.expire_stale_running_tasks(timeout_seconds=120) == []
assert manager.total() == 2