test: pin the tier fallback and the assembly guard to real behaviour

Both were wired but unwitnessed: hardcoding the transport's fallback, or
blanking the source tier the assembly guard reads, left the whole unit
suite green. Cover them where the value is visible -- the bytes on the
wire for nearest-vs-error, and the assembly-time refusal that must name
low as the executable alternative.
This commit is contained in:
2026-09-05 04:21:32 -04:00
parent 81a901144e
commit 468af53f51
2 changed files with 55 additions and 0 deletions
+37
View File
@@ -12,6 +12,7 @@ from polygateway import (
AllSourcesExhausted,
GatewayClient,
GatewaySettings,
RequestRejectedError,
gather_bounded,
)
from polygateway.backends.memory.breaker import InMemoryGate
@@ -275,6 +276,42 @@ class TestReasoningEffortPriority:
assert "reasoning_effort" not in body
class TestEffortFallbackWiring:
"""源级 `effort_fallback` 必须真的走到 `resolve_thinking`(issue #20)。
只测配置值域与纯函数是不够的: 变异实测显示把 transport 里的
`fallback=source.effort_fallback` 换成硬编码 `"error"`,全套单测依然全绿——
`nearest` 是人类明确要求实现的功能,没有这条端到端用例它会在零告警下变成
死代码(2026-09-05 独立验证查出)。故断言看**发出去的字节**。
"""
def _capturing_client(self, captured, **overrides):
def handler(request):
captured.append(json.loads(request.content))
return _sse()
return _client(handler=handler, **overrides)
async def test_nearest_sends_the_mapped_tier(self):
"""glm-5.3 只有 low/high/max: 请求 `medium` 等距,按"取弱"落到 low。"""
captured = []
source = _source(provider="zhipu", model="glm-5.3", effort_fallback="nearest")
async with self._capturing_client(captured, sources=[source]) as client:
await client.chat([{"role": "user", "content": "hi"}], reasoning_effort=Effort.MEDIUM)
assert captured[0]["reasoning_effort"] == "low"
async def test_error_fallback_refuses_the_same_request(self):
"""默认 `error` 必须报错而不是映射: 一次静默的换档就是一笔没打招呼的账单。"""
captured = []
source = _source(provider="zhipu", model="glm-5.3")
async with self._capturing_client(captured, sources=[source]) as client:
with pytest.raises(RequestRejectedError, match="medium"):
await client.chat(
[{"role": "user", "content": "hi"}], reasoning_effort=Effort.MEDIUM
)
assert captured == [] # 请求根本没发出去
class TestRequestTierNormalization:
"""`chat(reasoning_effort=...)` 是公共入口,裸字符串必须在此归一(issue #20)。
+18
View File
@@ -758,6 +758,24 @@ class TestCrossFieldInvariants:
with pytest.raises(ValueError, match="register_provider"):
GatewayClient.from_settings(settings, registry=register_provider(mystery))
def test_source_tier_the_model_cannot_satisfy_fails_at_assembly(self):
"""守卫必须读**源级档位**,而不只是 `enable_thinking`(设计 §4.2 三层优先级)。
变异实测: 把 `_guard_thinking` 的 `source_effort=source.reasoning_effort`
改成 `None`,全套单测依然全绿(2026-09-05 独立验证查出)。文案里必须出现
可执行替代 `low`——glm-5.3 官方关不掉推理,只报"不行"会把人推回
`extra_body` 那条绕过治理的老路(issue #20 的成因)。
"""
base = self._base()
src = dataclasses.replace(
base.sources[0], provider="zhipu", model="glm-5.3", reasoning_effort=Effort.NONE
)
with pytest.raises(ValueError) as exc:
GatewayClient.from_settings(dataclasses.replace(base, sources=(src,)))
message = str(exc.value)
assert "glm-5.3" in message
assert "low" in message
def test_openai_segment_now_assembles_with_the_standard_field(self):
# 行为变更(2026-09-04): reasoning_effort 是 OpenAI 官方字段而非厂商方言,
# 经网关的兼容端点收得下,故兜底段不再把"关闭"判为形态未知