Spaces:
Sleeping
Sleeping
| """ | |
| Tests for config/settings.py — model client routing logic. | |
| """ | |
| import pytest | |
| from unittest.mock import patch, MagicMock | |
| def _get_routing_fn(llm_mode: str): | |
| import importlib | |
| import sys | |
| with patch.dict("os.environ", {"LLM_MODE": llm_mode}): | |
| for key in list(sys.modules.keys()): | |
| if "config.settings" in key or key == "config.settings": | |
| del sys.modules[key] | |
| import config.settings as s | |
| importlib.reload(s) | |
| return s.get_model_client, s | |
| class TestModelClientRouting: | |
| def _mock_clients(self, settings_mod): | |
| cheap = MagicMock(name="cheap") | |
| reasoning = MagicMock(name="reasoning") | |
| analysis = MagicMock(name="analysis") | |
| local = MagicMock(name="local") | |
| settings_mod._cheap_client = lambda: cheap | |
| settings_mod._reasoning_client = lambda: reasoning | |
| settings_mod._analysis_client = lambda: analysis | |
| settings_mod._local_client = lambda: local | |
| return cheap, reasoning, analysis, local | |
| def test_cloud_data_uses_cheap(self): | |
| fn, mod = _get_routing_fn("cloud") | |
| cheap, reasoning, analysis, local = self._mock_clients(mod) | |
| result = fn("data") | |
| assert result is cheap | |
| def test_cloud_reasoning_uses_reasoning(self): | |
| fn, mod = _get_routing_fn("cloud") | |
| cheap, reasoning, analysis, local = self._mock_clients(mod) | |
| result = fn("reasoning") | |
| assert result is reasoning | |
| def test_cloud_analysis_uses_analysis(self): | |
| fn, mod = _get_routing_fn("cloud") | |
| cheap, reasoning, analysis, local = self._mock_clients(mod) | |
| result = fn("analysis") | |
| assert result is analysis | |
| def test_local_mode_all_tasks_use_local(self): | |
| fn, mod = _get_routing_fn("local") | |
| cheap, reasoning, analysis, local = self._mock_clients(mod) | |
| for task in ["data", "reasoning", "analysis"]: | |
| assert fn(task) is local, f"task={task} should use local in local mode" | |
| def test_hybrid_data_uses_local(self): | |
| fn, mod = _get_routing_fn("hybrid") | |
| cheap, reasoning, analysis, local = self._mock_clients(mod) | |
| assert fn("data") is local | |
| def test_hybrid_reasoning_uses_reasoning(self): | |
| fn, mod = _get_routing_fn("hybrid") | |
| cheap, reasoning, analysis, local = self._mock_clients(mod) | |
| assert fn("reasoning") is reasoning | |
| def test_hybrid_analysis_uses_analysis(self): | |
| fn, mod = _get_routing_fn("hybrid") | |
| cheap, reasoning, analysis, local = self._mock_clients(mod) | |
| assert fn("analysis") is analysis | |
| def test_unknown_task_defaults_to_analysis(self): | |
| fn, mod = _get_routing_fn("cloud") | |
| cheap, reasoning, analysis, local = self._mock_clients(mod) | |
| assert fn("unknown_task") is analysis | |
| class TestGroqClientFallback: | |
| """Ensure cheap/reasoning clients gracefully fall back when GROQ key absent.""" | |
| def test_cheap_client_falls_back_without_groq_key(self): | |
| with patch.dict("os.environ", {"GROQ_API_KEY": "", "LLM_MODE": "cloud"}): | |
| import importlib, sys | |
| for key in list(sys.modules.keys()): | |
| if "config.settings" in key: | |
| del sys.modules[key] | |
| import config.settings as s | |
| importlib.reload(s) | |
| # Should not raise — falls back to next provider | |
| # We just assert the function exists and returns something | |
| try: | |
| client = s._cheap_client() | |
| assert client is not None | |
| except Exception as e: | |
| # If no fallback keys set either, it's expected to fail downstream | |
| # but should not be a silent swallowed error | |
| assert "api_key" in str(e).lower() or "key" in str(e).lower() | |