项目文件夹

文件
2026-07-13 13:12:33 +08:00

315 行
11 KiB
Python

"""Router tier presets: config adapter parity, upgrade fixtures, downgrade guard.
The golden fixture (``tests/test_provider/golden/router_tier_profiles.json``)
was captured from
``git show staging/provider-overhaul:src/opensquilla/gateway/config.py``
(the ``_router_tier_profile_defaults`` dict literals at f884d4c9). Every test
here pins that moving the preset data into packaged TOML changed nothing about
how existing configs load: the fixture battery shapes come from the upgrade
audit and must keep loading byte-identically.
"""
from __future__ import annotations
import json
import tomllib
from pathlib import Path
import pytest
import tomli_w
from opensquilla.gateway.config import (
ROUTER_TIER_PROFILE_IDS,
GatewayConfig,
_default_tiers,
_router_tier_profile_defaults,
)
GOLDEN_PATH = (
Path(__file__).resolve().parents[1]
/ "test_provider"
/ "golden"
/ "router_tier_profiles.json"
)
LEGACY_NINE = frozenset(
{
"openrouter",
"dashscope",
"deepseek",
"gemini",
"volcengine",
"byteplus",
"openai",
"zhipu",
"moonshot",
}
)
UNKNOWN_PROFILE_ERROR = (
"unknown squilla_router.tier_profile 'groq'; expected one of "
"byteplus, dashscope, deepseek, gemini, moonshot, openai, openrouter, "
"volcengine, zhipu"
)
def _golden() -> dict[str, dict]:
return json.loads(GOLDEN_PATH.read_text(encoding="utf-8"))
# --- adapter parity ---------------------------------------------------------
def test_router_tier_profile_ids_are_exactly_the_legacy_nine() -> None:
assert ROUTER_TIER_PROFILE_IDS == LEGACY_NINE
@pytest.mark.parametrize("profile_id", sorted(LEGACY_NINE))
def test_profile_defaults_match_pre_registry_dict_literals(profile_id: str) -> None:
assert _router_tier_profile_defaults(profile_id) == _golden()[profile_id]
def test_default_tiers_match_pre_registry_openrouter_literal() -> None:
assert _default_tiers() == _golden()["openrouter"]
def test_profile_defaults_returns_mutable_copies() -> None:
first = _router_tier_profile_defaults("openai")
first["c0"]["model"] = "mutated"
assert _router_tier_profile_defaults("openai")["c0"]["model"] != "mutated"
def test_synthesized_preset_id_is_rejected_as_tier_profile() -> None:
# groq has a synthesized preset in the registry, but tier_profile
# acceptance stays pinned to the legacy nine (rc1 bricks on unknown ids).
with pytest.raises(ValueError) as excinfo:
_router_tier_profile_defaults("groq")
assert str(excinfo.value) == UNKNOWN_PROFILE_ERROR
# --- fixture battery (upgrade audit) ----------------------------------------
@pytest.mark.parametrize("profile_id", sorted(LEGACY_NINE))
def test_minimal_toml_per_profile_loads_identical_tiers(
tmp_path: Path, profile_id: str
) -> None:
"""(a) each legacy tier_profile in a minimal TOML -> today's effective tiers."""
path = tmp_path / "config.toml"
path.write_text(
f'[llm]\nprovider = "{profile_id}"\n\n'
f'[squilla_router]\ntier_profile = "{profile_id}"\n',
encoding="utf-8",
)
cfg = GatewayConfig.load_from_toml(path)
assert cfg.squilla_router.tier_profile == profile_id
assert cfg.squilla_router.tiers == _golden()[profile_id]
def test_mixed_tiers_without_profile_round_trip_untouched(tmp_path: Path) -> None:
"""(b) openrouter-mix shape: no tier_profile, explicit tiers stay verbatim."""
tiers = {
"c0": {
"provider": "openrouter",
"model": "vendor-a/fast-model",
"description": "custom fast route",
"supports_image": False,
"thinking_level": "low",
},
"c1": {
"provider": "openrouter",
"model": "vendor-b/balanced-model",
"description": "custom balanced route",
"supports_image": False,
"thinking_level": "medium",
},
"c2": {
"provider": "openrouter",
"model": "vendor-c/strong-model",
"description": "custom strong route",
"supports_image": False,
"thinking_level": "high",
},
"c3": {
"provider": "openrouter",
"model": "vendor-c/strong-model",
"description": "custom highest route",
"supports_image": False,
"thinking_level": "high",
},
"image_model": {
"provider": "openrouter",
"model": "vendor-d/vision-model",
"description": "custom image route",
"supports_image": True,
"image_only": True,
"thinking_level": "medium",
},
}
path = tmp_path / "config.toml"
path.write_text(
tomli_w.dumps(
{
"llm": {"provider": "openrouter"},
"squilla_router": {"enabled": True, "tiers": tiers},
}
),
encoding="utf-8",
)
cfg = GatewayConfig.load_from_toml(path)
assert cfg.squilla_router.tier_profile is None
assert cfg.squilla_router.tiers == tiers
dump = cfg.to_toml_dict()
router = dump["squilla_router"]
assert "tier_profile" not in router
assert router["tiers"] == tiers
# full round-trip: dump -> TOML -> load -> identical tiers
path2 = tmp_path / "roundtrip.toml"
path2.write_text(tomli_w.dumps(dump), encoding="utf-8")
cfg2 = GatewayConfig.load_from_toml(path2)
assert cfg2.squilla_router.tier_profile is None
assert cfg2.squilla_router.tiers == tiers
def test_rc1_desktop_legacy_tier_keys_merge_to_single_canonical(tmp_path: Path) -> None:
"""(c) rc1-desktop shape: t0-t3 keys + default_tier="t1" + tier_profile.
Legacy keys must normalize BEFORE the profile merge, producing a single
canonical c0-c3 key set with the overrides applied inside the matching
canonical tier (normalize-before-merge invariant).
"""
path = tmp_path / "config.toml"
path.write_text(
"\n".join(
[
"[llm]",
'provider = "deepseek"',
"",
"[squilla_router]",
'tier_profile = "deepseek"',
'default_tier = "t1"',
"",
"[squilla_router.tiers.t0]",
'model = "custom-fast-model"',
"",
"[squilla_router.tiers.t1]",
'model = "custom-balanced-model"',
"",
"[squilla_router.tiers.t2]",
'model = "custom-strong-model"',
'thinking_level = "high"',
"",
"[squilla_router.tiers.t3]",
'model = "custom-highest-model"',
"",
]
),
encoding="utf-8",
)
cfg = GatewayConfig.load_from_toml(path)
router = cfg.squilla_router
golden = _golden()["deepseek"]
assert router.default_tier == "c1"
assert sorted(router.tiers) == ["c0", "c1", "c2", "c3"] # single-key merge
assert router.tiers["c0"] == {**golden["c0"], "model": "custom-fast-model"}
assert router.tiers["c1"] == {**golden["c1"], "model": "custom-balanced-model"}
assert router.tiers["c2"] == {
**golden["c2"],
"model": "custom-strong-model",
"thinking_level": "high",
}
assert router.tiers["c3"] == {**golden["c3"], "model": "custom-highest-model"}
def test_unknown_tier_profile_rejected_with_same_error_shape(tmp_path: Path) -> None:
"""(d) unknown tier_profile "groq" -> same rejection message as today."""
path = tmp_path / "config.toml"
path.write_text(
'[llm]\nprovider = "groq"\n\n[squilla_router]\ntier_profile = "groq"\n',
encoding="utf-8",
)
with pytest.raises(Exception) as excinfo:
GatewayConfig.load_from_toml(path)
assert UNKNOWN_PROFILE_ERROR in str(excinfo.value)
def test_full_default_tree_round_trips_via_to_toml_dict(tmp_path: Path) -> None:
"""(e) full-default-tree (rc1 RPC-persisted shape) loads and round-trips."""
dump1 = GatewayConfig().to_toml_dict()
path = tmp_path / "config.toml"
path.write_text(tomli_w.dumps(dump1), encoding="utf-8")
payload = tomllib.loads(path.read_text(encoding="utf-8"))
cfg = GatewayConfig(**payload)
dump2 = cfg.to_toml_dict()
assert dump2 == dump1
# The default tree carries the curated tokenrhythm ladder (the built-in
# default provider ships packaged tier data but no persistable
# tier_profile, so its ladder is applied inline).
tiers = cfg.squilla_router.tiers
assert set(tiers) == {"c0", "c1", "c2", "c3", "image_model"}
expected_models = {
"c0": "deepseek-v4-flash",
"c1": "deepseek-v4-pro",
"c2": "kimi-k2.7-code",
"c3": "glm-5.2",
"image_model": "kimi-k2.6",
}
for name, tier in tiers.items():
assert tier["provider"] == "tokenrhythm"
assert tier["model"] == expected_models[name]
# --- H4: downgrade chokepoint at to_toml_dict --------------------------------
def test_to_toml_dict_expands_tiers_and_omits_non_legacy_tier_profile() -> None:
"""Non-legacy tier_profile never reaches disk: tiers expand, id is dropped.
Unreachable through validation today (non-legacy ids are rejected), so the
guard is exercised by corrupting the profile post-validation — exactly the
shape a future registry-wide consumer bug would produce.
"""
cfg = GatewayConfig(
llm={"provider": "deepseek"},
squilla_router={"tier_profile": "deepseek"},
)
effective_tiers = {name: dict(t) for name, t in cfg.squilla_router.tiers.items()}
object.__setattr__(cfg.squilla_router, "tier_profile", "groq")
router = cfg.to_toml_dict()["squilla_router"]
assert "tier_profile" not in router
assert router["tiers"] == effective_tiers
# the guarded dump must load on a legacy-nine-only validator (rc1 shape)
reloaded = GatewayConfig(llm={"provider": "deepseek"}, squilla_router=router)
assert reloaded.squilla_router.tier_profile is None
assert reloaded.squilla_router.tiers == effective_tiers
def test_to_toml_dict_still_collapses_legacy_profile_default_tiers() -> None:
"""Control: a legacy profile with default tiers keeps today's compact dump."""
cfg = GatewayConfig(
llm={"provider": "deepseek"},
squilla_router={"tier_profile": "deepseek"},
)
router = cfg.to_toml_dict()["squilla_router"]
assert router["tier_profile"] == "deepseek"
assert "tiers" not in router
def test_to_toml_dict_keeps_overridden_tiers_for_legacy_profile() -> None:
"""Control: profile + non-default tier override keeps both keys in the dump."""
cfg = GatewayConfig(
llm={"provider": "deepseek"},
squilla_router={
"tier_profile": "deepseek",
"tiers": {"c2": {"model": "custom-strong-model"}},
},
)
router = cfg.to_toml_dict()["squilla_router"]
assert router["tier_profile"] == "deepseek"
assert router["tiers"]["c2"]["model"] == "custom-strong-model"