mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-10-28 19:06:36 +08:00
82 lines
2.3 KiB
Python
82 lines
2.3 KiB
Python
"""
|
|
插件管理器异步方法的执行边界回归。
|
|
"""
|
|
|
|
from types import SimpleNamespace
|
|
from typing import Iterator
|
|
from unittest.mock import AsyncMock
|
|
|
|
import pytest
|
|
|
|
from app.foundation.singleton import Singleton
|
|
|
|
# 插件 SDK 在运行时动态导出管理器,此导入验证公开入口的异步合同。
|
|
from app.sdk.plugin import PluginManager # pylint: disable=no-name-in-module
|
|
|
|
|
|
@pytest.fixture
|
|
def plugin_manager() -> Iterator[PluginManager]:
|
|
"""
|
|
构造隔离的插件管理器实例。
|
|
"""
|
|
Singleton._instances.pop((PluginManager, (), frozenset()), None)
|
|
manager = PluginManager()
|
|
yield manager
|
|
Singleton._instances.pop((PluginManager, (), frozenset()), None)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_async_run_plugin_method_offloads_sync_plugin_method(
|
|
plugin_manager: PluginManager,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""
|
|
异步入口不得在事件循环内直接执行同步插件方法。
|
|
"""
|
|
calls: list[tuple[str, int]] = []
|
|
|
|
def sync_method(value: int) -> int:
|
|
calls.append(("sync", value))
|
|
return value + 1
|
|
|
|
plugin_manager.running_plugins["DemoPlugin"] = SimpleNamespace(
|
|
sync_method=sync_method,
|
|
)
|
|
worker = AsyncMock(return_value=2)
|
|
monkeypatch.setattr(
|
|
"app.runtime.extensions.plugin.manager.run_in_threadpool_to_completion",
|
|
worker,
|
|
)
|
|
|
|
assert await plugin_manager.async_run_plugin_method(
|
|
"DemoPlugin", "sync_method", 1
|
|
) == 2
|
|
worker.assert_awaited_once_with(sync_method, 1)
|
|
assert calls == []
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_async_run_plugin_method_keeps_async_plugin_method_on_loop(
|
|
plugin_manager: PluginManager,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""
|
|
原生协程插件方法继续直接等待,不额外占用同步 worker。
|
|
"""
|
|
async def async_method(value: int) -> int:
|
|
return value + 1
|
|
|
|
plugin_manager.running_plugins["DemoPlugin"] = SimpleNamespace(
|
|
async_method=async_method,
|
|
)
|
|
worker = AsyncMock()
|
|
monkeypatch.setattr(
|
|
"app.runtime.extensions.plugin.manager.run_in_threadpool_to_completion",
|
|
worker,
|
|
)
|
|
|
|
assert await plugin_manager.async_run_plugin_method(
|
|
"DemoPlugin", "async_method", 1
|
|
) == 2
|
|
worker.assert_not_awaited()
|