Files
PlantAI-rag-new/vstore/tests/test_vault.py
jerryandClaude Fable 5 4749f77544 fix(docgen): 两批手工测试修复——上传/预览/检索 + 护栏/导出/命名/编辑还原/二次预览
第一批:上传去限制+进度展示、模板HTML预览+按需导出、检索TAB实时更新
第二批:edit护栏移除、导出按钮纯化+file_name落库、编辑失焦还原、
       二次预览白底根治(防竞态+渲染兜底)
模板体系:7套公文模板(templates/)+templating渲染器、websearch联网

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 15:49:54 +08:00

129 lines
4.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""test_vault.py —— 主库:加密落盘无明文断言 + 增删检索(假 embed)。"""
from __future__ import annotations
import pytest
from vstore.vault import Vault, VaultError, get_embed_fn, set_embed_fn
@pytest.fixture
def vault(tmp_path, embed_fn):
v = Vault(tmp_path / "vault", tmp_path / "index")
return v
def _read_all_bytes(path) -> bytes:
if path.is_dir():
data = b""
for f in sorted(path.rglob("*")):
if f.is_file():
data += f.read_bytes()
return data
return path.read_bytes()
def test_add_encrypted_no_plaintext_on_disk(vault):
content = "小麦育种试验报告。这是绝密明文,绝不能出现在磁盘上。".encode("utf-8")
item = vault.add(content, "report.txt", {"name": "试验报告", "description": "小麦"}, as_template=False)
assert item["document_id"]
# 全部落盘字节(vault + index)不得包含明文
for path in (vault.vault_dir, vault.index.dir):
assert "小麦育种试验报告" not in _read_all_bytes(path).decode("utf-8", errors="replace")
assert "绝密明文" not in _read_all_bytes(vault.vault_dir).decode("utf-8", errors="replace")
def test_add_enc_is_fernet_token(vault):
item = vault.add(b"hello doc", "a.txt", {"name": "n"})
enc = vault.vault_dir / f"{item['document_id']}.enc"
assert enc.exists()
assert enc.read_bytes().startswith(b"gAAAA") # Fernet token 前缀
def test_add_and_get_decrypted(vault):
item = vault.add(
"正文内容第一段。\n\n第二段。".encode("utf-8"), "doc.txt", {"name": "材料", "category": "资料"}
)
doc = vault.get_decrypted(item["document_id"])
assert doc["meta"]["name"] == "材料"
assert "正文内容第一段" in doc["extracted"]["paragraphs"][0]
json_doc = vault.get_document_json(item["document_id"])
assert json_doc["title"] == "正文内容第一段。"
def test_add_empty_rejected(vault):
with pytest.raises(VaultError):
vault.add(b"", "a.txt", {})
def test_add_oversize_accepted(vault):
# 2026-09-04 手工测试:上传不再设大小门槛,21MB 应正常入库
big = b"x" * (21 * 1024 * 1024)
item = vault.add(big, "a.txt", {})
assert item["document_id"]
doc = vault.get_decrypted(item["document_id"])
assert doc["meta"]["size"] == len(big)
def test_add_bad_docx_rejected(vault):
with pytest.raises(VaultError):
vault.add(b"not a docx", "a.docx", {})
def test_delete_removes_enc_and_index(vault):
item = vault.add(b"content", "a.txt", {"name": "n"})
doc_id = item["document_id"]
assert vault.delete(doc_id) is True
assert not (vault.vault_dir / f"{doc_id}.enc").exists()
assert vault.get_decrypted(doc_id) is None
assert vault.delete("nope") is False
def test_search_uses_fake_embed(vault):
vault.add("小麦内容。".encode("utf-8"), "a.txt", {"name": "小麦", "description": "小麦育种"})
vault.add("水稻内容。".encode("utf-8"), "b.txt", {"name": "水稻", "description": "水稻栽培"})
result = vault.search("水稻", top_k=2)
assert result["mode"] in ("vector", "keyword", "latest")
assert len(result["items"]) >= 1
def test_rebuild_index_from_enc(vault):
vault.add("甲内容。".encode("utf-8"), "a.txt", {"name": "甲", "as_template": True})
vault.add("乙内容。".encode("utf-8"), "b.txt", {"name": "乙"})
rebuilt = vault.rebuild_index()
assert rebuilt["status"] == "ok"
assert rebuilt["count"] == 2
# 重建后可检索
result = vault.search("乙")
assert len(result["items"]) >= 1
def test_get_style_missing_returns_empty(vault):
item = vault.add(b"plain", "a.txt", {"name": "n"})
assert vault.get_style(item["document_id"]) == {}
def test_update_metadata(vault):
item = vault.add(b"x", "a.txt", {"name": "n"})
assert vault.update_metadata(item["document_id"], {"name": "改名"}) is True
rows = vault.list_rows()
assert rows[0]["name"] == "改名"
def test_template_outline_chunks_limited(vault):
# 大纲超长 → 切块 ≤ MAX_OUTLINE_CHUNKS;embed_chunks 反映切块数
from vstore.parsing import extract_docx # 用 docx 造带大纲文档
import io
from docx import Document
doc = Document()
for i in range(12):
doc.add_heading(f"第{i}章" + "内容" * 100, level=1)
doc.add_paragraph("正文。")
buf = io.BytesIO()
doc.save(buf)
item = vault.add(buf.getvalue(), "t.docx", {"name": "长模板"}, as_template=True)
assert 1 <= item["embed_chunks"] <= 3