ADK-gateway/backend/tests/test_api.py
2026-08-05 16:33:27 +08:00

115 lines
3.8 KiB
Python

"""接口集成测试。"""
import fakeredis.aioredis
import pytest
import pytest_asyncio
from httpx import ASGITransport, AsyncClient
from app.config import settings
from app.main import app
AUTH = settings.gateway_auth
ADMIN_AUTH = settings.admin_auth
@pytest_asyncio.fixture
async def client():
server = fakeredis.FakeServer()
redis = fakeredis.aioredis.FakeRedis(server=server, decode_responses=True)
app.state.redis = redis
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as c:
yield c
await redis.aclose()
@pytest.mark.asyncio
async def test_health(client):
r = await client.get("/health")
assert r.status_code == 200
assert r.json()["status"] == "ok"
@pytest.mark.asyncio
async def test_submit_and_query_task(client):
r = await client.post("/api/cli/tasks", json={"auth": AUTH, "task_type": "compile", "task_tags": ["build"]})
assert r.status_code == 200
data = r.json()
assert data["status"] == "pending"
rid = data["request_id"]
r2 = await client.get(f"/api/cli/tasks/{rid}", params={"auth": AUTH})
assert r2.status_code == 200
assert r2.json()["request_id"] == rid
@pytest.mark.asyncio
async def test_agent_register_heartbeat_result(client):
# 注册
r = await client.post("/api/agent/register", json={"auth": AUTH, "agent_id": "a1", "endpoint": "e1", "agent_tags": ["compile"], "max_concurrent": 2})
assert r.status_code == 200
# 心跳
r = await client.post("/api/agent/heartbeat", json={"auth": AUTH, "agent_id": "a1", "current_load": 0})
assert r.status_code == 200
# 提交任务并等待调度(手动触发一次调度)
r = await client.post("/api/cli/tasks", json={"auth": AUTH, "task_type": "compile", "task_tags": ["compile"]})
rid = r.json()["request_id"]
from app.services.scheduler import Scheduler
await Scheduler(app.state.redis).dispatch_pending(10)
# 回传结果
r = await client.post("/api/agent/result", json={"auth": AUTH, "request_id": rid, "agent_id": "a1", "status": "success", "progress": 100, "result": {"ok": True}})
assert r.status_code == 200
detail = await client.get(f"/api/cli/tasks/{rid}", params={"auth": AUTH})
assert detail.json()["status"] == "success"
@pytest.mark.asyncio
async def test_admin_overview(client):
r = await client.get("/api/admin/overview", headers={"X-Admin-Auth": ADMIN_AUTH})
assert r.status_code == 200
assert "task_total" in r.json()
@pytest.mark.asyncio
async def test_admin_rejects_bad_auth(client):
r = await client.get("/api/admin/overview", headers={"X-Admin-Auth": "wrong-admin"})
assert r.status_code == 401
@pytest.mark.asyncio
async def test_admin_requires_auth(client):
r = await client.get("/api/admin/overview")
assert r.status_code == 422 # 缺 X-Admin-Auth header
@pytest.mark.asyncio
async def test_agent_heartbeat_rejects_bad_auth(client):
r = await client.post("/api/agent/heartbeat", json={"auth": "wrong", "agent_id": "x1", "current_load": 0})
assert r.status_code == 401
@pytest.mark.asyncio
async def test_cli_query_rejects_bad_auth(client):
r = await client.get("/api/cli/tasks/whatever", params={"auth": "wrong"})
assert r.status_code == 401
@pytest.mark.asyncio
async def test_submit_task_rejects_bad_auth(client):
r = await client.post("/api/cli/tasks", json={"auth": "wrong-password", "task_type": "compile"})
assert r.status_code == 401
@pytest.mark.asyncio
async def test_submit_task_requires_auth(client):
r = await client.post("/api/cli/tasks", json={"task_type": "compile"})
assert r.status_code == 422 # 缺 auth 字段
@pytest.mark.asyncio
async def test_agent_register_rejects_bad_auth(client):
r = await client.post("/api/agent/register", json={"auth": "wrong-password", "agent_id": "a9", "endpoint": "e9"})
assert r.status_code == 401