Files
ewoooc/tests/test_event_router.py
OoO 1c2dc6cd61
All checks were successful
CD Pipeline / deploy (push) Successful in 1m14s
補強 AI 自動化閉環與安全降級
2026-04-29 22:56:00 +08:00

88 lines
2.9 KiB
Python

import asyncio
import json
def test_dispatch_degrades_and_queues_when_ai_or_telegram_fails(tmp_path, monkeypatch):
import services.event_router as event_router
queue_path = tmp_path / "event_router_failed.jsonl"
monkeypatch.setattr(event_router, "_QUEUE_PATH", str(queue_path))
monkeypatch.setattr(event_router, "_is_event_silenced", lambda event: False)
async def broken_l1(event, session_id):
raise RuntimeError("hermes unavailable")
monkeypatch.setattr(event_router, "_handle_l1", broken_l1)
monkeypatch.setattr(
event_router,
"send_telegram_with_result",
lambda *args, **kwargs: {
"ok": False,
"sent": 0,
"failed": 1,
"chat_ids": [123],
"errors": ["123:HTTP 500"],
},
)
result = asyncio.run(event_router.dispatch({
"source": "Scheduler.Test",
"event_type": "crawler_timeout",
"severity": "warning",
"title": "測試任務異常",
"summary": "timeout",
"trace": "Traceback...",
}))
assert result["tier"] == "L1"
assert result["delivered"] is False
assert result["queued"] is True
assert result["payload"]["status"] == "degraded"
queued = json.loads(queue_path.read_text(encoding="utf-8").strip())
assert queued["reason"] == "telegram_delivery_failed"
assert queued["event_key"] == "Scheduler.Test:crawler_timeout"
def test_dispatch_executes_only_auto_safe_actions(monkeypatch):
import services.agent_actions as agent_actions
import services.event_router as event_router
calls = []
monkeypatch.setattr(event_router, "_is_event_silenced", lambda event: False)
monkeypatch.setitem(
agent_actions.SAFE_ACTIONS,
"retry_task",
lambda **params: calls.append(params) or {"status": "scheduled"},
)
async def planned_l2(event, session_id):
return {
"dispatch_to": "safe_action",
"auto_execute": True,
"action_plan": [
{"action": "retry_task", "params": {"task_name": "run_momo_task"}},
{"action": "restart_container", "params": {"container": "momo-db"}},
],
}
monkeypatch.setattr(event_router, "_handle_l2", planned_l2)
monkeypatch.setattr(
event_router,
"send_telegram_with_result",
lambda *args, **kwargs: {"ok": True, "sent": 1, "failed": 0, "chat_ids": [123], "errors": []},
)
result = asyncio.run(event_router.dispatch({
"source": "Scheduler.MOMO",
"event_type": "scheduler_task_failure",
"severity": "alert",
"title": "MOMO 任務異常",
"summary": "boom",
"payload": {"task_name": "run_momo_task"},
}))
assert result["tier"] == "L2"
assert calls == [{"task_name": "run_momo_task"}]
assert result["payload"]["executed_actions"][0]["status"] == "ok"
assert result["payload"]["executed_actions"][1]["status"] == "rejected"