|
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
#
|
|
|
|
|
|
# 测试公共函数库
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
|
set -e
|
|
|
|
|
|
|
|
|
|
|
|
# 配置
|
|
|
|
|
|
BASE_URL="${BASE_URL:-http://localhost:4000}"
|
|
|
|
|
|
TEST_TIMESTAMP="${TEST_TIMESTAMP:-$(date +%s)}"
|
|
|
|
|
|
|
|
|
|
|
|
# 颜色输出
|
|
|
|
|
|
RED='\033[0;31m'
|
|
|
|
|
|
GREEN='\033[0;32m'
|
|
|
|
|
|
YELLOW='\033[1;33m'
|
|
|
|
|
|
BLUE='\033[0;34m'
|
|
|
|
|
|
NC='\033[0m' # No Color
|
|
|
|
|
|
|
|
|
|
|
|
# ========================================
|
|
|
|
|
|
# 辅助函数
|
|
|
|
|
|
# ========================================
|
|
|
|
|
|
|
|
|
|
|
|
# 打印带颜色的信息
|
|
|
|
|
|
info() {
|
|
|
|
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
success() {
|
|
|
|
|
|
echo -e "${GREEN}[PASS]${NC} $1"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
error() {
|
|
|
|
|
|
echo -e "${RED}[FAIL]${NC} $1"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
warn() {
|
|
|
|
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 检查上一个命令是否成功
|
|
|
|
|
|
check_success() {
|
|
|
|
|
|
if [ $? -eq 0 ]; then
|
|
|
|
|
|
success "$1"
|
|
|
|
|
|
return 0
|
|
|
|
|
|
else
|
|
|
|
|
|
error "$1"
|
|
|
|
|
|
return 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 检查上一个命令是否失败(用于测试权限拒绝)
|
|
|
|
|
|
check_fail() {
|
|
|
|
|
|
if [ $? -ne 0 ]; then
|
|
|
|
|
|
success "$1 (预期失败)"
|
|
|
|
|
|
return 0
|
|
|
|
|
|
else
|
|
|
|
|
|
error "$1 (应该失败但没有)"
|
|
|
|
|
|
return 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 检查HTTP响应码
|
|
|
|
|
|
# $1: 响应内容
|
|
|
|
|
|
# $2: 期望状态码(默认 200)
|
|
|
|
|
|
check_http_code() {
|
|
|
|
|
|
local response="$1"
|
|
|
|
|
|
local expected="${2:-200}"
|
|
|
|
|
|
local code
|
|
|
|
|
|
|
|
|
|
|
|
# 提取 code 字段,如果不存在则认为是 200
|
|
|
|
|
|
code=$(echo "$response" | jq -r '.code // 200')
|
|
|
|
|
|
|
|
|
|
|
|
if [ "$code" == "$expected" ]; then
|
|
|
|
|
|
return 0
|
|
|
|
|
|
else
|
|
|
|
|
|
error "期望状态码: $expected, 实际: $code"
|
|
|
|
|
|
info "响应: $response"
|
|
|
|
|
|
return 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 检查服务是否运行
|
|
|
|
|
|
check_service() {
|
|
|
|
|
|
if ! curl -s "$BASE_URL/_api.json" > /dev/null 2>&1; then
|
|
|
|
|
|
error "服务未启动,请先启动服务"
|
|
|
|
|
|
info "运行: go run cli/main.go -db=sqlite -dsn /tmp/vb.sqlite -p 4000"
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
success "服务正在运行"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# ========================================
|
|
|
|
|
|
# API 请求封装
|
|
|
|
|
|
# ========================================
|
|
|
|
|
|
|
|
|
|
|
|
# GET 请求
|
|
|
|
|
|
api_get() {
|
|
|
|
|
|
local path="$1"
|
|
|
|
|
|
local token="${2:-}"
|
|
|
|
|
|
local headers=""
|
|
|
|
|
|
|
|
|
|
|
|
if [ -n "$token" ]; then
|
|
|
|
|
|
headers="-H Authorization: Bearer $token"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
curl -s -X GET "$BASE_URL$path" $headers
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# POST 请求
|
|
|
|
|
|
api_post() {
|
|
|
|
|
|
local path="$1"
|
|
|
|
|
|
local data="$2"
|
|
|
|
|
|
local token="${3:-}"
|
|
|
|
|
|
local extra_headers="${4:-}"
|
|
|
|
|
|
local headers="-H Content-Type: application/json"
|
|
|
|
|
|
|
|
|
|
|
|
if [ -n "$token" ]; then
|
|
|
|
|
|
headers="$headers -H Authorization: Bearer $token"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
if [ -n "$extra_headers" ]; then
|
|
|
|
|
|
headers="$headers $extra_headers"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
curl -s -X POST "$BASE_URL$path" $headers -d "$data"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# PATCH 请求
|
|
|
|
|
|
api_patch() {
|
|
|
|
|
|
local path="$1"
|
|
|
|
|
|
local data="$2"
|
|
|
|
|
|
local token="${3:-}"
|
|
|
|
|
|
local extra_headers="${4:-}"
|
|
|
|
|
|
local headers="-H Content-Type: application/json"
|
|
|
|
|
|
|
|
|
|
|
|
if [ -n "$token" ]; then
|
|
|
|
|
|
headers="$headers -H Authorization: Bearer $token"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
if [ -n "$extra_headers" ]; then
|
|
|
|
|
|
headers="$headers $extra_headers"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
curl -s -X PATCH "$BASE_URL$path" $headers -d "$data"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# DELETE 请求
|
|
|
|
|
|
api_delete() {
|
|
|
|
|
|
local path="$1"
|
|
|
|
|
|
local token="$2"
|
|
|
|
|
|
local extra_headers="${3:-}"
|
|
|
|
|
|
local headers=""
|
|
|
|
|
|
|
|
|
|
|
|
if [ -n "$token" ]; then
|
|
|
|
|
|
headers="-H Authorization: Bearer $token"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
if [ -n "$extra_headers" ]; then
|
|
|
|
|
|
headers="$headers $extra_headers"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
curl -s -X DELETE "$BASE_URL$path" $headers
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# ========================================
|
|
|
|
|
|
# 用户相关操作
|
|
|
|
|
|
# ========================================
|
|
|
|
|
|
|
|
|
|
|
|
# 注册用户
|
|
|
|
|
|
# 返回: 注册响应
|
|
|
|
|
|
register_user() {
|
|
|
|
|
|
local username="$1"
|
|
|
|
|
|
local password="$2"
|
|
|
|
|
|
local email="$3"
|
|
|
|
|
|
|
|
|
|
|
|
api_post "/api/auth/register" \
|
|
|
|
|
|
"{\"username\": \"$username\", \"password\": \"$password\", \"email\": \"$email\"}"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 登录用户
|
|
|
|
|
|
# 返回: 登录响应
|
|
|
|
|
|
login_user() {
|
|
|
|
|
|
local username="$1"
|
|
|
|
|
|
local password="$2"
|
|
|
|
|
|
|
|
|
|
|
|
api_post "/api/auth/login" \
|
|
|
|
|
|
"{\"username\": \"$username\", \"password\": \"$password\"}"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 提取 token
|
|
|
|
|
|
get_token() {
|
|
|
|
|
|
local login_response="$1"
|
|
|
|
|
|
echo "$login_response" | jq -r '.access_token'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 提取用户ID
|
|
|
|
|
|
get_user_id() {
|
|
|
|
|
|
local login_response="$1"
|
|
|
|
|
|
echo "$login_response" | jq -r '.user.id'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# ========================================
|
|
|
|
|
|
# 组织相关操作
|
|
|
|
|
|
# ========================================
|
|
|
|
|
|
|
|
|
|
|
|
# 创建组织
|
|
|
|
|
|
create_org() {
|
|
|
|
|
|
local token="$1"
|
|
|
|
|
|
local code="$2"
|
|
|
|
|
|
local name="$3"
|
|
|
|
|
|
local desc="${4:-}"
|
|
|
|
|
|
|
|
|
|
|
|
api_post "/api/orgs" \
|
|
|
|
|
|
"{\"code\": \"$code\", \"name\": \"$name\", \"description\": \"$desc\"}" \
|
|
|
|
|
|
"$token"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 更新组织
|
|
|
|
|
|
update_org() {
|
|
|
|
|
|
local token="$1"
|
|
|
|
|
|
local org_id="$2"
|
|
|
|
|
|
local data="$3"
|
|
|
|
|
|
|
|
|
|
|
|
api_patch "/api/orgs/$org_id" "$data" "$token" "-H X-Org-ID: $org_id"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 添加组织成员
|
|
|
|
|
|
add_org_member() {
|
|
|
|
|
|
local token="$1"
|
|
|
|
|
|
local org_id="$2"
|
|
|
|
|
|
local user_id="$3"
|
|
|
|
|
|
local role="${4:-member}"
|
|
|
|
|
|
|
|
|
|
|
|
api_post "/api/orgs/$org_id/members" \
|
|
|
|
|
|
"{\"user_id\": \"$user_id\", \"role\": \"$role\"}" \
|
|
|
|
|
|
"$token" \
|
|
|
|
|
|
"-H X-Org-ID: $org_id"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# ========================================
|
|
|
|
|
|
# 测试框架
|
|
|
|
|
|
# ========================================
|
|
|
|
|
|
|
|
|
|
|
|
# 测试开始
|
|
|
|
|
|
test_start() {
|
|
|
|
|
|
local name="$1"
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
echo "========================================"
|
|
|
|
|
|
echo "测试: $name"
|
|
|
|
|
|
echo "========================================"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 测试步骤
|
|
|
|
|
|
step() {
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
info "$1"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 测试结束
|
|
|
|
|
|
test_end() {
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
success "测试完成"
|
|
|
|
|
|
}
|