Files
MoviePilot/tests/test_acceleration.py
DDSRem 2de976f6b3 Merge pull request #7050 from DDSRem-Dev/codex-comment-migration
docs: 统一全项目中文注释和结构化契约说明
2026-10-17 19:26:29 +08:00

162 lines
5.5 KiB
Python

"""
系统拓扑、目录大小和规则解析加速端口测试。
"""
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import MagicMock
import pytest
from app.application import directory as directory_module
from app.application import rules as rules_module
from app.application.transfer import jobs as jobs_module
from app.startup.composition import domain as domain_composition
def test_directory_helper_requires_configured_topology_for_local_paths(
monkeypatch,
) -> None:
"""
真实本地路径同盘判断未装配时必须稳定失败。
"""
monkeypatch.setattr(directory_module, "_disk_topology", None)
with pytest.raises(RuntimeError, match="本地磁盘拓扑能力尚未由启动组合根配置"):
directory_module.DirectoryHelper()._is_same_source(
(Path("/downloads"), "local"),
(Path("/library"), "local"),
)
def test_directory_helper_only_calls_topology_for_two_local_paths(
monkeypatch,
) -> None:
"""
远端存储只比较类型,本地路径才调用磁盘拓扑端口。
"""
topology = MagicMock()
topology.is_same_disk.return_value = True
monkeypatch.setattr(directory_module, "_disk_topology", topology)
helper = directory_module.DirectoryHelper()
assert helper._is_same_source(
(Path("/remote-a"), "rclone"),
(Path("/remote-b"), "rclone"),
) is True
assert helper._is_same_source(
(Path("/downloads"), "local"),
(Path("/library"), "local"),
) is True
topology.is_same_disk.assert_called_once_with(
Path("/downloads"),
Path("/library"),
)
def test_rule_parser_uses_accelerator_when_available(monkeypatch) -> None:
"""
加速器返回解析结构时应保留 pyparsing 兼容投影。
"""
accelerator = MagicMock()
accelerator.parse_filter_rule.return_value = [["HDR", "and", ["not", "BLU"]]]
monkeypatch.setattr(rules_module, "_filter_rule_parser", accelerator)
parsed = rules_module.RuleParser().parse("HDR & !BLU")
assert parsed.as_list() == [["HDR", "and", ["not", "BLU"]]]
accelerator.parse_filter_rule.assert_called_once_with("HDR & !BLU")
@pytest.mark.parametrize("accelerator", [None, MagicMock()])
def test_rule_parser_falls_back_to_python_when_acceleration_unavailable(
monkeypatch,
accelerator,
) -> None:
"""
未装配或普通适配器异常都必须回退到 Python 解析器。
"""
if accelerator is not None:
accelerator.parse_filter_rule.side_effect = RuntimeError("rust unavailable")
monkeypatch.setattr(rules_module, "_filter_rule_parser", accelerator)
parsed = rules_module.RuleParser().parse("HDR & !BLU")
assert parsed.as_list()
def test_job_task_size_only_reads_missing_local_size(monkeypatch) -> None:
"""
目录大小端口只服务于未携带 size 的本地工作项。
"""
reader = MagicMock()
reader.get_directory_size.return_value = 2048
monkeypatch.setattr(jobs_module, "_directory_size", reader)
explicit = SimpleNamespace(
fileitem=SimpleNamespace(size=1024, storage="local", path="/explicit"),
)
remote = SimpleNamespace(
fileitem=SimpleNamespace(size=None, storage="rclone", path="/remote"),
)
local = SimpleNamespace(
fileitem=SimpleNamespace(size=None, storage="local", path="/downloads"),
)
assert jobs_module._job_task_size(explicit) == 1024
assert jobs_module._job_task_size(remote) == 0
assert jobs_module._job_task_size(local) == 2048
reader.get_directory_size.assert_called_once_with(Path("/downloads"))
def test_job_task_size_requires_reader_for_missing_local_size(monkeypatch) -> None:
"""
本地工作项缺失 size 且端口未装配时必须明确失败。
"""
monkeypatch.setattr(jobs_module, "_directory_size", None)
local = SimpleNamespace(
fileitem=SimpleNamespace(size=None, storage="local", path="/downloads"),
)
with pytest.raises(RuntimeError, match="本地目录大小能力尚未由启动组合根配置"):
jobs_module._job_task_size(local)
def test_domain_composition_injects_all_system_acceleration_ports(monkeypatch) -> None:
"""
领域组合根必须显式注入拓扑、规则解析和目录大小三个端口。
"""
disk = MagicMock()
parser = MagicMock()
size = MagicMock()
monkeypatch.setattr(domain_composition, "configure_disk_topology", disk)
monkeypatch.setattr(domain_composition, "configure_filter_rule_parser", parser)
monkeypatch.setattr(domain_composition, "configure_directory_size", size)
for name in (
"configure_dns_resolver",
"configure_customization_provider",
"configure_release_groups_provider",
"configure_custom_words_provider",
"configure_search_source_provider",
"configure_recognition_runtime",
"clear_rust_parse_options_cache",
):
monkeypatch.setattr(domain_composition, name, MagicMock())
monkeypatch.setattr(
"app.domain.projection.tmdb.configure_image_url_builder",
MagicMock(),
)
monkeypatch.setattr(domain_composition, "RecognitionRuleService", MagicMock())
monkeypatch.setattr(
domain_composition,
"get_runtime_setting",
MagicMock(return_value=()),
)
domain_composition.compose_domain_dependencies()
disk.assert_called_once_with(domain_composition.SystemUtils)
parser.assert_called_once_with(domain_composition.rust_accelerator)
size.assert_called_once_with(domain_composition.SystemUtils)