- tests/docgen/:DC-UNIT/API/CONF/E2E/UI/REGRESSION/PERF 分组用例与可复跑脚本,报告逐条留痕(R1-R3 全记录) - 意图 30 条前后端同表双跑(pytest + node) - Playwright headless:docgen-ui/docgen-regression spec + b3 benchpanel 第 5 TAB 断言更新 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
163 lines
8.4 KiB
Bash
Executable File
163 lines
8.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# run_e2e_curl.sh —— DC-E2E-CURL-01~09(端到端 curl 序列,每步断言)
|
||
#
|
||
# 前置(必须由 TL 完成,本脚本不做任何启动动作):
|
||
# 1. TL 已启动 dev BFF 与 vstore 实例(vstore 必须开启加密落盘);
|
||
# 2. 通过环境变量告知地址:
|
||
# DOCGEN_E2E_VSTORE 默认 http://127.0.0.1:8094
|
||
# DOCGEN_E2E_BFF 默认 http://127.0.0.1:8090
|
||
# DOCGEN_E2E_VAULT vstore 加密库目录绝对路径(用于保密断言),必填
|
||
# DOCGEN_E2E_SENTINEL 入库样例的明文标志串(用于 grep 无命中断言),必填
|
||
# 3. 若未提供必填变量:本脚本打印 PENDING 并以 77 退出(SKIP,不视为 FAIL)。
|
||
#
|
||
# 纪律:
|
||
# - 只在 TL 指定的端口与目录上操作;样例用占位明文;
|
||
# - 断言幂等(不依赖 vault 既有数据的命中次序;删除只删本次入库记录);
|
||
# - 失败立即退出非零;每步输出对应用例编号,便于回填 test_case_report.md。
|
||
#
|
||
# R1 执行口径(2026-09-03):BFF=8090、vstore=8094(TL 授权端口)。
|
||
|
||
set -u
|
||
cd "$(dirname "$0")/../.." || exit 2 # 仓库根
|
||
|
||
VSTORE="${DOCGEN_E2E_VSTORE:-http://127.0.0.1:8094}"
|
||
BFF="${DOCGEN_E2E_BFF:-http://127.0.0.1:8090}"
|
||
VAULT="${DOCGEN_E2E_VAULT:-}"
|
||
SENTINEL="${DOCGEN_E2E_SENTINEL:-}"
|
||
|
||
say() { echo "== $1 =="; }
|
||
ok() { echo " [PASS] $1"; }
|
||
die() { echo " [FAIL] $1"; echo "===== E2E 汇总:本步断言失败(exit 1) ====="; exit 1; }
|
||
|
||
if [ -z "$VAULT" ] || [ -z "$SENTINEL" ]; then
|
||
echo "[PENDING] 需 TL 提供 DOCGEN_E2E_VAULT(vstore 加密库目录)与 DOCGEN_E2E_SENTINEL(样例明文标志串),本脚本 SKIP"
|
||
exit 77
|
||
fi
|
||
command -v curl >/dev/null || { echo "curl 缺失"; exit 2; }
|
||
PY=/home/xzq/5090/teamWorkspace/zh/plantai-rag-new-venv/bin/python
|
||
|
||
# ---------- DC-E2E-CURL-01 健康检查 ----------
|
||
say "DC-E2E-CURL-01 /api/vstore/health"
|
||
HEALTH=$(curl -fsS "$VSTORE/api/vstore/health") || die "vstore health 请求失败"
|
||
echo "$HEALTH" | grep -q '"ok":true' && ok "health ok" || die "health 非 ok:$HEALTH"
|
||
|
||
# ---------- DC-E2E-CURL-02 入库 → 保密断言(黄金断言) ----------
|
||
say "DC-E2E-CURL-02 入库 + ls 仅 .enc + 明文 grep 无命中"
|
||
SAMPLE=/tmp/docgen_e2e_sample.docx
|
||
"$PY" - <<'PYEOF' || die "样例 docx 生成失败"
|
||
import os
|
||
from docx import Document
|
||
d = Document()
|
||
d.add_heading("占位测试标题", level=1)
|
||
d.add_paragraph("样例明文标志串:%s。" % os.environ["DOCGEN_E2E_SENTINEL"])
|
||
d.save("/tmp/docgen_e2e_sample.docx")
|
||
PYEOF
|
||
INGEST_OUT=$(curl -fsS -X POST "$VSTORE/api/vstore/ingest" \
|
||
-F "file=@$SAMPLE;filename=样例通知.docx" \
|
||
-F "name=样例通知R1" -F "category=通知" -F "as_template=true")
|
||
echo "$INGEST_OUT" | grep -q '"ok":true' && ok "ingest ok" || die "ingest 失败:$INGEST_OUT"
|
||
NEW_DOC_ID=$(echo "$INGEST_OUT" | sed -n 's/.*"document_id":"\([^"]*\)".*/\1/p')
|
||
[ -n "$NEW_DOC_ID" ] && ok "取到 document_id=$NEW_DOC_ID" || die "ingest 响应缺 document_id"
|
||
# 保密断言 A:ls vault 只见 .enc
|
||
LS_OUT=$(ls -1 "$VAULT")
|
||
echo "$LS_OUT" | grep -q '\.enc$' || die "vault 目录无 .enc 文件:$LS_OUT"
|
||
BAD=$(echo "$LS_OUT" | grep -v -E '(\.enc$)' || true)
|
||
[ -z "$BAD" ] && ok "ls vault 仅见 .enc" || die "vault 出现异常文件:$BAD"
|
||
# 保密断言 B:明文 grep 无命中
|
||
if grep -rq "$SENTINEL" "$VAULT" 2>/dev/null; then die "vault 内 grep 命中明文标志串(明文落盘!)"; fi
|
||
ok "明文 grep 无命中($SENTINEL)"
|
||
|
||
# ---------- DC-E2E-CURL-03 检索 ----------
|
||
say "DC-E2E-CURL-03 检索"
|
||
SEARCH_MODE=$(curl -fsS "$VSTORE/api/vstore/search?q=$SENTINEL&top_k=3&as_template=true" \
|
||
| sed -n 's/.*"mode":"\([^"]*\)".*/\1/p')
|
||
case "$SEARCH_MODE" in
|
||
vector|keyword|latest) ok "search mode=$SEARCH_MODE(三档降级内)" ;;
|
||
*) die "检索 mode 异常:$SEARCH_MODE" ;;
|
||
esac
|
||
|
||
# ---------- DC-E2E-CURL-04 取明文(仅生成时取用路径) ----------
|
||
say "DC-E2E-CURL-04 取文档明文"
|
||
curl -fsS "$VSTORE/api/vstore/documents/$NEW_DOC_ID" >/tmp/docgen_doc.json \
|
||
&& ok "GET documents/{id} 200" || die "GET documents/{id} 失败"
|
||
grep -q "$SENTINEL" /tmp/docgen_doc.json \
|
||
&& ok "响应含明文全文(占位样例标志串)" || die "documents 响应未含明文全文"
|
||
grep -q '"outline"' /tmp/docgen_doc.json && ok "响应含 outline 字段" || die "documents 响应缺 outline"
|
||
rm -f /tmp/docgen_doc.json
|
||
|
||
# ---------- DC-E2E-CURL-05 BFF 入库 ----------
|
||
say "DC-E2E-CURL-05 BFF 入库"
|
||
BFF_UP=$(curl -fsS -X POST "$BFF/api/docgen/library" \
|
||
-F "file=@$SAMPLE;filename=样例通知BFF.docx" \
|
||
-F "name=样例通知BFFR1" -F "category=通知")
|
||
echo "$BFF_UP" | grep -q '"ok":true' && ok "BFF 入库 ok" || die "BFF 入库失败:$BFF_UP"
|
||
BFF_LIB_ID=$(echo "$BFF_UP" | sed -n 's/.*"library_id":"\([^"]*\)".*/\1/p' | head -1)
|
||
[ -n "$BFF_LIB_ID" ] && ok "BFF 库记录 id=$BFF_LIB_ID" || die "BFF 入库响应缺 library_id"
|
||
# 复验保密断言
|
||
if grep -rq "$SENTINEL" "$VAULT" 2>/dev/null; then die "BFF 入库后 vault 出现明文(保密断言失败)"; fi
|
||
ok "BFF 入库后 vault 仍无明文"
|
||
|
||
# ---------- DC-E2E-CURL-06 BFF 生成 ----------
|
||
say "DC-E2E-CURL-06 BFF 生成"
|
||
GEN=$(curl -fsS -X POST "$BFF/api/docgen/generate" \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{"description":"帮我写一份年度工作总结","session_id":"e2e-sess-1","library_ids":[]}')
|
||
echo "$GEN" | grep -q '"status":"done"' && ok "生成 done" || die "生成未 done:$GEN"
|
||
ART_ID=$(echo "$GEN" | sed -n 's/.*"artifact":{[^}]*"id":"\([^"]*\)".*/\1/p')
|
||
[ -n "$ART_ID" ] && ok "取到 artifact id=$ART_ID" || die "未取到 artifact id"
|
||
|
||
# ---------- DC-E2E-CURL-07 编辑/保存/导出 ----------
|
||
say "DC-E2E-CURL-07 编辑/保存/导出"
|
||
curl -fsS -X PATCH "$BFF/api/docgen/artifacts/$ART_ID/content" \
|
||
-H 'Content-Type: application/json' -d '{"markdown":"# 新标题\n\n新正文段落。"}' \
|
||
| grep -q '"ok":true' && ok "PATCH content ok" || die "PATCH content 失败"
|
||
curl -fsS -X POST "$BFF/api/docgen/artifacts/$ART_ID/edit" \
|
||
-H 'Content-Type: application/json' -d '{"instruction":"润色一下第一段"}' \
|
||
| grep -q '"ok":true' && ok "edit ok" || die "edit 失败"
|
||
curl -fsS -X POST "$BFF/api/docgen/artifacts/$ART_ID/export" \
|
||
-H 'Content-Type: application/json' -d '{"format":"pdf"}' \
|
||
| grep -q '"ok":true' && ok "export pdf ok" || die "export 失败"
|
||
|
||
# ---------- DC-E2E-CURL-08 下载断言 + 可打开断言 ----------
|
||
say "DC-E2E-CURL-08 下载 attachment + 文件可打开"
|
||
cd /tmp || exit 2
|
||
curl -fsS -D /tmp/docgen_dl_headers.txt -o /tmp/docgen_e2e_out.pdf \
|
||
"$BFF/api/docgen/artifacts/$ART_ID/download?format=pdf" || die "download 失败"
|
||
grep -qi 'Content-Disposition:.*attachment' /tmp/docgen_dl_headers.txt \
|
||
&& ok "Content-Disposition attachment" || die "缺 attachment 头:$(cat /tmp/docgen_dl_headers.txt)"
|
||
grep -qi "filename\*=UTF-8''" /tmp/docgen_dl_headers.txt \
|
||
&& ok "RFC 5987 filename* 编码" || echo " [WARN] 未检出 filename*=UTF-8''(记录实测列)"
|
||
"$PY" - <<'PYEOF' && ok "PDF 可打开且页数>0" || die "下载的 PDF 打不开"
|
||
import fitz
|
||
with fitz.open("/tmp/docgen_e2e_out.pdf") as doc:
|
||
assert doc.page_count > 0
|
||
PYEOF
|
||
curl -fsS -X POST "$BFF/api/docgen/artifacts/$ART_ID/export" \
|
||
-H 'Content-Type: application/json' -d '{"format":"docx"}' \
|
||
| grep -q '"ok":true' || die "export docx 失败"
|
||
curl -fsS -o /tmp/docgen_e2e_out.docx \
|
||
"$BFF/api/docgen/artifacts/$ART_ID/download?format=docx" || die "docx download 失败"
|
||
"$PY" - <<'PYEOF' && ok "DOCX 可打开且段落>0" || die "下载的 DOCX 打不开"
|
||
import docx
|
||
d = docx.Document("/tmp/docgen_e2e_out.docx")
|
||
assert len(d.paragraphs) > 0
|
||
PYEOF
|
||
|
||
# ---------- DC-E2E-CURL-09 删除与收尾保密复验 ----------
|
||
say "DC-E2E-CURL-09 删除与收尾"
|
||
if [ -n "$BFF_LIB_ID" ]; then
|
||
DL_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE "$BFF/api/docgen/library/$BFF_LIB_ID")
|
||
[ "$DL_STATUS" = "204" ] && ok "DELETE 库记录 204" || die "DELETE 库记录 HTTP $DL_STATUS"
|
||
# vstore 端删除复验:BFF 库记录 id 即 vstore document_id,对应 .enc 应消失
|
||
if [ ! -f "$VAULT/$BFF_LIB_ID.enc" ]; then
|
||
ok "对应密文 .enc 已删除"
|
||
else
|
||
echo " [WARN] vault 端 $BFF_LIB_ID.enc 仍存在(记录实测列)"
|
||
fi
|
||
fi
|
||
if grep -rq "$SENTINEL" "$VAULT" 2>/dev/null; then die "收尾后 vault 仍有明文(保密断言失败)"; fi
|
||
ok "收尾后 vault 无明文"
|
||
rm -f "$SAMPLE" /tmp/docgen_e2e_out.pdf /tmp/docgen_e2e_out.docx /tmp/docgen_dl_headers.txt
|
||
|
||
echo "===== E2E 汇总:全部断言步骤通过(FAIL=0) ====="
|