221 lines
8.6 KiB
Bash
Executable File
221 lines
8.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Momentry Core API 全端點測試 — 完整輸入輸出記錄
|
||
# 用法: ./tests_api.sh [host] [port]
|
||
# 預設: http://localhost:3003
|
||
|
||
HOST="${1:-localhost}"
|
||
PORT="${2:-3003}"
|
||
BASE="http://${HOST}:${PORT}"
|
||
API_KEY="${MOMENTRY_API_KEY:-muser_test_001}"
|
||
OUTDIR="docs_v1.0/API_V1.0.0/TEST_RESULTS"
|
||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||
OUTFILE="${OUTDIR}/api_test_${TIMESTAMP}.md"
|
||
LOGDIR="${OUTDIR}/api_responses_${TIMESTAMP}"
|
||
mkdir -p "$LOGDIR" "$OUTDIR"
|
||
|
||
PASS=0; FAIL=0
|
||
|
||
log_resp() { echo -n ""; }
|
||
|
||
call_api() {
|
||
local method="$1" url="$2" desc="$3" section="$4" body="${5:-}"
|
||
local safe_name
|
||
safe_name=$(echo "${desc}" | sed 's/[^a-zA-Z0-9_]/_/g' | cut -c1-40)
|
||
local resp_file="${LOGDIR}/${section}_${safe_name}.json"
|
||
local http_code
|
||
|
||
http_code=$(curl -s -o "${resp_file}" -w "%{http_code}" \
|
||
-X "${method}" \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: ${API_KEY}" \
|
||
${body:+-d "${body}"} \
|
||
"${BASE}${url}" 2>/dev/null)
|
||
|
||
local resp_size=$(wc -c < "${resp_file}" 2>/dev/null | tr -d ' ')
|
||
local resp_preview=$(head -c 200 "${resp_file}" 2>/dev/null | tr '\n' ' ')
|
||
|
||
if [ "${http_code}" -ge 200 ] && [ "${http_code}" -lt 500 ]; then
|
||
PASS=$((PASS+1))
|
||
else
|
||
FAIL=$((FAIL+1))
|
||
fi
|
||
|
||
cat >> "${OUTFILE}" << ENTRY
|
||
### ${method} ${url}
|
||
|
||
**說明**: ${desc}
|
||
**HTTP 狀態**: ${http_code}
|
||
**回應大小**: ${resp_size} bytes
|
||
|
||
**Request**:
|
||
\`\`\`bash
|
||
curl -X ${method} \\
|
||
-H "Content-Type: application/json" \\
|
||
-H "X-API-Key: YOUR_API_KEY" \\
|
||
${body:+-d '${body}' \\}
|
||
${BASE}${url}
|
||
\`\`\`
|
||
|
||
**Response**:
|
||
\`\`\`json
|
||
$(cat "${resp_file}" 2>/dev/null)
|
||
\`\`\`
|
||
|
||
---
|
||
ENTRY
|
||
|
||
printf " %-4s %-50s %s\n" "${http_code}" "${desc}" "${resp_preview:0:80}"
|
||
}
|
||
|
||
# ==== Test Execution ====
|
||
|
||
cat > "${OUTFILE}" << HEAD
|
||
# Momentry Core API 全端點測試報告 (完整 I/O)
|
||
|
||
**測試時間**: $(date '+%Y-%m-%d %H:%M:%S')
|
||
**伺服器**: ${BASE}
|
||
**API Key**: ${API_KEY:0:10}...
|
||
**API 版本**: V4.0 / API V1
|
||
**端點總數**: 46
|
||
|
||
---
|
||
|
||
HEAD
|
||
|
||
echo "=== Momentry Core API Test ==="
|
||
echo "Server: ${BASE}"
|
||
echo ""
|
||
|
||
# 1. Health
|
||
echo "--- 1. Health ---"
|
||
SECTION="01_health"
|
||
call_api GET "/health" "Health check" "$SECTION"
|
||
call_api GET "/health/detailed" "Health detailed" "$SECTION"
|
||
|
||
# 2. Auth
|
||
echo "--- 2. Auth ---"
|
||
SECTION="02_auth"
|
||
call_api POST "/api/v1/auth/login" "Login" "$SECTION" '{"username":"demo","password":"demo"}'
|
||
call_api POST "/api/v1/auth/logout" "Logout" "$SECTION"
|
||
|
||
# 3. Files
|
||
echo "--- 3. Files ---"
|
||
SECTION="03_files"
|
||
call_api GET "/api/v1/files" "List files" "$SECTION"
|
||
call_api GET "/api/v1/files/scan" "Scan files" "$SECTION"
|
||
call_api POST "/api/v1/files/register" "Register file" "$SECTION" '{"path":"/Users/accusys/test_video/charade_sample.mp4"}'
|
||
call_api POST "/api/v1/files/unregister" "Unregister file" "$SECTION" '{"file_uuid":"00000000000000000000000000000000"}'
|
||
|
||
DEMO_FILE="417a7e93860d70c87aee6c4c1b715d70"
|
||
call_api GET "/api/v1/file/${DEMO_FILE}" "File detail" "$SECTION"
|
||
call_api GET "/api/v1/file/${DEMO_FILE}/probe" "File probe" "$SECTION"
|
||
call_api GET "/api/v1/file/${DEMO_FILE}/identities" "File identities" "$SECTION"
|
||
call_api GET "/api/v1/file/${DEMO_FILE}/chunks" "File chunks" "$SECTION"
|
||
call_api POST "/api/v1/file/${DEMO_FILE}/process" "Trigger processing" "$SECTION" '{"processors":["story"]}'
|
||
|
||
# 4. Identity
|
||
echo "--- 4. Identity ---"
|
||
SECTION="04_identity"
|
||
call_api GET "/api/v1/identities" "List identities" "$SECTION"
|
||
call_api POST "/api/v1/identity" "Create identity" "$SECTION" '{"face_json_path":"test","identity_name":"Test Identity"}'
|
||
|
||
DEMO_ID="a9a90105-6d6b-46ff-92da-0c3c1a57dff4"
|
||
call_api GET "/api/v1/identity/${DEMO_ID}" "Identity detail" "$SECTION"
|
||
call_api GET "/api/v1/identity/${DEMO_ID}/files" "Identity files" "$SECTION"
|
||
call_api GET "/api/v1/identity/${DEMO_ID}/chunks" "Identity chunks" "$SECTION"
|
||
call_api POST "/api/v1/identity/${DEMO_ID}/bind" "Bind face" "$SECTION" "{\"file_uuid\":\"${DEMO_FILE}\",\"face_id\":\"face_100\"}"
|
||
call_api POST "/api/v1/identity/${DEMO_ID}/unbind" "Unbind face" "$SECTION" "{\"file_uuid\":\"${DEMO_FILE}\",\"face_id\":\"face_100\"}"
|
||
call_api POST "/api/v1/identity/00000000-0000-0000-0000-000000000001/mergeinto" "Merge into" "$SECTION" '{"into_uuid":"00000000-0000-0000-0000-000000000002"}'
|
||
call_api DELETE "/api/v1/identity/00000000-0000-0000-0000-000000000003" "Delete identity" "$SECTION"
|
||
|
||
# 5. Faces
|
||
echo "--- 5. Faces ---"
|
||
SECTION="05_faces"
|
||
call_api GET "/api/v1/faces/candidates" "Face candidates" "$SECTION"
|
||
|
||
# 6. Search
|
||
echo "--- 6. Search ---"
|
||
SECTION="06_search"
|
||
call_api POST "/api/v1/search" "Vector search" "$SECTION" '{"query":"Cary Grant as mysterious stranger","limit":5}'
|
||
call_api POST "/api/v1/search/bm25" "BM25 search" "$SECTION" '{"query":"stolen fortune thriller","limit":5}'
|
||
call_api POST "/api/v1/search/hybrid" "Hybrid search" "$SECTION" '{"query":"Paris apartment scene","limit":5}'
|
||
call_api POST "/api/v1/search/smart" "Smart search" "$SECTION" '{"uuid":"'${DEMO_FILE}'","query":"Audrey Hepburn","limit":5}'
|
||
call_api POST "/api/v1/search/universal" "Universal search" "$SECTION" '{"query":"stamp","uuid":"'${DEMO_FILE}'","limit":5}'
|
||
call_api POST "/api/v1/search/frames" "Frame search" "$SECTION" '{"query":"passport","uuid":"'${DEMO_FILE}'","limit":5}'
|
||
call_api POST "/api/v1/search/visual" "Visual search" "$SECTION" "{\"uuid\":\"${DEMO_FILE}\",\"criteria\":{}}"
|
||
call_api POST "/api/v1/search/visual/class" "Visual by class" "$SECTION" "{\"uuid\":\"${DEMO_FILE}\",\"object_class\":\"person\"}"
|
||
call_api POST "/api/v1/search/visual/density" "Visual by density" "$SECTION" "{\"uuid\":\"${DEMO_FILE}\",\"min_density\":0.5}"
|
||
call_api POST "/api/v1/search/visual/combination" "Visual combination" "$SECTION" "{\"uuid\":\"${DEMO_FILE}\",\"combination\":[[\"person\",1]]}"
|
||
call_api POST "/api/v1/search/visual/stats" "Visual stats" "$SECTION" "{\"uuid\":\"${DEMO_FILE}\"}"
|
||
|
||
# 7. Jobs
|
||
echo "--- 7. Jobs ---"
|
||
SECTION="07_jobs"
|
||
call_api GET "/api/v1/jobs" "List jobs" "$SECTION"
|
||
call_api GET "/api/v1/job/00000000-0000-0000-0000-000000000000" "Job detail" "$SECTION"
|
||
call_api GET "/api/v1/rule/story/status" "Rule status" "$SECTION"
|
||
call_api GET "/api/v1/progress/${DEMO_FILE}" "Progress" "$SECTION"
|
||
|
||
# 8. Resources
|
||
echo "--- 8. Resources ---"
|
||
SECTION="08_resources"
|
||
call_api GET "/api/v1/resources" "List resources" "$SECTION"
|
||
call_api POST "/api/v1/resource/register" "Register resource" "$SECTION" '{"name":"demo_worker","type":"worker","host":"localhost","port":9000}'
|
||
call_api POST "/api/v1/resource/heartbeat" "Resource heartbeat" "$SECTION" '{"name":"demo_worker"}'
|
||
|
||
# 9. Agents
|
||
echo "--- 9. Agents ---"
|
||
SECTION="09_agents"
|
||
call_api POST "/api/v1/agents/translate" "Translate" "$SECTION" '{"text":"Hello world","target_language":"zh-TW"}'
|
||
call_api POST "/api/v1/agents/identity/analyze" "Identity analyze" "$SECTION" "{\"file_uuid\":\"${DEMO_FILE}\"}"
|
||
call_api POST "/api/v1/agents/identity/suggest" "Identity suggest" "$SECTION" "{\"file_uuid\":\"${DEMO_FILE}\"}"
|
||
call_api GET "/api/v1/agents/identity/status" "Identity agent status" "$SECTION"
|
||
call_api POST "/api/v1/agents/suggest/merge" "Suggest merge" "$SECTION" "{\"file_uuid\":\"${DEMO_FILE}\"}"
|
||
call_api POST "/api/v1/agents/5w1h/analyze" "5W1H analyze" "$SECTION" '{"chunk_id":"chunk_1"}'
|
||
call_api POST "/api/v1/agents/5w1h/batch" "5W1H batch" "$SECTION" '{"chunk_ids":["chunk_1","chunk_2"]}'
|
||
call_api GET "/api/v1/agents/5w1h/status" "5W1H status" "$SECTION"
|
||
|
||
# 10. Stats & Admin
|
||
echo "--- 10. Stats & Admin ---"
|
||
SECTION="10_stats"
|
||
call_api GET "/api/v1/stats/sftpgo" "SFTPGo status" "$SECTION"
|
||
call_api GET "/api/v1/stats/inference" "Inference health" "$SECTION"
|
||
call_api POST "/api/v1/config/cache" "Cache toggle" "$SECTION" '{"enable":true}'
|
||
|
||
# ---- Summary ----
|
||
TOTAL=$((PASS + FAIL))
|
||
|
||
cat >> "${OUTFILE}" << SUMMARY
|
||
|
||
---
|
||
|
||
## 測試摘要
|
||
|
||
| 結果 | 數量 | 佔比 |
|
||
|------|------|------|
|
||
| ✅ 通過 (2xx/3xx/4xx) | ${PASS} | $(awk "BEGIN {printf \"%.0f\", ${PASS}/${TOTAL}*100}")% |
|
||
| ❌ 失敗 (5xx) | ${FAIL} | $(awk "BEGIN {printf \"%.0f\", ${FAIL}/${TOTAL}*100}")% |
|
||
| **合計** | **${TOTAL}** | **100%** |
|
||
|
||
> 註: 4xx 回應(如 404 Not Found、422 Unprocessable)視為「通過」,因為端點正常回應只是請求參數未能完整比對到資料。5xx 表示伺服器內部錯誤,需修復。
|
||
|
||
## 示範數據
|
||
|
||
| 資源 | UUID |
|
||
|------|------|
|
||
| Demo File (Charade) | \`${DEMO_FILE}\` |
|
||
| Demo Identity (Cary Grant) | \`${DEMO_ID}\` |
|
||
|
||
## 完整回應檔案
|
||
|
||
${LOGDIR}/
|
||
SUMMARY
|
||
|
||
echo ""
|
||
echo "============================================"
|
||
echo " Test Complete"
|
||
echo " PASS: ${PASS} FAIL: ${FAIL} TOTAL: ${TOTAL}"
|
||
echo " Report: ${OUTFILE}"
|
||
echo " Responses: ${LOGDIR}/"
|
||
echo "============================================"
|