From ca320c6db0f9bdc69245aad7e052b19686acb19a Mon Sep 17 00:00:00 2001 From: milky0217 Date: Wed, 10 Jun 2026 09:27:19 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=83=A8=E7=BD=B2=E6=B5=8B=E8=AF=95BASE?= =?UTF-8?q?=5FURL=E5=8F=98=E9=87=8F=E6=8F=90=E5=8D=87=E4=B8=BA=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E9=81=BF=E5=85=8D=E5=85=B6=E4=BB=96=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E6=9C=AA=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/test.sh | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/lib/test.sh b/lib/test.sh index c03cdc8..2226de6 100644 --- a/lib/test.sh +++ b/lib/test.sh @@ -2,6 +2,9 @@ # test.sh — 部署后测试(依赖 common.sh 的 remote()) # =========================================== +# 用于所有测试函数的基础 URL(在 run_tests 中设置) +BASE_URL="http://127.0.0.1" + # 测试失败自动回滚 rollback_and_exit() { local reason="$1" @@ -21,10 +24,11 @@ test_basic_connectivity() { if [ "${BACKEND_PORT}" = "4433" ] || [ "${BACKEND_PORT}" = "4434" ]; then proto="https" fi - local base_url="${proto}://127.0.0.1:${BACKEND_PORT}" + # 设置全局 BASE_URL,供其他测试函数使用 + BASE_URL="${proto}://127.0.0.1:${BACKEND_PORT}" local max_retries=3 retry=0 while [ $retry -lt $max_retries ]; do - retry=$((retry+1)); log_info "尝试 ${retry}/${max_retries}: 测试本地后端 (${base_url})" + retry=$((retry+1)); log_info "尝试 ${retry}/${max_retries}: 测试本地后端 (${BASE_URL})" local all=true for test in \ "/health:200" \ @@ -33,7 +37,7 @@ test_basic_connectivity() { "/:200"; do IFS=':' read -r path expected method extra <<< "$test" [ -z "$method" ] && method="GET" - local code; code=$(remote "curl -sk -o /dev/null -w '%{http_code}' --max-time 10 -X ${method} ${base_url}${path} ${extra}" 2>/dev/null || echo "000") + local code; code=$(remote "curl -sk -o /dev/null -w '%{http_code}' --max-time 10 -X ${method} ${BASE_URL}${path} ${extra}" 2>/dev/null || echo "000") if [ "$code" != "$expected" ] && [ "$expected" != "200,400" ] && ! { [ "$expected" = "400,200" ] && { [ "$code" = "400" ] || [ "$code" = "200" ]; }; }; then if { [ "$expected" = "400" ] && [ "$code" = "200" ]; } || { [ "$expected" = "401" ] && [ "$code" = "200" ]; }; then log_info " ${path} 正常 (HTTP ${code})"; continue @@ -62,25 +66,25 @@ test_database_connection() { } test_token_flow() { - local login; login=$(remote "curl -sk --max-time 10 -X POST ${base_url}/api/login -H 'Content-Type: application/json' -d '{\"code\":\"test\"}'" 2>/dev/null || echo "") + local login; login=$(remote "curl -sk --max-time 10 -X POST ${BASE_URL}/api/login -H 'Content-Type: application/json' -d '{\"code\":\"test\"}'" 2>/dev/null || echo "") local token; token=$(echo "$login" | grep -o '"token":"[^"]*"' | head -1 | cut -d'"' -f4 || echo "") [ -z "$token" ] && log_warn " 未获取到 token(微信 code 无效是正常的)" || log_info " 获取到 token" # 测试受保护端点 - local profile; profile=$(remote "curl -sk --max-time 10 ${base_url}/api/user/profile -H 'Authorization: Bearer ${token}'" 2>/dev/null || echo "") + local profile; profile=$(remote "curl -sk --max-time 10 ${BASE_URL}/api/user/profile -H 'Authorization: Bearer ${token}'" 2>/dev/null || echo "") echo "$profile" | grep -q '"success":true' && log_info " /api/user/profile JWT 验证成功" || log_warn " /api/user/profile 无权限(正常)" - local refresh; refresh=$(remote "curl -sk --max-time 10 -X POST ${base_url}/api/refresh-token -H 'Content-Type: application/json' -d '{\"refresh_token\":\"invalid\"}'" 2>/dev/null || echo "") + local refresh; refresh=$(remote "curl -sk --max-time 10 -X POST ${BASE_URL}/api/refresh-token -H 'Content-Type: application/json' -d '{\"refresh_token\":\"invalid\"}'" 2>/dev/null || echo "") log_info " refresh_token 端点响应正常" log_info "Token 流程测试通过"; return 0 } test_weather_details_jwt() { - local login; login=$(remote "curl -sk --max-time 10 -X POST ${base_url}/api/login -H 'Content-Type: application/json' -d '{\"code\":\"test\"}'" 2>/dev/null || echo "") + local login; login=$(remote "curl -sk --max-time 10 -X POST ${BASE_URL}/api/login -H 'Content-Type: application/json' -d '{\"code\":\"test\"}'" 2>/dev/null || echo "") local token; token=$(echo "$login" | grep -o '"token":"[^"]*"' | head -1 | cut -d'"' -f4 || echo "") [ -z "$token" ] && { log_warn " 无 token,跳过 weather/details 测试(微信 code 无效是正常的)"; return 0; } - local resp; resp=$(remote "curl -sk --max-time 10 '${base_url}/weather/details?id=1' -H 'Authorization: Bearer ${token}'" 2>/dev/null || echo "") + local resp; resp=$(remote "curl -sk --max-time 10 '${BASE_URL}/weather/details?id=1' -H 'Authorization: Bearer ${token}'" 2>/dev/null || echo "") if echo "$resp" | grep -q '"success":true' || echo "$resp" | grep -q "Forbidden"; then log_info " weather/details JWT 验证通过" else @@ -93,7 +97,7 @@ test_invalid_token_401() { local bad="eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjB9.bad" local all=true for path in "/api/user/profile" "/weather/details?id=1" "/api/weather"; do - local c; c=$(remote "curl -sk -o /dev/null -w '%{http_code}' --max-time 10 '${base_url}${path}' -H 'Authorization: Bearer ${bad}'" 2>/dev/null || echo "000") + local c; c=$(remote "curl -sk -o /dev/null -w '%{http_code}' --max-time 10 '${BASE_URL}${path}' -H 'Authorization: Bearer ${bad}'" 2>/dev/null || echo "000") [ "$c" = "401" ] && log_info " ${path} 返回 401 ✓" || { log_warn " ${path} 返回 ${c}"; all=false; } done $all && log_info "无效 Token 401 测试通过" && return 0 @@ -101,7 +105,7 @@ test_invalid_token_401() { } test_response_content() { - local r; r=$(remote "curl -sk --max-time 10 ${base_url}/health" 2>/dev/null || echo "") + local r; r=$(remote "curl -sk --max-time 10 ${BASE_URL}/health" 2>/dev/null || echo "") echo "$r" | grep -q '"status"' && echo "$r" | grep -q '"database"' && \ log_info " /health JSON 格式正确 ✓" || { log_warn " /health 响应异常"; return 1; } echo "$r" | grep -q '"database":"connected"' && \ @@ -119,13 +123,13 @@ test_mock_login() { local key; key=$(remote "grep 'MOCK_LOGIN_KEY' /etc/systemd/system/${SERVICE_NAME} 2>/dev/null | head -1 | sed 's/.*MOCK_LOGIN_KEY=//'" 2>/dev/null || echo "") [ -z "$key" ] && { log_warn " 未配置 MOCK_LOGIN_KEY,跳过"; return 0; } - local resp; resp=$(remote "curl -sk --max-time 10 '${base_url}/api/mock-login' -H 'X-Mock-Key: ${key}'" 2>/dev/null || echo "") + local resp; resp=$(remote "curl -sk --max-time 10 '${BASE_URL}/api/mock-login' -H 'X-Mock-Key: ${key}'" 2>/dev/null || echo "") local token; token=$(echo "$resp" | grep -o '"token":"[^"]*"' | head -1 | cut -d'"' -f4 || echo "") if [ -n "$token" ]; then log_info " mock-login 返回有效 JWT ✅" # 用获取到的 token 测试通知接口 - local notif; notif=$(remote "curl -sk --max-time 10 '${base_url}/api/notifications/unread-count' -H 'Authorization: Bearer ${token}'" 2>/dev/null || echo "") + local notif; notif=$(remote "curl -sk --max-time 10 '${BASE_URL}/api/notifications/unread-count' -H 'Authorization: Bearer ${token}'" 2>/dev/null || echo "") echo "$notif" | grep -q '"success":true' && log_info " /api/notifications/unread-count 正常 ✅" || log_warn " 通知接口响应异常" else log_warn " mock-login 未返回 token" @@ -135,13 +139,13 @@ test_mock_login() { test_payment_endpoints() { local all=true - local c; c=$(remote "curl -sk -o /dev/null -w '%{http_code}' --max-time 10 '${base_url}/payment'" 2>/dev/null || echo "000") + local c; c=$(remote "curl -sk -o /dev/null -w '%{http_code}' --max-time 10 '${BASE_URL}/payment'" 2>/dev/null || echo "000") [ "$c" = "200" ] && log_info " /payment 返回 200 ✅" || { log_warn " /payment 返回 ${c}"; all=false; } - c=$(remote "curl -sk -o /dev/null -w '%{http_code}' --max-time 10 '${base_url}/payment/page?package=monthly&jwt=bad'" 2>/dev/null || echo "000") + c=$(remote "curl -sk -o /dev/null -w '%{http_code}' --max-time 10 '${BASE_URL}/payment/page?package=monthly&jwt=bad'" 2>/dev/null || echo "000") [ "$c" = "401" ] && log_info " /payment/page (bad JWT) 返回 401 ✅" || { log_warn " /payment/page 返回 ${c}"; all=false; } - c=$(remote "curl -sk -o /dev/null -w '%{http_code}' --max-time 10 '${base_url}/api/user/quota' -H 'Authorization: Bearer bad'" 2>/dev/null || echo "000") + c=$(remote "curl -sk -o /dev/null -w '%{http_code}' --max-time 10 '${BASE_URL}/api/user/quota' -H 'Authorization: Bearer bad'" 2>/dev/null || echo "000") [ "$c" = "401" ] && log_info " /api/user/quota (bad JWT) 返回 401 ✅" || { log_warn " /api/user/quota 返回 ${c}"; all=false; } $all && log_info "支付端点测试通过" && return 0 @@ -209,14 +213,14 @@ test_payment_flow() { # 1. 获取 mock JWT local login_resp - login_resp=$(remote "curl -sk --max-time 10 '${base_url}/api/mock-login' -H 'X-Mock-Key: ${mock_key}'" 2>/dev/null || echo "") + login_resp=$(remote "curl -sk --max-time 10 '${BASE_URL}/api/mock-login' -H 'X-Mock-Key: ${mock_key}'" 2>/dev/null || echo "") local token token=$(echo "$login_resp" | grep -o '"token":"[^"]*"' | head -1 | cut -d'"' -f4 || echo "") if [ -n "$token" ]; then # 2. 创建月度订单 local order_page - order_page=$(remote "curl -sk --max-time 10 '${base_url}/payment/page?package=monthly&jwt=${token}'" 2>/dev/null || echo "") + order_page=$(remote "curl -sk --max-time 10 '${BASE_URL}/payment/page?package=monthly&jwt=${token}'" 2>/dev/null || echo "") # 3. 从页面提取订单号 local order_no @@ -225,7 +229,7 @@ test_payment_flow() { if [ -n "$order_no" ] && [ "$order_no" != "null" ]; then # 4. Mock 确认支付 local confirm_resp - confirm_resp=$(remote "curl -sk --max-time 10 -X POST '${base_url}/api/payment/mock-confirm' \ + confirm_resp=$(remote "curl -sk --max-time 10 -X POST '${BASE_URL}/api/payment/mock-confirm' \ -H 'Authorization: Bearer ${token}' \ -H 'X-Mock-Key: ${mock_key}' \ -H 'Content-Type: application/json' \