#!/bin/bash # ================================================== # OCDP Backend - 三种模式测试脚本 # ================================================== # 测试三种部署模式: # 1. Mock 模式(无 docker compose,backend 热重载) # 2. Production 模式(docker compose 仅依赖服务,backend 热重载) # 3. Production 模式(docker compose 包含 backend) # ================================================== set -e # 遇到错误立即退出 # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 日志函数 log_info() { echo -e "${BLUE}ℹ️ $1${NC}" } log_success() { echo -e "${GREEN}✅ $1${NC}" } log_error() { echo -e "${RED}❌ $1${NC}" } log_warning() { echo -e "${YELLOW}⚠️ $1${NC}" } log_section() { echo "" echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo -e "${BLUE} $1${NC}" echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" } # 等待服务启动 wait_for_service() { local url=$1 local max_attempts=30 local attempt=1 log_info "等待服务启动: $url" while [ $attempt -le $max_attempts ]; do if curl -s -f "$url" > /dev/null 2>&1; then log_success "服务已启动!" return 0 fi echo -n "." sleep 1 attempt=$((attempt + 1)) done log_error "服务启动超时" return 1 } # 测试健康检查 test_health() { local mode=$1 log_info "测试健康检查..." response=$(curl -s http://localhost:8080/health) if echo "$response" | grep -q "healthy"; then log_success "$mode 模式健康检查通过" return 0 else log_error "$mode 模式健康检查失败" echo "响应: $response" return 1 fi } # 测试 API test_api() { local mode=$1 log_info "测试 API..." # 测试注册 local test_username="testuser$RANDOM" local test_password="test123" register_response=$(curl -s -X POST http://localhost:8080/api/v1/auth/register \ -H "Content-Type: application/json" \ -d '{"username":"'"$test_username"'","password":"'"$test_password"'","email":"test@example.com"}') if echo "$register_response" | grep -q "id"; then log_success "$mode 模式 API 注册测试通过" else log_warning "$mode 模式 API 注册测试失败(可能用户已存在)" fi # 测试登录 login_response=$(curl -s -X POST http://localhost:8080/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"'"$test_username"'","password":"'"$test_password"'"}') if echo "$login_response" | grep -q "accessToken"; then log_success "$mode 模式 API 登录测试通过" return 0 else log_error "$mode 模式 API 登录测试失败" echo "响应: $login_response" return 1 fi } # 清理环境 cleanup() { log_info "清理环境..." # 停止所有容器 docker compose down --remove-orphans > /dev/null 2>&1 || true docker compose --profile backend down --remove-orphans > /dev/null 2>&1 || true docker compose --profile mock down --remove-orphans > /dev/null 2>&1 || true # 停止可能在运行的本地进程 pkill -f "tmp/main" > /dev/null 2>&1 || true pkill -f "cmd/api/main.go" > /dev/null 2>&1 || true sleep 2 log_success "清理完成" } # ================================================== # 测试 1: Mock 模式(无 docker compose,backend 热重载) # ================================================== test_mode_1() { log_section "测试模式 1: Mock 模式(本地运行,热重载)" log_info "配置:" log_info " • 运行方式: 本地 Go" log_info " • 适配器: Mock(内存存储)" log_info " • 数据库: 无需" log_info " • 热重载: 支持(Air)" # 检查 Air 是否安装 if ! command -v air &> /dev/null; then log_error "Air 未安装,跳过热重载测试" log_info "安装命令: go install github.com/air-verse/air@latest" return 1 fi # 启动 Mock 模式(后台) log_info "启动 Mock 模式..." export ADAPTER_MODE=mock export PORT=8080 export JWT_SECRET=test-secret # 在后台启动 nohup air -c .air.toml > /tmp/ocdp-mock.log 2>&1 & local pid=$! log_info "进程 PID: $pid" # 等待服务启动 if wait_for_service "http://localhost:8080/health"; then # 测试服务 test_health "Mock" test_api "Mock" # 停止服务 log_info "停止服务..." kill $pid 2>/dev/null || true pkill -f "tmp/main" 2>/dev/null || true sleep 2 log_success "模式 1 测试完成" return 0 else log_error "服务启动失败,查看日志: /tmp/ocdp-mock.log" kill $pid 2>/dev/null || true return 1 fi } # ================================================== # 测试 2: Production 模式(docker compose 仅依赖,backend 热重载) # ================================================== test_mode_2() { log_section "测试模式 2: Docker Compose 仅依赖服务(本地 backend 热重载)" log_info "配置:" log_info " • 数据库: Docker (PostgreSQL)" log_info " • Backend: 本地 Go" log_info " • 适配器: Production" log_info " • 热重载: 支持(Air)" # 检查 Air 是否安装 if ! command -v air &> /dev/null; then log_error "Air 未安装,跳过热重载测试" return 1 fi # 启动 PostgreSQL log_info "启动 PostgreSQL 容器..." docker compose up -d postgres # 等待数据库就绪 log_info "等待 PostgreSQL 启动..." sleep 10 # 检查数据库健康状态 if ! docker compose exec -T postgres pg_isready -U postgres > /dev/null 2>&1; then log_error "PostgreSQL 未就绪" docker compose logs postgres return 1 fi log_success "PostgreSQL 已启动" # 启动 Backend(后台) log_info "启动 Backend (本地)..." export ADAPTER_MODE=production export PORT=8080 export JWT_SECRET=test-secret export ENCRYPTION_KEY=12345678901234567890123456789012 export DATABASE_URL="postgresql://postgres:postgres@localhost:5432/ocdp?sslmode=disable" # 在后台启动 nohup air -c .air.toml > /tmp/ocdp-real.log 2>&1 & local pid=$! log_info "进程 PID: $pid" # 等待服务启动 if wait_for_service "http://localhost:8080/health"; then # 测试服务 test_health "Production (本地 backend)" test_api "Production (本地 backend)" # 停止服务 log_info "停止 backend..." kill $pid 2>/dev/null || true pkill -f "tmp/main" 2>/dev/null || true sleep 2 # 停止数据库 log_info "停止 PostgreSQL..." docker compose down log_success "模式 2 测试完成" return 0 else log_error "服务启动失败,查看日志: /tmp/ocdp-real.log" kill $pid 2>/dev/null || true docker compose down return 1 fi } # ================================================== # 测试 3: Production 模式(docker compose 包含 backend) # ================================================== test_mode_3() { log_section "测试模式 3: Docker Compose 完整服务(包含 backend)" log_info "配置:" log_info " • 数据库: Docker (PostgreSQL)" log_info " • Backend: Docker 容器" log_info " • 适配器: Production" log_info " • 热重载: 不支持" # 确保 .env 文件存在 if [ ! -f .env ]; then log_info "创建 .env 文件..." cp env.example .env fi # 启动完整服务 log_info "启动完整服务(PostgreSQL + Backend)..." docker compose --profile backend up -d # 等待服务启动 log_info "等待服务启动(可能需要构建镜像,请耐心等待)..." # 检查容器状态 sleep 15 if ! docker compose ps | grep -q "ocdp-backend"; then log_error "Backend 容器未启动" docker compose logs backend return 1 fi # 等待健康检查通过 if wait_for_service "http://localhost:8080/health"; then # 测试服务 test_health "Production (Docker)" test_api "Production (Docker)" # 查看容器状态 log_info "容器状态:" docker compose ps # 停止服务 log_info "停止服务..." docker compose --profile backend down log_success "模式 3 测试完成" return 0 else log_error "服务启动失败" log_info "Backend 日志:" docker compose logs backend docker compose --profile backend down return 1 fi } # ================================================== # 主函数 # ================================================== main() { log_section "OCDP Backend - 三种模式自动化测试" log_info "项目目录: $(pwd)" log_info "测试时间: $(date)" # 检查是否在项目根目录 if [ ! -f "docker-compose.yml" ]; then log_error "请在项目根目录运行此脚本" exit 1 fi # 初始清理 cleanup # 运行测试 local failed=0 # 测试模式 1 if test_mode_1; then log_success "✅ 模式 1 测试通过" else log_error "❌ 模式 1 测试失败" failed=$((failed + 1)) fi cleanup sleep 3 # 测试模式 2 if test_mode_2; then log_success "✅ 模式 2 测试通过" else log_error "❌ 模式 2 测试失败" failed=$((failed + 1)) fi cleanup sleep 3 # 测试模式 3 if test_mode_3; then log_success "✅ 模式 3 测试通过" else log_error "❌ 模式 3 测试失败" failed=$((failed + 1)) fi cleanup # 总结 log_section "测试总结" if [ $failed -eq 0 ]; then log_success "🎉 所有测试通过!" log_info "" log_info "三种部署模式总结:" log_info "" log_info "1️⃣ Mock 模式(开发)" log_info " 命令: make dev-mock" log_info " 特点: 无需数据库,快速启动,热重载" log_info "" log_info "2️⃣ Real 模式(开发 + 数据库)" log_info " 命令: docker compose up -d && make dev-real" log_info " 特点: PostgreSQL 容器,Backend 本地热重载" log_info "" log_info "3️⃣ Production 模式(生产)" log_info " 命令: docker compose --profile backend up -d" log_info " 特点: 完全容器化,适合生产环境" exit 0 else log_error "❌ $failed 个测试失败" exit 1 fi } # 执行主函数 main