Files
PlantAI-rag-new/vstore/tests/test_backend.py
jerryandClaude Fable 5 5db3ead73e feat(docgen): doc_writer 能力全链——vstore 独立服务 + BFF docgen 路由 + 前端文档工作台
- vstore 独立安装包(8094):解析/嵌入/加密 vault/faiss 检索,存储路径支持本地 file 与 http(s):// URL,启动握手校验,集群化预留(embed 独立模块)
- BFF docgen 路由:上传入库/generate/编辑/导出/下载/主库管理,意图护栏(与前端同词典),vstore 失败兜底,quota 507 与 TTL 惰性清理
- 前端:自然触发意图路由、拖拽上传 chips、能力徽标、右侧文档 TAB(WYSIWYG 编辑/prompt 修改/PDF+DOCX 导出下载)、右栏拖宽+手柄仿左栏
- 批量导入工具 docgen_import.py(并发 8、导入即加密+删源明文)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-03 21:13:37 +08:00

83 lines
2.7 KiB
Python

"""test_backend.py —— 后端路径解析三形态 + 远程握手失败拒绝。"""
from __future__ import annotations
import httpx
import pytest
from vstore.backend import (
BackendError,
LocalBackend,
RemoteBackend,
handshake,
is_remote_spec,
parse_backend,
)
def test_parse_backend_bare_paths():
backend = parse_backend("/tmp/vault", "/tmp/index")
assert isinstance(backend, LocalBackend)
assert str(backend.vault_path) == "/tmp/vault"
def test_parse_backend_file_url():
backend = parse_backend("file:///tmp/vault", "file:///tmp/index")
assert isinstance(backend, LocalBackend)
assert str(backend.vault_path) == "/tmp/vault" # file:// 前缀剥掉
assert str(backend.index_path) == "/tmp/index"
def test_parse_backend_http_urls():
backend = parse_backend("http://h1:1/vault", "https://h2:2/index")
assert isinstance(backend, RemoteBackend)
assert backend.vault_url == "http://h1:1/vault"
assert backend.index_url == "https://h2:2/index"
def test_parse_backend_mixed_rejected():
with pytest.raises(BackendError):
parse_backend("/tmp/vault", "http://h:1/index")
def test_is_remote_spec():
assert is_remote_spec("http://x")
assert is_remote_spec("https://x")
assert not is_remote_spec("file:///x")
assert not is_remote_spec("/tmp/x")
assert not is_remote_spec("ftp://x") # 仅 http/https 视为远程
def test_local_handshake_ok(tmp_path):
backend = LocalBackend(str(tmp_path / "vault"), str(tmp_path / "index"))
handshake(backend) # 不抛
assert (tmp_path / "vault").exists()
def test_remote_health_ok(monkeypatch):
def fake_get(url, timeout=None):
assert url.endswith("/health")
return httpx.Response(200, json={"ok": True, "count": 0}, request=httpx.Request("GET", url))
monkeypatch.setattr("vstore.backend.httpx.get", fake_get)
backend = RemoteBackend("http://h:1/v", "http://h:2/i")
assert backend.health()["ok"] is True
def test_remote_handshake_failure_rejected(monkeypatch):
def fake_get(url, timeout=None):
raise httpx.ConnectError("down", request=None)
monkeypatch.setattr("vstore.backend.httpx.get", fake_get)
backend = RemoteBackend("http://h:1/v", "http://h:2/i")
with pytest.raises(BackendError):
handshake(backend)
def test_remote_search_empty_handshake(monkeypatch):
def fake_get(url, timeout=None, params=None):
return httpx.Response(200, json={"ok": True, "mode": "latest", "items": []}, request=httpx.Request("GET", url))
monkeypatch.setattr("vstore.backend.httpx.get", fake_get)
backend = RemoteBackend("http://h:1/v", "http://h:2/i")
assert backend.search_empty()["ok"] is True