From f9b357b9d7b7c5e4282806c50a63422d085c6a1a Mon Sep 17 00:00:00 2001 From: iomgaa Date: Sat, 5 Sep 2026 06:54:40 -0400 Subject: [PATCH] test: give two silent guards something to fail on again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `test_extra_body_overrides_the_profile_slot` guards that a source's `extra_body` wins over the slot the profile injects. Since T5 made `enable_thinking=True` mean `auto`, its minimax fixture injected an empty fragment — swapping the two update calls changed nothing and the whole suite stayed green, while a real source (zhipu, glm-5.3, tier `low`) would have shipped `low` instead of the `high` the caller wrote. Move the fixture onto that combination, where the two sides write the same key. `emit_attempt`'s docstring promises `reasoning_applies` carries no default so that a missed argument is a TypeError rather than a silent `True`; nothing enforced it. Pin the signature the way `record_llm_call` is already pinned. --- tests/unit/test_openai_compat.py | 19 ++++++++++++++----- tests/unit/test_telemetry.py | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/tests/unit/test_openai_compat.py b/tests/unit/test_openai_compat.py index 3d2c525..e882c05 100644 --- a/tests/unit/test_openai_compat.py +++ b/tests/unit/test_openai_compat.py @@ -747,7 +747,13 @@ class TestRequestShaping: assert "enable_thinking" not in seen # 旧形态实测被静默丢弃,不再下发 async def test_extra_body_overrides_the_profile_slot(self): - """注入顺序即优先级: profile → extra_body → overlay,两行不可调换。""" + """注入顺序即优先级: profile → extra_body → overlay,两行不可调换。 + + 固定用 **zhipu + glm-5.3 + 源级 low** 这组: 判据必须落在一个 profile + **真的写了值**的键上,两边写同一个键才谈得上谁覆盖谁。用 minimax + + `enable_thinking=True` 是测不出来的——T5 起 `True ≡ auto`,而 auto 的注入 + 片段就是 minimax 的 `on_base`(空字典),两行怎么调换结果都一样,断言恒真。 + """ seen = {} def handler(request): @@ -755,14 +761,17 @@ class TestRequestShaping: return _sse_stream(_chunk(content="x"), _chunk(usage=_USAGE)) source = _source( - name="mm", - provider="minimax", - model="MiniMax-M3", - enable_thinking=True, + name="zp", + provider="zhipu", + model="glm-5.3", + reasoning_effort="low", extra_body={"reasoning_effort": "high"}, ) await _complete(_transport_for(handler), source) + # profile 注入的是 low,extra_body 后写故发出去的是 high;顺序一调换就变 low, + # 即下游写在 extra_body 里的覆盖被库悄悄顶掉(issue #20 的成因形态) assert seen["reasoning_effort"] == "high" + assert seen["thinking"] == {"type": "enabled"} # profile 独有的那半边仍在 async def test_model_that_cannot_disable_is_rejected_not_silently_ignored(self): """M2.x 关不掉推理: 必须是四分类之一的 RequestRejected,不是裸 ValueError。 diff --git a/tests/unit/test_telemetry.py b/tests/unit/test_telemetry.py index f9b4867..693db6f 100644 --- a/tests/unit/test_telemetry.py +++ b/tests/unit/test_telemetry.py @@ -1421,6 +1421,21 @@ class TestEmitterReasoningEffort: ) assert rec.rows[0]["reasoning_effort"] is None + def test_reasoning_applies_has_no_default(self): + """上一条测的是"传了 False 会怎样",这条测的是"**漏传**会怎样"。 + + `reasoning_applies` 的约定是不设默认值(与 `TelemetryRecorder` 同款):库外 + 无第三方调用者,写全签名成本为零,而默认 `True` 会让将来新增的第四条 emit + 路径(又一个非推理客户端)漏传时静默落进 chat 口径——一次 embedding 失败被 + 挂上源上误配的 `auto` 档,正是上一条测试要防的形态,却绕过了它的断言。 + 约定只写在 docstring 里是没有执法点的,故在此以 `inspect.signature` 实测。 + """ + import inspect + + param = inspect.signature(TelemetryEmitter.emit_attempt).parameters["reasoning_applies"] + assert param.default is inspect.Parameter.empty + assert param.kind is inspect.Parameter.KEYWORD_ONLY + async def test_an_out_of_domain_tier_degrades_but_keeps_the_row(self): """域外取值降级为 `NULL` 且**不丢整行**(遥测必录);与缓存回放同一方向。