Files
awoooi/apps/api/tests/test_openclaw_legacy_ollama_failover.py
Your Name 2ff0ef3bb6
Some checks failed
CD Pipeline / tests (push) Failing after 1m49s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
Code Review / ai-code-review (push) Successful in 24s
fix(openclaw): route legacy ollama through failover endpoints
2026-05-05 13:55:52 +08:00

141 lines
4.2 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from typing import Any
import httpx
import pytest
from src.services import openclaw as openclaw_module
from src.services.openclaw import OpenClawService
class _FakeRegistry:
def get_model(self, provider: str, use_case: str) -> str:
return "qwen2.5:7b-instruct"
def get_provider_options(self, provider: str) -> dict[str, Any]:
return {"num_predict": 32, "temperature": 0.1, "top_p": 0.9}
@dataclass
class _FakeEndpoint:
provider_name: str
url: str
class _FakeRoute:
def __init__(self, endpoints: list[_FakeEndpoint]) -> None:
self._endpoints = endpoints
def all_endpoints_in_order(self) -> list[_FakeEndpoint]:
return self._endpoints
class _FakeManager:
def __init__(self, endpoints: list[_FakeEndpoint]) -> None:
self._endpoints = endpoints
async def select_provider(self) -> _FakeRoute:
return _FakeRoute(self._endpoints)
class _FakeResponse:
status_code = 200
def raise_for_status(self) -> None:
return None
def json(self) -> dict[str, Any]:
return {"response": '{"action_title":"ok"}'}
class _FakeClient:
def __init__(self, fail_urls: set[str]) -> None:
self.fail_urls = fail_urls
self.posted_urls: list[str] = []
async def post(self, url: str, **kwargs: Any) -> _FakeResponse:
self.posted_urls.append(url)
if url in self.fail_urls:
raise httpx.ConnectError("offline")
return _FakeResponse()
@pytest.mark.asyncio
async def test_legacy_ollama_uses_failover_order_before_gemini(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(openclaw_module, "get_model_registry", lambda: _FakeRegistry())
monkeypatch.setattr(openclaw_module.settings, "OPENCLAW_TIMEOUT", 30)
monkeypatch.setattr(openclaw_module.settings, "OLLAMA_DIAGNOSE_TIMEOUT_SECONDS", 200)
monkeypatch.setattr(
openclaw_module,
"get_ollama_failover_manager",
lambda: _FakeManager(
[
_FakeEndpoint("ollama_gcp_a", "http://gcp-a:11435"),
_FakeEndpoint("ollama_gcp_b", "http://gcp-b:11436"),
_FakeEndpoint("ollama_local", "http://local-111:11434"),
_FakeEndpoint("gemini", ""),
],
),
)
client = _FakeClient(fail_urls={"http://gcp-a:11435/api/generate"})
service = object.__new__(OpenClawService)
async def _get_client() -> _FakeClient:
return client
monkeypatch.setattr(service, "_get_client", _get_client)
result, ok = await service._call_ollama("diagnose")
assert ok is True
assert result == '{"action_title":"ok"}'
assert client.posted_urls == [
"http://gcp-a:11435/api/generate",
"http://gcp-b:11436/api/generate",
]
@pytest.mark.asyncio
async def test_legacy_ollama_falls_back_to_configured_three_layer_urls(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(openclaw_module, "get_model_registry", lambda: _FakeRegistry())
monkeypatch.setattr(openclaw_module.settings, "OPENCLAW_TIMEOUT", 30)
monkeypatch.setattr(openclaw_module.settings, "OLLAMA_DIAGNOSE_TIMEOUT_SECONDS", 200)
monkeypatch.setattr(openclaw_module.settings, "OLLAMA_URL", "http://gcp-a:11435")
monkeypatch.setattr(openclaw_module.settings, "OLLAMA_SECONDARY_URL", "http://gcp-b:11436")
monkeypatch.setattr(openclaw_module.settings, "OLLAMA_FALLBACK_URL", "http://local-111:11434")
monkeypatch.setattr(
openclaw_module,
"get_ollama_failover_manager",
lambda: _FakeManager([_FakeEndpoint("gemini", "")]),
)
client = _FakeClient(
fail_urls={
"http://gcp-a:11435/api/generate",
"http://gcp-b:11436/api/generate",
},
)
service = object.__new__(OpenClawService)
async def _get_client() -> _FakeClient:
return client
monkeypatch.setattr(service, "_get_client", _get_client)
result, ok = await service._call_ollama("diagnose")
assert ok is True
assert result == '{"action_title":"ok"}'
assert client.posted_urls == [
"http://gcp-a:11435/api/generate",
"http://gcp-b:11436/api/generate",
"http://local-111:11434/api/generate",
]