Files
2026-07-13 13:12:33 +08:00

78 lines
2.2 KiB
Python

"""ChannelManager lifecycle diagnostics."""
from __future__ import annotations
import pytest
from opensquilla.channels.manager import ChannelManager
class _FailingChannel:
async def start(self) -> None:
raise RuntimeError("Feishu adapter dependency missing — reinstall OpenSquilla")
class _SlowChannel:
startup_timeout_s = 0.001
stopped = False
async def start(self) -> None:
await __import__("asyncio").sleep(0.05)
async def stop(self) -> None:
self.stopped = True
class _StructuredAuthError(RuntimeError):
diagnostic = {
"error_class": "auth_invalid",
"provider_code": "authFailed",
"message": "凭证无效:检查 DingTalk AppKey/AppSecret",
"retryable": False,
}
class _StructuredFailingChannel:
async def start(self) -> None:
raise _StructuredAuthError("DingTalk credentials were rejected")
@pytest.mark.asyncio
async def test_start_all_retains_start_exception_details():
manager = ChannelManager({"feishu": _FailingChannel()}, None, None)
results = await manager.start_all()
assert results == {"feishu": False}
assert manager.start_errors()["feishu"] == {
"error_type": "RuntimeError",
"error": "Feishu adapter dependency missing — reinstall OpenSquilla",
"exception": (
"RuntimeError('Feishu adapter dependency missing — reinstall OpenSquilla')"
),
}
@pytest.mark.asyncio
async def test_start_all_honors_adapter_startup_timeout():
channel = _SlowChannel()
manager = ChannelManager({"feishu": channel}, None, None)
results = await manager.start_all()
assert results == {"feishu": False}
assert manager.start_errors()["feishu"]["error_type"] == "TimeoutError"
assert channel.stopped is True
@pytest.mark.asyncio
async def test_start_all_retains_structured_channel_diagnostic():
manager = ChannelManager({"dingtalk": _StructuredFailingChannel()}, None, None)
results = await manager.start_all()
assert results == {"dingtalk": False}
error = manager.start_errors()["dingtalk"]
assert error["diagnostic"] == _StructuredAuthError.diagnostic
assert "AppKey/AppSecret" in error["diagnostic"]["message"]