Files
Aether/tests/api/public/test_system_catalog_rust.py
fawney19 ddf18fed9a feat: 扩展 Rust gateway 全功能模块,新增 billing/crypto/wallet crate 及完整数据层
- 新增 aether-billing、aether-crypto、aether-wallet 独立 crate
- aether-data 扩展 repository 层:announcements、auth_modules、billing、
  candidate_selection、gemini_file_mappings、global_models、management_tokens、
  oauth_providers、proxy_nodes、quota、users、wallet 等模块
- aether-gateway 新增 api/auth/billing/control/middleware/scheduler/usage/
  video_tasks/hooks/maintenance/model_fetch/provider_transport 等功能模块
- 重构 executor decision 和 gateway state 为模块目录结构
- 新增 gateway router、frontdoor 路由层及对应测试
- Python 侧 API 路由重构,新增 compat/support 模块
- 前端 Logo 组件更新及 Provider 管理页面调整
2026-03-31 19:19:04 +08:00

131 lines
4.2 KiB
Python

from __future__ import annotations
from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock
import httpx
import pytest
from fastapi import HTTPException
def _build_provider_fixture() -> SimpleNamespace:
endpoint = SimpleNamespace(
id="endpoint_1",
base_url="https://upstream.test",
api_format="openai:chat",
is_active=True,
)
key = SimpleNamespace(
id="key_1",
is_active=True,
api_formats=None,
)
return SimpleNamespace(
id="provider_1",
name="openai",
endpoints=[endpoint],
api_keys=[key],
)
@pytest.mark.asyncio
async def test_test_connection_prefers_rust_executor(
monkeypatch: pytest.MonkeyPatch,
) -> None:
from src.api.public import system_catalog as mod
provider = _build_provider_fixture()
monkeypatch.setattr(mod, "_select_provider", lambda _db, _provider_name: provider)
monkeypatch.setattr(mod, "build_test_request_body", lambda *_args, **_kwargs: {"model": "gpt-test"})
monkeypatch.setattr(mod, "get_provider_auth", AsyncMock(return_value=None))
class _DummyBuilder:
def build(self, *_args: object, **_kwargs: object) -> tuple[dict[str, str], dict[str, str]]:
return {"model": "gpt-test"}, {"authorization": "Bearer test"}
monkeypatch.setattr(mod, "PassthroughRequestBuilder", lambda: _DummyBuilder())
monkeypatch.setattr(
mod,
"build_provider_url",
lambda *_args, **_kwargs: "https://upstream.test/v1/chat/completions",
)
proxy_snapshot = object()
monkeypatch.setattr(
mod,
"_build_test_connection_transport_context",
AsyncMock(return_value=({"enabled": True}, {"node_id": "node-1", "tunnel": True}, proxy_snapshot)),
)
rust_response = httpx.Response(
200,
request=httpx.Request("POST", "https://upstream.test/v1/chat/completions"),
json={"id": "resp_rust"},
)
rust_call = AsyncMock(return_value=rust_response)
monkeypatch.setattr(mod, "_try_rust_test_connection_response", rust_call)
result = await mod._test_connection_response(
request=SimpleNamespace(query_params={}),
db=MagicMock(),
provider=None,
model="gpt-test",
api_format=None,
)
assert result["status"] == "success"
assert result["response_id"] == "resp_rust"
rust_call.assert_awaited_once()
@pytest.mark.asyncio
async def test_test_connection_returns_503_when_rust_unavailable(
monkeypatch: pytest.MonkeyPatch,
) -> None:
from src.api.public import system_catalog as mod
provider = _build_provider_fixture()
monkeypatch.setattr(mod, "_select_provider", lambda _db, _provider_name: provider)
monkeypatch.setattr(mod, "build_test_request_body", lambda *_args, **_kwargs: {"model": "gpt-test"})
monkeypatch.setattr(mod, "get_provider_auth", AsyncMock(return_value=None))
class _DummyBuilder:
def build(self, *_args: object, **_kwargs: object) -> tuple[dict[str, str], dict[str, str]]:
return {"model": "gpt-test"}, {"authorization": "Bearer test"}
monkeypatch.setattr(mod, "PassthroughRequestBuilder", lambda: _DummyBuilder())
monkeypatch.setattr(
mod,
"build_provider_url",
lambda *_args, **_kwargs: "https://upstream.test/v1/chat/completions",
)
monkeypatch.setattr(
mod,
"_build_test_connection_transport_context",
AsyncMock(return_value=({"enabled": True}, {"node_id": "node-1", "tunnel": True}, None)),
)
monkeypatch.setattr(
mod,
"_try_rust_test_connection_response",
AsyncMock(
side_effect=HTTPException(
status_code=503,
detail="System catalog test-connection requires Rust executor",
)
),
)
with pytest.raises(HTTPException) as exc_info:
await mod._test_connection_response(
request=SimpleNamespace(query_params={}),
db=MagicMock(),
provider=None,
model="gpt-test",
api_format=None,
)
assert exc_info.value.status_code == 503
assert exc_info.value.detail == "System catalog test-connection requires Rust executor"