From 259662e9144348857f11c5196d61fc8ea24f3c64 Mon Sep 17 00:00:00 2001 From: Alexandre Teixeira <111787685+alteixeira20@users.noreply.github.com> Date: Sat, 27 Jun 2026 23:49:43 +0100 Subject: [PATCH] test: split endpoint resolver tests (#4957) --- tests/test_endpoint_resolver_headers.py | 16 ++++ tests/test_endpoint_resolver_models.py | 67 +++++++++++++++ ...lver.py => test_endpoint_resolver_urls.py} | 81 +------------------ 3 files changed, 84 insertions(+), 80 deletions(-) create mode 100644 tests/test_endpoint_resolver_headers.py create mode 100644 tests/test_endpoint_resolver_models.py rename tests/{test_endpoint_resolver.py => test_endpoint_resolver_urls.py} (53%) diff --git a/tests/test_endpoint_resolver_headers.py b/tests/test_endpoint_resolver_headers.py new file mode 100644 index 000000000..a2ac5429d --- /dev/null +++ b/tests/test_endpoint_resolver_headers.py @@ -0,0 +1,16 @@ +"""Tests for endpoint_resolver — request header construction.""" +from src.endpoint_resolver import build_headers + + +class TestBuildHeaders: + def test_no_key(self): + assert build_headers(None, "https://api.openai.com/v1") == {} + + def test_openai_bearer(self): + assert build_headers("sk-abc", "https://api.openai.com/v1") == {"Authorization": "Bearer sk-abc"} + + def test_anthropic_headers(self): + assert build_headers("sk-ant-abc", "https://api.anthropic.com") == {"x-api-key": "sk-ant-abc", "anthropic-version": "2023-06-01"} + + def test_empty_key(self): + assert build_headers("", "https://api.openai.com/v1") == {} diff --git a/tests/test_endpoint_resolver_models.py b/tests/test_endpoint_resolver_models.py new file mode 100644 index 000000000..72cb6cd69 --- /dev/null +++ b/tests/test_endpoint_resolver_models.py @@ -0,0 +1,67 @@ +"""Tests for endpoint_resolver — endpoint/model selection and enabled-model filtering.""" +import json + +from src.endpoint_resolver import ( + _first_chat_model, + _endpoint_hidden_models, + _endpoint_enabled_models, +) + + +class _Ep: + """Minimal ModelEndpoint stand-in for the model-picking helpers.""" + def __init__(self, cached=None, hidden=None): + self.cached_models = json.dumps(cached) if cached is not None else None + self.hidden_models = json.dumps(hidden) if hidden is not None else None + + +class TestFirstChatModel: + def test_skips_embedding_and_tts(self): + models = ["text-embedding-ada-002", "whisper-large-v3", "gpt-4o"] + assert _first_chat_model(models) == "gpt-4o" + + def test_falls_back_to_first_when_all_non_chat(self): + assert _first_chat_model(["whisper-large-v3"]) == "whisper-large-v3" + + def test_empty(self): + assert _first_chat_model([]) is None + + +class TestEnabledModels: + def test_excludes_hidden(self): + # The Groq repro: 16 models, only gpt-oss-120b enabled. + cached = [ + "openai/gpt-oss-safeguard-20b", "canopylabs/orpheus-arabic-saudi", + "whisper-large-v3", "openai/gpt-oss-120b", + ] + hidden = [ + "openai/gpt-oss-safeguard-20b", "canopylabs/orpheus-arabic-saudi", + "whisper-large-v3", + ] + ep = _Ep(cached=cached, hidden=hidden) + assert _endpoint_enabled_models(ep) == ["openai/gpt-oss-120b"] + + def test_no_hidden_returns_all(self): + ep = _Ep(cached=["a", "b"], hidden=None) + assert _endpoint_enabled_models(ep) == ["a", "b"] + + def test_picker_never_selects_disabled_model(self): + # Regression: a disabled model listed first must not be auto-picked. + cached = ["canopylabs/orpheus-arabic-saudi", "openai/gpt-oss-120b"] + hidden = ["canopylabs/orpheus-arabic-saudi"] + ep = _Ep(cached=cached, hidden=hidden) + assert _first_chat_model(_endpoint_enabled_models(ep)) == "openai/gpt-oss-120b" + + def test_stale_configured_model_is_discarded(self): + # A configured model that's been disabled is dropped, falling through + # to the first enabled chat model. + ep = _Ep( + cached=["canopylabs/orpheus-arabic-saudi", "openai/gpt-oss-120b"], + hidden=["canopylabs/orpheus-arabic-saudi"], + ) + configured = "canopylabs/orpheus-arabic-saudi" + if configured in _endpoint_hidden_models(ep): + configured = "" + if not configured: + configured = _first_chat_model(_endpoint_enabled_models(ep)) + assert configured == "openai/gpt-oss-120b" diff --git a/tests/test_endpoint_resolver.py b/tests/test_endpoint_resolver_urls.py similarity index 53% rename from tests/test_endpoint_resolver.py rename to tests/test_endpoint_resolver_urls.py index 606f23151..fb7105577 100644 --- a/tests/test_endpoint_resolver.py +++ b/tests/test_endpoint_resolver_urls.py @@ -1,16 +1,10 @@ -"""Tests for endpoint_resolver — pure functions tested directly.""" -import json - +"""Tests for endpoint_resolver — URL normalization and URL construction.""" import pytest from src.endpoint_resolver import ( - _first_chat_model, - _endpoint_hidden_models, - _endpoint_enabled_models, normalize_base, build_chat_url, build_models_url, - build_headers, ) @@ -99,76 +93,3 @@ class TestBuildModelsUrl: def test_rejects_query_or_fragment_base(self, bad_base): with pytest.raises(ValueError, match="query or fragment"): build_models_url(bad_base) - - -class TestBuildHeaders: - def test_no_key(self): - assert build_headers(None, "https://api.openai.com/v1") == {} - - def test_openai_bearer(self): - assert build_headers("sk-abc", "https://api.openai.com/v1") == {"Authorization": "Bearer sk-abc"} - - def test_anthropic_headers(self): - assert build_headers("sk-ant-abc", "https://api.anthropic.com") == {"x-api-key": "sk-ant-abc", "anthropic-version": "2023-06-01"} - - def test_empty_key(self): - assert build_headers("", "https://api.openai.com/v1") == {} - - -class _Ep: - """Minimal ModelEndpoint stand-in for the model-picking helpers.""" - def __init__(self, cached=None, hidden=None): - self.cached_models = json.dumps(cached) if cached is not None else None - self.hidden_models = json.dumps(hidden) if hidden is not None else None - - -class TestFirstChatModel: - def test_skips_embedding_and_tts(self): - models = ["text-embedding-ada-002", "whisper-large-v3", "gpt-4o"] - assert _first_chat_model(models) == "gpt-4o" - - def test_falls_back_to_first_when_all_non_chat(self): - assert _first_chat_model(["whisper-large-v3"]) == "whisper-large-v3" - - def test_empty(self): - assert _first_chat_model([]) is None - - -class TestEnabledModels: - def test_excludes_hidden(self): - # The Groq repro: 16 models, only gpt-oss-120b enabled. - cached = [ - "openai/gpt-oss-safeguard-20b", "canopylabs/orpheus-arabic-saudi", - "whisper-large-v3", "openai/gpt-oss-120b", - ] - hidden = [ - "openai/gpt-oss-safeguard-20b", "canopylabs/orpheus-arabic-saudi", - "whisper-large-v3", - ] - ep = _Ep(cached=cached, hidden=hidden) - assert _endpoint_enabled_models(ep) == ["openai/gpt-oss-120b"] - - def test_no_hidden_returns_all(self): - ep = _Ep(cached=["a", "b"], hidden=None) - assert _endpoint_enabled_models(ep) == ["a", "b"] - - def test_picker_never_selects_disabled_model(self): - # Regression: a disabled model listed first must not be auto-picked. - cached = ["canopylabs/orpheus-arabic-saudi", "openai/gpt-oss-120b"] - hidden = ["canopylabs/orpheus-arabic-saudi"] - ep = _Ep(cached=cached, hidden=hidden) - assert _first_chat_model(_endpoint_enabled_models(ep)) == "openai/gpt-oss-120b" - - def test_stale_configured_model_is_discarded(self): - # A configured model that's been disabled is dropped, falling through - # to the first enabled chat model. - ep = _Ep( - cached=["canopylabs/orpheus-arabic-saudi", "openai/gpt-oss-120b"], - hidden=["canopylabs/orpheus-arabic-saudi"], - ) - configured = "canopylabs/orpheus-arabic-saudi" - if configured in _endpoint_hidden_models(ep): - configured = "" - if not configured: - configured = _first_chat_model(_endpoint_enabled_models(ep)) - assert configured == "openai/gpt-oss-120b"