ForcePilot/backend/test/unit/channel/infrastructure/plugin/test_loader.py

86 lines
2.5 KiB
Python
Raw Normal View History

from __future__ import annotations
import sys
import tempfile
from pathlib import Path
import pytest
from yuxi.channel.infrastructure.plugin.loader import PluginLoader
class FakeAdapterClass:
def __init__(self, **kwargs) -> None:
pass
async def open(self) -> None:
pass
async def close(self) -> None:
pass
@property
def capabilities(self):
return None
@classmethod
def get_default_config(cls) -> dict:
return {}
class TestPluginLoader:
@pytest.fixture
def loader(self):
return PluginLoader()
@pytest.mark.asyncio
async def test_load_module_by_path(self, loader):
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
f.write("class MyAdapter:\n")
f.write(" def __init__(self, **kwargs): pass\n")
f.write(" async def open(self): pass\n")
f.write(" async def close(self): pass\n")
f.write(" @property\n")
f.write(" def capabilities(self): return None\n")
f.write(" @classmethod\n")
f.write(" def get_default_config(cls): return {}\n")
path = f.name
try:
module = await loader.load(path)
assert module is not None
assert hasattr(module, "MyAdapter")
finally:
Path(path).unlink()
@pytest.mark.asyncio
async def test_load_existing_module(self, loader):
module = await loader.load("sys")
assert module is sys
def test_extract_adapter_class_found(self, loader):
module = type("Module", (), {"MyAdapter": FakeAdapterClass})()
result = loader.extract_adapter_class(module)
assert result is FakeAdapterClass
def test_extract_adapter_class_none(self, loader):
module = type("Module", (), {"foo": "bar"})()
result = loader.extract_adapter_class(module)
assert result is None
def test_extract_adapter_class_skips_private(self, loader):
class _PrivateAdapter(FakeAdapterClass):
pass
module = type("Module", (), {"_PrivateAdapter": _PrivateAdapter})()
result = loader.extract_adapter_class(module)
assert result is None
def test_extract_adapter_class_requires_methods(self, loader):
class Incomplete:
pass
module = type("Module", (), {"Incomplete": Incomplete})()
result = loader.extract_adapter_class(module)
assert result is None