diff --git a/tests/integration/test_governance_stack.py b/tests/integration/test_governance_stack.py index 1b31d69..acffbcb 100644 --- a/tests/integration/test_governance_stack.py +++ b/tests/integration/test_governance_stack.py @@ -11,7 +11,12 @@ import sqlite3 import httpx import pytest -from polygateway import CircuitOpenError, GatewayClient, TransientError +from polygateway import ( + CircuitOpenError, + GatewayClient, + RequestRejectedError, + TransientError, +) from polygateway.backends.memory.breaker import InMemoryGate from polygateway.backends.memory.cache import InMemoryCache from polygateway.backends.memory.limiter import InMemoryLimiter @@ -173,6 +178,40 @@ class TestTelemetryAcrossPaths: assert len({cid for _, cid in rows}) == 2 # call_id 逐次独立 +class TestRejectionReasonIsQueryable: + """issue #10 的验收主张: 400 之后,网关说的话必须能在遥测表里查到。 + + 下游一轮 1050 张影像的批处理里,1 张在读表格时收到 400 被判确定性失败, + 事后"这张图到底哪里不合规"无从查起——响应体在 transport 翻译层就没了。 + """ + + # issue #10 原文给出的真实响应体(一字不改) + _BODY = ( + '{"error":{"message":"<400> ***.***.InvalidParameter: The image format is illegal ' + 'and cannot be opened","type":"invalid_request_error","param":"",' + '"code":"invalid_parameter_error"}}' + ) + + async def test_rejected_call_leaves_the_reason_in_telemetry(self, tmp_path): + recorder = SQLiteRecorder(tmp_path / "t.db") + client = _full_client( + lambda req: httpx.Response(400, content=self._BODY.encode()), telemetry=recorder + ) + + with pytest.raises(RequestRejectedError): + await client.chat([{"role": "user", "content": "hi"}]) + + recorder.close() + rows = sqlite3.connect(tmp_path / "t.db").execute("SELECT error FROM llm_calls").fetchall() + assert rows, "400 必须留下遥测行(遥测必录)" + errors = " ".join(r[0] or "" for r in rows) + # 修复前这里只有 "qwen_1 请求被拒: 400"——诊断信息一个字都不在 + assert "InvalidParameter" in errors + assert "The image format is illegal" in errors + # 尾部的 code 才是向网关方追查的凭据,头部硬切正好会丢掉它 + assert "invalid_parameter_error" in errors + + class TestStructuredThroughStack: async def test_feedback_reask_passes_through_governance(self): """重问经过内层治理: 第二次真实请求同样被限流/熔断记账。"""