Files
Nexus/tests/chain/test_agent_dashboard_flow.py
2026-07-08 22:31:31 +08:00

92 lines
2.7 KiB
Python

"""CH-AGT-001 — heartbeat → Redis → dashboard online count."""
from __future__ import annotations
from unittest.mock import AsyncMock
import pytest
from server.api.agent import receive_heartbeat
from server.api.dependencies import get_server_service
from server.api.schemas import AgentHeartbeat
from server.api.servers import server_stats
pytestmark = pytest.mark.chain
@pytest.mark.asyncio
async def test_heartbeat_then_stats_online_count(
db_session,
test_server,
test_admin,
mock_request,
monkeypatch,
):
api_key = "chain-agent-key"
test_server.agent_api_key = api_key
await db_session.commit()
stored: dict[str, dict] = {}
pipeline_keys: list[str] = []
async def fake_hset(key, mapping=None):
if mapping:
stored[key] = dict(mapping)
async def fake_scan(cursor, match=None, count=200):
keys = [k for k in stored if k.startswith("heartbeat:")]
return 0, keys
async def fake_hgetall(key):
return stored.get(key, {})
class FakePipeline:
def hgetall(self, key: str) -> None:
pipeline_keys.append(key)
async def execute(self):
keys = list(pipeline_keys)
pipeline_keys.clear()
return [stored.get(k, {}) for k in keys]
def fake_pipeline():
return FakePipeline()
mock_redis = AsyncMock()
mock_redis.hset = fake_hset
mock_redis.expire = AsyncMock()
mock_redis.get = AsyncMock(return_value=None)
mock_redis.smembers = AsyncMock(return_value=set())
mock_redis.sadd = AsyncMock()
mock_redis.srem = AsyncMock()
mock_redis.delete = AsyncMock()
mock_redis.incr = AsyncMock(return_value=1)
mock_redis.scan = fake_scan
mock_redis.hgetall = fake_hgetall
mock_redis.pipeline = fake_pipeline
monkeypatch.setattr("server.api.agent.get_redis", lambda: mock_redis)
monkeypatch.setattr("server.api.servers.get_redis", lambda: mock_redis)
monkeypatch.setattr("server.utils.alert_streak.broadcast_alert", AsyncMock())
monkeypatch.setattr("server.utils.alert_streak.broadcast_recovery", AsyncMock())
monkeypatch.setattr("server.api.agent.send_telegram_system_alert", AsyncMock())
mock_request.state.db = db_session
service = await get_server_service(mock_request)
hb = await receive_heartbeat(
AgentHeartbeat(
server_id=test_server.id,
is_online=True,
system_info={"cpu_usage": 10.0, "mem_usage": 20.0, "disk_usage": 30.0},
),
api_key=api_key,
service=service,
db=db_session,
)
assert hb["status"] == "ok"
stats = await server_stats(test_admin["admin"], db_session)
assert stats["online"] >= 1
assert stats["total"] >= 1