693cd952cd
仓库首次入库(此前仅存在于本地工作区与测试服构建产物中,未上传)。 改动(src/knowledge_adapter/asset_content_processor.py): - 新增 _TRUNCATED_TRAILING_MARKDOWN_RESOURCE_IMAGE 规则,清除 chunk 末尾被截断的  - 回归测试 tests/test_asset_content_processor.py:: test_truncated_trailing_markdown_resource_image_is_removed 验证证据: - 测试服 120.76.217.51,镜像 knowledge-adapter-service:reviewed-test-aeab4b5fca2d (release aeab4b5fca2d8661):KB d015d05c-25c8-4d63-b2ab-e8590d3c2dfb 5 个查询全部 http=200、records=5、残留 resource:// = 0;KB b9dacd62 无退化;容器日志无 error/exception - 本地:pytest 141 项全通过、ruff 全通过 - 该文件与 258c31e0fe07fd08 源码的差异经逐文件 md5 比对,为唯一变更文件
114 lines
3.7 KiB
Python
114 lines
3.7 KiB
Python
from uuid import UUID
|
|
|
|
import httpx
|
|
import pytest
|
|
from pydantic import SecretStr
|
|
|
|
from knowledge_adapter.weknora_client import (
|
|
WeKnoraBadResponseError,
|
|
WeKnoraClient,
|
|
WeKnoraUnavailableError,
|
|
)
|
|
|
|
KB_ID = UUID("3904b40e-278b-4273-a6fa-db6cbc975587")
|
|
WEKNORA_KEY = "test-weknora-key"
|
|
|
|
|
|
async def test_search_uses_only_readonly_endpoint_and_expected_contract() -> None:
|
|
requests: list[httpx.Request] = []
|
|
|
|
def handler(request: httpx.Request) -> httpx.Response:
|
|
requests.append(request)
|
|
return httpx.Response(200, json={"success": True, "data": []})
|
|
|
|
client = WeKnoraClient(
|
|
base_url="http://weknora.internal:8080",
|
|
api_key=SecretStr(WEKNORA_KEY),
|
|
timeout_seconds=15,
|
|
transport=httpx.MockTransport(handler),
|
|
)
|
|
async with client:
|
|
results = await client.search(query="normalized query", knowledge_base_id=KB_ID)
|
|
|
|
assert results == []
|
|
assert len(requests) == 1
|
|
request = requests[0]
|
|
assert request.method == "POST"
|
|
assert request.url.path == "/api/v1/knowledge-search"
|
|
assert request.headers["X-API-Key"] == WEKNORA_KEY
|
|
assert request.headers.get("Authorization") is None
|
|
assert request.read().decode() == (
|
|
'{"query":"normalized query",'
|
|
'"knowledge_base_ids":["3904b40e-278b-4273-a6fa-db6cbc975587"]}'
|
|
)
|
|
|
|
|
|
async def test_timeout_becomes_sanitized_unavailable_error() -> None:
|
|
def handler(request: httpx.Request) -> httpx.Response:
|
|
raise httpx.ReadTimeout("internal timeout details", request=request)
|
|
|
|
client = WeKnoraClient(
|
|
base_url="http://weknora.internal:8080",
|
|
api_key=SecretStr(WEKNORA_KEY),
|
|
timeout_seconds=15,
|
|
transport=httpx.MockTransport(handler),
|
|
)
|
|
|
|
with pytest.raises(WeKnoraUnavailableError) as captured:
|
|
async with client:
|
|
await client.search(query="sensitive query", knowledge_base_id=KB_ID)
|
|
|
|
assert str(captured.value) == "WeKnora unavailable"
|
|
|
|
|
|
async def test_500_becomes_sanitized_bad_response_error() -> None:
|
|
def handler(_request: httpx.Request) -> httpx.Response:
|
|
return httpx.Response(500, text="sensitive upstream failure")
|
|
|
|
client = WeKnoraClient(
|
|
base_url="http://weknora.internal:8080",
|
|
api_key=SecretStr(WEKNORA_KEY),
|
|
timeout_seconds=15,
|
|
transport=httpx.MockTransport(handler),
|
|
)
|
|
|
|
with pytest.raises(WeKnoraBadResponseError) as captured:
|
|
async with client:
|
|
await client.search(query="sensitive query", knowledge_base_id=KB_ID)
|
|
|
|
assert str(captured.value) == "invalid WeKnora response"
|
|
|
|
|
|
async def test_non_json_200_becomes_sanitized_bad_response_error() -> None:
|
|
def handler(_request: httpx.Request) -> httpx.Response:
|
|
return httpx.Response(200, text="not-json sensitive body")
|
|
|
|
client = WeKnoraClient(
|
|
base_url="http://weknora.internal:8080",
|
|
api_key=SecretStr(WEKNORA_KEY),
|
|
timeout_seconds=15,
|
|
transport=httpx.MockTransport(handler),
|
|
)
|
|
|
|
with pytest.raises(WeKnoraBadResponseError) as captured:
|
|
async with client:
|
|
await client.search(query="sensitive query", knowledge_base_id=KB_ID)
|
|
|
|
assert str(captured.value) == "invalid WeKnora response"
|
|
|
|
|
|
async def test_success_false_becomes_bad_response_error() -> None:
|
|
def handler(_request: httpx.Request) -> httpx.Response:
|
|
return httpx.Response(200, json={"success": False, "data": []})
|
|
|
|
client = WeKnoraClient(
|
|
base_url="http://weknora.internal:8080",
|
|
api_key=SecretStr(WEKNORA_KEY),
|
|
timeout_seconds=15,
|
|
transport=httpx.MockTransport(handler),
|
|
)
|
|
|
|
with pytest.raises(WeKnoraBadResponseError):
|
|
async with client:
|
|
await client.search(query="query", knowledge_base_id=KB_ID)
|