587 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			587 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package binanceservice
 | ||
| 
 | ||
| import (
 | ||
| 	"context"
 | ||
| 	"fmt"
 | ||
| 	"sync"
 | ||
| 	"testing"
 | ||
| 	"time"
 | ||
| 
 | ||
| 	"github.com/go-admin-team/go-admin-core/logger"
 | ||
| 	"github.com/go-redis/redis/v8"
 | ||
| 	"github.com/shopspring/decimal"
 | ||
| 	"github.com/stretchr/testify/assert"
 | ||
| 	"github.com/stretchr/testify/suite"
 | ||
| 	"gorm.io/driver/mysql"
 | ||
| 	"gorm.io/gorm"
 | ||
| )
 | ||
| 
 | ||
| // OptimizedSystemTestSuite 优化系统测试套件
 | ||
| type OptimizedSystemTestSuite struct {
 | ||
| 	suite.Suite
 | ||
| 	db              *gorm.DB
 | ||
| 	redisClient     *redis.Client
 | ||
| 	config          *OptimizedConfig
 | ||
| 	metricsCollector *MetricsCollector
 | ||
| 	errorHandler    *ErrorHandler
 | ||
| 	lockManager     *LockManager
 | ||
| 	txManager       *TransactionManager
 | ||
| 	reverseService  *ReverseServiceOptimized
 | ||
| }
 | ||
| 
 | ||
| // SetupSuite 设置测试套件
 | ||
| func (suite *OptimizedSystemTestSuite) SetupSuite() {
 | ||
| 	// 初始化数据库连接(测试环境)
 | ||
| 	dsn := "root:password@tcp(localhost:3306)/test_exchange?charset=utf8mb4&parseTime=True&loc=Local"
 | ||
| 	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
 | ||
| 	if err != nil {
 | ||
| 		suite.T().Skip("跳过集成测试:无法连接数据库")
 | ||
| 		return
 | ||
| 	}
 | ||
| 	suite.db = db
 | ||
| 
 | ||
| 	// 初始化Redis连接(测试环境)
 | ||
| 	suite.redisClient = redis.NewClient(&redis.Options{
 | ||
| 		Addr:     "localhost:6379",
 | ||
| 		Password: "",
 | ||
| 		DB:       1, // 使用测试数据库
 | ||
| 	})
 | ||
| 
 | ||
| 	// 测试Redis连接
 | ||
| 	ctx := context.Background()
 | ||
| 	if err := suite.redisClient.Ping(ctx).Err(); err != nil {
 | ||
| 		suite.T().Skip("跳过集成测试:无法连接Redis")
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 初始化配置
 | ||
| 	suite.config = GetDefaultOptimizedConfig()
 | ||
| 	suite.config.MonitorConfig.Enabled = true
 | ||
| 
 | ||
| 	// 初始化组件
 | ||
| 	suite.metricsCollector = NewMetricsCollector(suite.config)
 | ||
| 	suite.errorHandler = NewErrorHandler(suite.config, suite.metricsCollector)
 | ||
| 	suite.lockManager = NewLockManager(suite.config, suite.redisClient, suite.metricsCollector)
 | ||
| 	suite.txManager = NewTransactionManager(suite.db, suite.metricsCollector, suite.config)
 | ||
| 
 | ||
| 	// 启动指标收集
 | ||
| 	suite.metricsCollector.Start()
 | ||
| 
 | ||
| 	// 创建测试表
 | ||
| 	suite.createTestTables()
 | ||
| }
 | ||
| 
 | ||
| // TearDownSuite 清理测试套件
 | ||
| func (suite *OptimizedSystemTestSuite) TearDownSuite() {
 | ||
| 	if suite.metricsCollector != nil {
 | ||
| 		suite.metricsCollector.Stop()
 | ||
| 	}
 | ||
| 	if suite.redisClient != nil {
 | ||
| 		suite.redisClient.Close()
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| // SetupTest 设置每个测试
 | ||
| func (suite *OptimizedSystemTestSuite) SetupTest() {
 | ||
| 	// 清理Redis测试数据
 | ||
| 	ctx := context.Background()
 | ||
| 	suite.redisClient.FlushDB(ctx)
 | ||
| 
 | ||
| 	// 清理数据库测试数据
 | ||
| 	suite.db.Exec("DELETE FROM test_orders")
 | ||
| 	suite.db.Exec("DELETE FROM test_positions")
 | ||
| }
 | ||
| 
 | ||
| // createTestTables 创建测试表
 | ||
| func (suite *OptimizedSystemTestSuite) createTestTables() {
 | ||
| 	// 创建测试订单表
 | ||
| 	suite.db.Exec(`
 | ||
| 		CREATE TABLE IF NOT EXISTS test_orders (
 | ||
| 			id BIGINT PRIMARY KEY AUTO_INCREMENT,
 | ||
| 			order_id VARCHAR(100) UNIQUE NOT NULL,
 | ||
| 			user_id VARCHAR(50) NOT NULL,
 | ||
| 			symbol VARCHAR(20) NOT NULL,
 | ||
| 			side VARCHAR(10) NOT NULL,
 | ||
| 			quantity DECIMAL(20,8) NOT NULL,
 | ||
| 			price DECIMAL(20,8),
 | ||
| 			status VARCHAR(20) NOT NULL,
 | ||
| 			version INT DEFAULT 0,
 | ||
| 			created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
 | ||
| 			updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 | ||
| 			INDEX idx_user_symbol (user_id, symbol),
 | ||
| 			INDEX idx_status (status),
 | ||
| 			INDEX idx_version (version)
 | ||
| 		)
 | ||
| 	`)
 | ||
| 
 | ||
| 	// 创建测试持仓表
 | ||
| 	suite.db.Exec(`
 | ||
| 		CREATE TABLE IF NOT EXISTS test_positions (
 | ||
| 			id BIGINT PRIMARY KEY AUTO_INCREMENT,
 | ||
| 			user_id VARCHAR(50) NOT NULL,
 | ||
| 			symbol VARCHAR(20) NOT NULL,
 | ||
| 			side VARCHAR(10) NOT NULL,
 | ||
| 			quantity DECIMAL(20,8) NOT NULL,
 | ||
| 			avg_price DECIMAL(20,8),
 | ||
| 			status VARCHAR(20) NOT NULL,
 | ||
| 			version INT DEFAULT 0,
 | ||
| 			created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
 | ||
| 			updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 | ||
| 			UNIQUE KEY uk_user_symbol_side (user_id, symbol, side),
 | ||
| 			INDEX idx_version (version)
 | ||
| 		)
 | ||
| 	`)
 | ||
| }
 | ||
| 
 | ||
| // TestLockManager 测试锁管理器
 | ||
| func (suite *OptimizedSystemTestSuite) TestLockManager() {
 | ||
| 	ctx := context.Background()
 | ||
| 
 | ||
| 	// 测试分布式锁
 | ||
| 	suite.Run("DistributedLock", func() {
 | ||
| 		config := LockManagerConfig{
 | ||
| 			Type:       LockTypeDistributed,
 | ||
| 			Scope:      ScopeOrder,
 | ||
| 			Key:        "test_order_123",
 | ||
| 			Expiration: 10 * time.Second,
 | ||
| 			Timeout:    5 * time.Second,
 | ||
| 			RetryDelay: 100 * time.Millisecond,
 | ||
| 		}
 | ||
| 
 | ||
| 		// 获取锁
 | ||
| 		lock, err := suite.lockManager.AcquireLock(ctx, config)
 | ||
| 		assert.NoError(suite.T(), err)
 | ||
| 		assert.NotNil(suite.T(), lock)
 | ||
| 		assert.True(suite.T(), lock.IsLocked())
 | ||
| 
 | ||
| 		// 尝试获取同一个锁(应该失败)
 | ||
| 		config.Timeout = 1 * time.Second
 | ||
| 		_, err = suite.lockManager.AcquireLock(ctx, config)
 | ||
| 		assert.Error(suite.T(), err)
 | ||
| 
 | ||
| 		// 释放锁
 | ||
| 		err = suite.lockManager.ReleaseLock(ctx, lock)
 | ||
| 		assert.NoError(suite.T(), err)
 | ||
| 		assert.False(suite.T(), lock.IsLocked())
 | ||
| 	})
 | ||
| 
 | ||
| 	// 测试本地锁
 | ||
| 	suite.Run("LocalLock", func() {
 | ||
| 		config := LockManagerConfig{
 | ||
| 			Type:       LockTypeLocal,
 | ||
| 			Scope:      ScopeUser,
 | ||
| 			Key:        "test_user_456",
 | ||
| 			Expiration: 10 * time.Second,
 | ||
| 			Timeout:    5 * time.Second,
 | ||
| 			RetryDelay: 100 * time.Millisecond,
 | ||
| 		}
 | ||
| 
 | ||
| 		lock, err := suite.lockManager.AcquireLock(ctx, config)
 | ||
| 		assert.NoError(suite.T(), err)
 | ||
| 		assert.NotNil(suite.T(), lock)
 | ||
| 		assert.True(suite.T(), lock.IsLocked())
 | ||
| 
 | ||
| 		err = suite.lockManager.ReleaseLock(ctx, lock)
 | ||
| 		assert.NoError(suite.T(), err)
 | ||
| 	})
 | ||
| 
 | ||
| 	// 测试并发锁
 | ||
| 	suite.Run("ConcurrentLocks", func() {
 | ||
| 		var wg sync.WaitGroup
 | ||
| 		successCount := 0
 | ||
| 		var mu sync.Mutex
 | ||
| 
 | ||
| 		for i := 0; i < 10; i++ {
 | ||
| 			wg.Add(1)
 | ||
| 			go func(id int) {
 | ||
| 				defer wg.Done()
 | ||
| 
 | ||
| 				config := LockManagerConfig{
 | ||
| 					Type:       LockTypeDistributed,
 | ||
| 					Scope:      ScopeGlobal,
 | ||
| 					Key:        "concurrent_test",
 | ||
| 					Expiration: 2 * time.Second,
 | ||
| 					Timeout:    1 * time.Second,
 | ||
| 					RetryDelay: 50 * time.Millisecond,
 | ||
| 				}
 | ||
| 
 | ||
| 				lock, err := suite.lockManager.AcquireLock(ctx, config)
 | ||
| 				if err == nil {
 | ||
| 					mu.Lock()
 | ||
| 					successCount++
 | ||
| 					mu.Unlock()
 | ||
| 
 | ||
| 					time.Sleep(100 * time.Millisecond)
 | ||
| 					suite.lockManager.ReleaseLock(ctx, lock)
 | ||
| 				}
 | ||
| 			}(i)
 | ||
| 		}
 | ||
| 
 | ||
| 		wg.Wait()
 | ||
| 		assert.Equal(suite.T(), 1, successCount, "只有一个goroutine应该获得锁")
 | ||
| 	})
 | ||
| }
 | ||
| 
 | ||
| // TestTransactionManager 测试事务管理器
 | ||
| func (suite *OptimizedSystemTestSuite) TestTransactionManager() {
 | ||
| 	ctx := context.Background()
 | ||
| 
 | ||
| 	// 测试基本事务
 | ||
| 	suite.Run("BasicTransaction", func() {
 | ||
| 		config := GetDefaultTransactionConfig()
 | ||
| 		result := suite.txManager.WithTransaction(ctx, config, func(txCtx *TransactionContext) error {
 | ||
| 			// 插入测试数据
 | ||
| 			return txCtx.Tx.Exec(`
 | ||
| 				INSERT INTO test_orders (order_id, user_id, symbol, side, quantity, status) 
 | ||
| 				VALUES (?, ?, ?, ?, ?, ?)
 | ||
| 			`, "order_001", "user_001", "BTCUSDT", "BUY", 1.0, "NEW").Error
 | ||
| 		})
 | ||
| 
 | ||
| 		assert.True(suite.T(), result.Success)
 | ||
| 		assert.NoError(suite.T(), result.Error)
 | ||
| 
 | ||
| 		// 验证数据已插入
 | ||
| 		var count int64
 | ||
| 		suite.db.Raw("SELECT COUNT(*) FROM test_orders WHERE order_id = ?", "order_001").Scan(&count)
 | ||
| 		assert.Equal(suite.T(), int64(1), count)
 | ||
| 	})
 | ||
| 
 | ||
| 	// 测试事务回滚
 | ||
| 	suite.Run("TransactionRollback", func() {
 | ||
| 		config := GetDefaultTransactionConfig()
 | ||
| 		result := suite.txManager.WithTransaction(ctx, config, func(txCtx *TransactionContext) error {
 | ||
| 			// 插入数据
 | ||
| 			if err := txCtx.Tx.Exec(`
 | ||
| 				INSERT INTO test_orders (order_id, user_id, symbol, side, quantity, status) 
 | ||
| 				VALUES (?, ?, ?, ?, ?, ?)
 | ||
| 			`, "order_002", "user_002", "ETHUSDT", "SELL", 2.0, "NEW").Error; err != nil {
 | ||
| 				return err
 | ||
| 			}
 | ||
| 
 | ||
| 			// 故意返回错误以触发回滚
 | ||
| 			return fmt.Errorf("测试回滚")
 | ||
| 		})
 | ||
| 
 | ||
| 		assert.False(suite.T(), result.Success)
 | ||
| 		assert.Error(suite.T(), result.Error)
 | ||
| 
 | ||
| 		// 验证数据未插入
 | ||
| 		var count int64
 | ||
| 		suite.db.Raw("SELECT COUNT(*) FROM test_orders WHERE order_id = ?", "order_002").Scan(&count)
 | ||
| 		assert.Equal(suite.T(), int64(0), count)
 | ||
| 	})
 | ||
| 
 | ||
| 	// 测试乐观锁
 | ||
| 	suite.Run("OptimisticLock", func() {
 | ||
| 		// 先插入测试数据
 | ||
| 		suite.db.Exec(`
 | ||
| 			INSERT INTO test_positions (user_id, symbol, side, quantity, avg_price, status, version) 
 | ||
| 			VALUES (?, ?, ?, ?, ?, ?, ?)
 | ||
| 		`, "user_003", "BTCUSDT", "LONG", 1.0, 50000.0, "OPEN", 0)
 | ||
| 
 | ||
| 		// 测试正常更新
 | ||
| 		updates := map[string]interface{}{
 | ||
| 			"quantity": 2.0,
 | ||
| 		}
 | ||
| 		err := suite.txManager.UpdateWithOptimisticLock(ctx, nil, updates, 
 | ||
| 			"user_id = ? AND symbol = ? AND side = ? AND version = ?", 
 | ||
| 			"user_003", "BTCUSDT", "LONG", 0)
 | ||
| 		assert.NoError(suite.T(), err)
 | ||
| 
 | ||
| 		// 测试版本冲突
 | ||
| 		updates["quantity"] = 3.0
 | ||
| 		err = suite.txManager.UpdateWithOptimisticLock(ctx, nil, updates, 
 | ||
| 			"user_id = ? AND symbol = ? AND side = ? AND version = ?", 
 | ||
| 			"user_003", "BTCUSDT", "LONG", 0) // 使用旧版本号
 | ||
| 		assert.Error(suite.T(), err)
 | ||
| 		assert.Contains(suite.T(), err.Error(), "乐观锁冲突")
 | ||
| 	})
 | ||
| }
 | ||
| 
 | ||
| // TestErrorHandler 测试错误处理器
 | ||
| func (suite *OptimizedSystemTestSuite) TestErrorHandler() {
 | ||
| 	ctx := context.Background()
 | ||
| 
 | ||
| 	// 测试错误分类
 | ||
| 	suite.Run("ErrorClassification", func() {
 | ||
| 		testCases := []struct {
 | ||
| 			error    error
 | ||
| 			expected ErrorType
 | ||
| 		}{
 | ||
| 			{fmt.Errorf("connection refused"), ErrorTypeNetwork},
 | ||
| 			{fmt.Errorf("database connection failed"), ErrorTypeDatabase},
 | ||
| 			{fmt.Errorf("context deadline exceeded"), ErrorTypeTimeout},
 | ||
| 			{fmt.Errorf("too many requests"), ErrorTypeRateLimit},
 | ||
| 			{fmt.Errorf("unauthorized access"), ErrorTypeAuth},
 | ||
| 			{fmt.Errorf("invalid parameter"), ErrorTypeValidation},
 | ||
| 			{fmt.Errorf("insufficient balance"), ErrorTypeBusiness},
 | ||
| 		}
 | ||
| 
 | ||
| 		for _, tc := range testCases {
 | ||
| 			errorInfo := suite.errorHandler.ClassifyError(tc.error, "test")
 | ||
| 			assert.Equal(suite.T(), tc.expected, errorInfo.Type)
 | ||
| 		}
 | ||
| 	})
 | ||
| 
 | ||
| 	// 测试重试机制
 | ||
| 	suite.Run("RetryMechanism", func() {
 | ||
| 		attempts := 0
 | ||
| 		config := RetryConfig{
 | ||
| 			MaxRetries:     3,
 | ||
| 			RetryDelay:     10 * time.Millisecond,
 | ||
| 			MaxRetryDelay:  100 * time.Millisecond,
 | ||
| 			BackoffFactor:  2.0,
 | ||
| 			ApiRetryCount:  3,
 | ||
| 			DbRetryCount:   3,
 | ||
| 		}
 | ||
| 
 | ||
| 		// 测试重试成功
 | ||
| 		err := suite.errorHandler.RetryWithBackoff(ctx, func() error {
 | ||
| 			attempts++
 | ||
| 			if attempts < 3 {
 | ||
| 				return fmt.Errorf("temporary error")
 | ||
| 			}
 | ||
| 			return nil
 | ||
| 		}, config, "test_retry")
 | ||
| 
 | ||
| 		assert.NoError(suite.T(), err)
 | ||
| 		assert.Equal(suite.T(), 3, attempts)
 | ||
| 
 | ||
| 		// 测试重试失败
 | ||
| 		attempts = 0
 | ||
| 		err = suite.errorHandler.RetryWithBackoff(ctx, func() error {
 | ||
| 			attempts++
 | ||
| 			return fmt.Errorf("persistent error")
 | ||
| 		}, config, "test_retry_fail")
 | ||
| 
 | ||
| 		assert.Error(suite.T(), err)
 | ||
| 		assert.Equal(suite.T(), 3, attempts)
 | ||
| 	})
 | ||
| }
 | ||
| 
 | ||
| // TestMetricsCollector 测试指标收集器
 | ||
| func (suite *OptimizedSystemTestSuite) TestMetricsCollector() {
 | ||
| 	// 测试订单指标
 | ||
| 	suite.Run("OrderMetrics", func() {
 | ||
| 		// 记录订单处理
 | ||
| 		suite.metricsCollector.RecordOrderProcessed(true, 100*time.Millisecond)
 | ||
| 		suite.metricsCollector.RecordOrderProcessed(false, 200*time.Millisecond)
 | ||
| 		suite.metricsCollector.RecordOrderCanceled()
 | ||
| 		suite.metricsCollector.RecordReverseOrder(true)
 | ||
| 
 | ||
| 		metrics := suite.metricsCollector.GetMetrics()
 | ||
| 		orderMetrics := metrics["order_metrics"].(*OrderMetrics)
 | ||
| 
 | ||
| 		assert.Equal(suite.T(), int64(2), orderMetrics.TotalProcessed)
 | ||
| 		assert.Equal(suite.T(), int64(1), orderMetrics.SuccessfulOrders)
 | ||
| 		assert.Equal(suite.T(), int64(1), orderMetrics.FailedOrders)
 | ||
| 		assert.Equal(suite.T(), int64(1), orderMetrics.CanceledOrders)
 | ||
| 		assert.Equal(suite.T(), int64(1), orderMetrics.ReverseOrdersCreated)
 | ||
| 	})
 | ||
| 
 | ||
| 	// 测试持仓指标
 | ||
| 	suite.Run("PositionMetrics", func() {
 | ||
| 		difference := decimal.NewFromFloat(0.1)
 | ||
| 		suite.metricsCollector.RecordPositionSync(true, difference)
 | ||
| 		suite.metricsCollector.RecordPositionSync(false, decimal.Zero)
 | ||
| 		suite.metricsCollector.RecordClosePosition(false)
 | ||
| 		suite.metricsCollector.RecordClosePosition(true)
 | ||
| 
 | ||
| 		metrics := suite.metricsCollector.GetMetrics()
 | ||
| 		positionMetrics := metrics["position_metrics"].(*PositionMetrics)
 | ||
| 
 | ||
| 		assert.Equal(suite.T(), int64(2), positionMetrics.SyncAttempts)
 | ||
| 		assert.Equal(suite.T(), int64(1), positionMetrics.SyncSuccesses)
 | ||
| 		assert.Equal(suite.T(), int64(1), positionMetrics.SyncFailures)
 | ||
| 		assert.Equal(suite.T(), int64(2), positionMetrics.ClosePositions)
 | ||
| 		assert.Equal(suite.T(), int64(1), positionMetrics.ForceClosePositions)
 | ||
| 	})
 | ||
| 
 | ||
| 	// 测试性能指标
 | ||
| 	suite.Run("PerformanceMetrics", func() {
 | ||
| 		suite.metricsCollector.RecordLockOperation(true, 50*time.Millisecond)
 | ||
| 		suite.metricsCollector.RecordDbOperation(false, 30*time.Millisecond, nil)
 | ||
| 		suite.metricsCollector.RecordApiCall(100*time.Millisecond, nil, 1)
 | ||
| 		suite.metricsCollector.RecordConcurrency(5)
 | ||
| 
 | ||
| 		metrics := suite.metricsCollector.GetMetrics()
 | ||
| 		perfMetrics := metrics["performance_metrics"].(*PerformanceMetrics)
 | ||
| 
 | ||
| 		assert.Equal(suite.T(), int64(1), perfMetrics.LockAcquisitions)
 | ||
| 		assert.Equal(suite.T(), int64(1), perfMetrics.DbQueries)
 | ||
| 		assert.Equal(suite.T(), int64(1), perfMetrics.ApiCalls)
 | ||
| 		assert.Equal(suite.T(), int64(5), perfMetrics.ConcurrentRequests)
 | ||
| 	})
 | ||
| }
 | ||
| 
 | ||
| // TestConcurrentOperations 测试并发操作
 | ||
| func (suite *OptimizedSystemTestSuite) TestConcurrentOperations() {
 | ||
| 	ctx := context.Background()
 | ||
| 
 | ||
| 	suite.Run("ConcurrentOrderProcessing", func() {
 | ||
| 		var wg sync.WaitGroup
 | ||
| 		successCount := 0
 | ||
| 		var mu sync.Mutex
 | ||
| 
 | ||
| 		// 并发处理订单
 | ||
| 		for i := 0; i < 10; i++ {
 | ||
| 			wg.Add(1)
 | ||
| 			go func(id int) {
 | ||
| 				defer wg.Done()
 | ||
| 
 | ||
| 				// 使用锁保护订单处理
 | ||
| 				lockConfig := GetOrderLockConfig(fmt.Sprintf("order_%d", id))
 | ||
| 				err := suite.lockManager.WithLock(ctx, lockConfig, func() error {
 | ||
| 					// 模拟订单处理
 | ||
| 					config := GetDefaultTransactionConfig()
 | ||
| 					result := suite.txManager.WithTransaction(ctx, config, func(txCtx *TransactionContext) error {
 | ||
| 						return txCtx.Tx.Exec(`
 | ||
| 							INSERT INTO test_orders (order_id, user_id, symbol, side, quantity, status) 
 | ||
| 							VALUES (?, ?, ?, ?, ?, ?)
 | ||
| 						`, fmt.Sprintf("concurrent_order_%d", id), fmt.Sprintf("user_%d", id), 
 | ||
| 							"BTCUSDT", "BUY", 1.0, "NEW").Error
 | ||
| 					})
 | ||
| 
 | ||
| 					if result.Success {
 | ||
| 						mu.Lock()
 | ||
| 						successCount++
 | ||
| 						mu.Unlock()
 | ||
| 					}
 | ||
| 
 | ||
| 					return result.Error
 | ||
| 				})
 | ||
| 
 | ||
| 				if err != nil {
 | ||
| 					logger.Errorf("并发订单处理失败 [%d]: %v", id, err)
 | ||
| 				}
 | ||
| 			}(i)
 | ||
| 		}
 | ||
| 
 | ||
| 		wg.Wait()
 | ||
| 		assert.Equal(suite.T(), 10, successCount, "所有并发订单都应该成功处理")
 | ||
| 
 | ||
| 		// 验证数据库中的记录数
 | ||
| 		var count int64
 | ||
| 		suite.db.Raw("SELECT COUNT(*) FROM test_orders WHERE order_id LIKE 'concurrent_order_%'").Scan(&count)
 | ||
| 		assert.Equal(suite.T(), int64(10), count)
 | ||
| 	})
 | ||
| }
 | ||
| 
 | ||
| // TestSystemIntegration 测试系统集成
 | ||
| func (suite *OptimizedSystemTestSuite) TestSystemIntegration() {
 | ||
| 	ctx := context.Background()
 | ||
| 
 | ||
| 	suite.Run("CompleteOrderFlow", func() {
 | ||
| 		userID := "integration_user"
 | ||
| 		symbol := "BTCUSDT"
 | ||
| 		orderID := "integration_order_001"
 | ||
| 
 | ||
| 		// 步骤1:创建订单(使用锁和事务)
 | ||
| 		err := WithOrderLock(ctx, orderID, func() error {
 | ||
| 			return WithDefaultTransaction(ctx, func(txCtx *TransactionContext) error {
 | ||
| 				return txCtx.Tx.Exec(`
 | ||
| 					INSERT INTO test_orders (order_id, user_id, symbol, side, quantity, price, status) 
 | ||
| 					VALUES (?, ?, ?, ?, ?, ?, ?)
 | ||
| 				`, orderID, userID, symbol, "BUY", 1.0, 50000.0, "NEW").Error
 | ||
| 			})
 | ||
| 		})
 | ||
| 		assert.NoError(suite.T(), err)
 | ||
| 
 | ||
| 		// 步骤2:更新订单状态(使用乐观锁)
 | ||
| 		updates := map[string]interface{}{
 | ||
| 			"status": "FILLED",
 | ||
| 		}
 | ||
| 		err = UpdateWithOptimisticLockGlobal(ctx, nil, updates, 
 | ||
| 			"order_id = ? AND version = ?", orderID, 0)
 | ||
| 		assert.NoError(suite.T(), err)
 | ||
| 
 | ||
| 		// 步骤3:创建持仓(使用锁和事务)
 | ||
| 		err = WithPositionLock(ctx, userID, symbol, func() error {
 | ||
| 			return WithDefaultTransaction(ctx, func(txCtx *TransactionContext) error {
 | ||
| 				return txCtx.Tx.Exec(`
 | ||
| 					INSERT INTO test_positions (user_id, symbol, side, quantity, avg_price, status) 
 | ||
| 					VALUES (?, ?, ?, ?, ?, ?)
 | ||
| 					ON DUPLICATE KEY UPDATE 
 | ||
| 					quantity = quantity + VALUES(quantity),
 | ||
| 					avg_price = (avg_price * quantity + VALUES(avg_price) * VALUES(quantity)) / (quantity + VALUES(quantity)),
 | ||
| 					version = version + 1
 | ||
| 				`, userID, symbol, "LONG", 1.0, 50000.0, "OPEN").Error
 | ||
| 			})
 | ||
| 		})
 | ||
| 		assert.NoError(suite.T(), err)
 | ||
| 
 | ||
| 		// 验证最终状态
 | ||
| 		var orderStatus string
 | ||
| 		suite.db.Raw("SELECT status FROM test_orders WHERE order_id = ?", orderID).Scan(&orderStatus)
 | ||
| 		assert.Equal(suite.T(), "FILLED", orderStatus)
 | ||
| 
 | ||
| 		var positionQuantity float64
 | ||
| 		suite.db.Raw("SELECT quantity FROM test_positions WHERE user_id = ? AND symbol = ?", 
 | ||
| 			userID, symbol).Scan(&positionQuantity)
 | ||
| 		assert.Equal(suite.T(), 1.0, positionQuantity)
 | ||
| 	})
 | ||
| }
 | ||
| 
 | ||
| // TestPerformance 测试性能
 | ||
| func (suite *OptimizedSystemTestSuite) TestPerformance() {
 | ||
| 	ctx := context.Background()
 | ||
| 
 | ||
| 	suite.Run("LockPerformance", func() {
 | ||
| 		startTime := time.Now()
 | ||
| 		iterations := 1000
 | ||
| 
 | ||
| 		for i := 0; i < iterations; i++ {
 | ||
| 			lockConfig := GetOrderLockConfig(fmt.Sprintf("perf_order_%d", i))
 | ||
| 			lock, err := suite.lockManager.AcquireLock(ctx, lockConfig)
 | ||
| 			assert.NoError(suite.T(), err)
 | ||
| 			suite.lockManager.ReleaseLock(ctx, lock)
 | ||
| 		}
 | ||
| 
 | ||
| 		duration := time.Since(startTime)
 | ||
| 		avgDuration := duration / time.Duration(iterations)
 | ||
| 		logger.Infof("锁性能测试: %d 次操作耗时 %v,平均每次 %v", iterations, duration, avgDuration)
 | ||
| 
 | ||
| 		// 平均每次操作应该在合理范围内
 | ||
| 		assert.Less(suite.T(), avgDuration, 10*time.Millisecond)
 | ||
| 	})
 | ||
| 
 | ||
| 	suite.Run("TransactionPerformance", func() {
 | ||
| 		startTime := time.Now()
 | ||
| 		iterations := 100
 | ||
| 
 | ||
| 		for i := 0; i < iterations; i++ {
 | ||
| 			config := GetDefaultTransactionConfig()
 | ||
| 			result := suite.txManager.WithTransaction(ctx, config, func(txCtx *TransactionContext) error {
 | ||
| 				return txCtx.Tx.Exec(`
 | ||
| 					INSERT INTO test_orders (order_id, user_id, symbol, side, quantity, status) 
 | ||
| 					VALUES (?, ?, ?, ?, ?, ?)
 | ||
| 				`, fmt.Sprintf("perf_order_%d", i), "perf_user", "BTCUSDT", "BUY", 1.0, "NEW").Error
 | ||
| 			})
 | ||
| 			assert.True(suite.T(), result.Success)
 | ||
| 		}
 | ||
| 
 | ||
| 		duration := time.Since(startTime)
 | ||
| 		avgDuration := duration / time.Duration(iterations)
 | ||
| 		logger.Infof("事务性能测试: %d 次操作耗时 %v,平均每次 %v", iterations, duration, avgDuration)
 | ||
| 
 | ||
| 		// 平均每次事务应该在合理范围内
 | ||
| 		assert.Less(suite.T(), avgDuration, 100*time.Millisecond)
 | ||
| 	})
 | ||
| }
 | ||
| 
 | ||
| // TestSuite 运行测试套件
 | ||
| func TestOptimizedSystemSuite(t *testing.T) {
 | ||
| 	suite.Run(t, new(OptimizedSystemTestSuite))
 | ||
| }
 | ||
| 
 | ||
| // BenchmarkLockManager 锁管理器基准测试
 | ||
| func BenchmarkLockManager(b *testing.B) {
 | ||
| 	// 这里可以添加基准测试
 | ||
| 	b.Skip("基准测试需要Redis连接")
 | ||
| }
 | ||
| 
 | ||
| // BenchmarkTransactionManager 事务管理器基准测试
 | ||
| func BenchmarkTransactionManager(b *testing.B) {
 | ||
| 	// 这里可以添加基准测试
 | ||
| 	b.Skip("基准测试需要数据库连接")
 | ||
| } |