141 lines
4.2 KiB
Python
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",
|
|
]
|