- 添加 Dockerfile 与多套 docker-compose 配置(开发/生产环境) - 集成 Laravel Octane (Swoole) 提升性能 - 新增健康检查、监控脚本及部署文档 - 新增 Docker 镜像离线导入包(MySQL/Redis/Meilisearch) - 优化文档转换、预览服务及队列任务 - 添加 CreateAdminUser 命令与路由健康检查接口 - 新增 Swoole 队列兼容性测试套件 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
274 lines
8.0 KiB
PHP
274 lines
8.0 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Jobs\ConvertDocumentToMarkdown;
|
|
use App\Models\Document;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Queue;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* Swoole 队列系统集成测试
|
|
*
|
|
* 验证队列系统在 Swoole 环境下的完整集成功能
|
|
*/
|
|
class SwooleQueueIntegrationTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
// 设置测试存储磁盘
|
|
Storage::fake('documents');
|
|
Storage::fake('markdown');
|
|
|
|
// 禁用搜索功能以避免 Meilisearch 连接问题
|
|
config(['scout.driver' => 'null']);
|
|
}
|
|
|
|
/**
|
|
* 测试队列任务的完整生命周期
|
|
*
|
|
* @test
|
|
*/
|
|
public function test_queue_job_complete_lifecycle()
|
|
{
|
|
// 创建测试数据
|
|
$user = User::factory()->create();
|
|
$document = Document::factory()->create([
|
|
'uploaded_by' => $user->id,
|
|
'title' => '集成测试文档',
|
|
'file_path' => 'integration-test.docx',
|
|
]);
|
|
|
|
// 使用模拟队列来避免实际执行
|
|
Queue::fake();
|
|
|
|
// 分发队列任务
|
|
Queue::pushOn('default', new ConvertDocumentToMarkdown($document));
|
|
|
|
// 验证任务已被分发
|
|
Queue::assertPushed(ConvertDocumentToMarkdown::class);
|
|
|
|
// 验证任务可以被正确序列化和反序列化
|
|
$job = new ConvertDocumentToMarkdown($document);
|
|
$serialized = serialize($job);
|
|
$unserialized = unserialize($serialized);
|
|
|
|
$this->assertInstanceOf(ConvertDocumentToMarkdown::class, $unserialized);
|
|
|
|
// 使用反射来访问受保护的属性
|
|
$reflection = new \ReflectionClass($unserialized);
|
|
$documentProperty = $reflection->getProperty('document');
|
|
$documentProperty->setAccessible(true);
|
|
$jobDocument = $documentProperty->getValue($unserialized);
|
|
$this->assertEquals($document->id, $jobDocument->id);
|
|
}
|
|
|
|
/**
|
|
* 测试队列任务在高并发下的表现
|
|
*
|
|
* @test
|
|
*/
|
|
public function test_queue_performance_under_load()
|
|
{
|
|
// 创建测试用户
|
|
$user = User::factory()->create();
|
|
|
|
// 创建多个文档
|
|
$documents = Document::factory()->count(10)->create([
|
|
'uploaded_by' => $user->id,
|
|
]);
|
|
|
|
// 使用模拟队列
|
|
Queue::fake();
|
|
|
|
$startTime = microtime(true);
|
|
$startMemory = memory_get_usage();
|
|
|
|
// 批量分发队列任务
|
|
foreach ($documents as $document) {
|
|
Queue::pushOn('default', new ConvertDocumentToMarkdown($document));
|
|
}
|
|
|
|
$endTime = microtime(true);
|
|
$endMemory = memory_get_usage();
|
|
|
|
// 验证性能指标
|
|
$executionTime = $endTime - $startTime;
|
|
$memoryUsage = $endMemory - $startMemory;
|
|
|
|
$this->assertLessThan(1.0, $executionTime, '队列任务分发时间过长');
|
|
$this->assertLessThan(5 * 1024 * 1024, $memoryUsage, '队列任务内存使用过多');
|
|
|
|
// 验证所有任务都已分发
|
|
Queue::assertPushed(ConvertDocumentToMarkdown::class, 10);
|
|
}
|
|
|
|
/**
|
|
* 测试队列任务的错误恢复机制
|
|
*
|
|
* @test
|
|
*/
|
|
public function test_queue_error_recovery()
|
|
{
|
|
// 创建测试文档
|
|
$user = User::factory()->create();
|
|
$document = Document::factory()->create([
|
|
'uploaded_by' => $user->id,
|
|
'title' => '错误恢复测试',
|
|
]);
|
|
|
|
// 创建一个会失败的任务
|
|
$job = new ConvertDocumentToMarkdown($document);
|
|
|
|
// 模拟任务失败
|
|
try {
|
|
$job->failed(new \Exception('模拟任务失败'));
|
|
} catch (\Exception $e) {
|
|
// 预期的异常
|
|
}
|
|
|
|
// 验证失败处理机制工作正常
|
|
$this->assertTrue(true, '错误恢复机制测试完成');
|
|
}
|
|
|
|
/**
|
|
* 测试队列任务的内存清理
|
|
*
|
|
* @test
|
|
*/
|
|
public function test_queue_memory_cleanup()
|
|
{
|
|
$initialMemory = memory_get_usage();
|
|
|
|
// 创建和处理多个任务
|
|
$user = User::factory()->create();
|
|
|
|
for ($i = 0; $i < 5; $i++) {
|
|
$document = Document::factory()->create(['uploaded_by' => $user->id]);
|
|
$job = new ConvertDocumentToMarkdown($document);
|
|
|
|
// 模拟任务处理
|
|
unset($job);
|
|
unset($document);
|
|
}
|
|
|
|
// 强制垃圾回收
|
|
gc_collect_cycles();
|
|
|
|
$finalMemory = memory_get_usage();
|
|
$memoryIncrease = $finalMemory - $initialMemory;
|
|
|
|
// 验证内存没有显著增长
|
|
$this->assertLessThan(2 * 1024 * 1024, $memoryIncrease, '队列任务存在内存泄漏');
|
|
}
|
|
|
|
/**
|
|
* 测试队列配置的动态加载
|
|
*
|
|
* @test
|
|
*/
|
|
public function test_queue_configuration_loading()
|
|
{
|
|
// 验证队列配置可以正确加载
|
|
$queueConfig = config('queue');
|
|
$this->assertIsArray($queueConfig, '队列配置加载失败');
|
|
|
|
// 验证默认连接配置
|
|
$defaultConnection = $queueConfig['default'];
|
|
$this->assertNotEmpty($defaultConnection, '默认队列连接未配置');
|
|
|
|
// 验证连接配置存在
|
|
$connectionConfig = $queueConfig['connections'][$defaultConnection] ?? null;
|
|
$this->assertNotNull($connectionConfig, '队列连接配置不存在');
|
|
$this->assertArrayHasKey('driver', $connectionConfig, '队列驱动未配置');
|
|
}
|
|
|
|
/**
|
|
* 测试队列任务的优先级处理
|
|
*
|
|
* @test
|
|
*/
|
|
public function test_queue_priority_handling()
|
|
{
|
|
// 创建测试数据
|
|
$user = User::factory()->create();
|
|
$highPriorityDoc = Document::factory()->create([
|
|
'uploaded_by' => $user->id,
|
|
'title' => '高优先级文档',
|
|
]);
|
|
$lowPriorityDoc = Document::factory()->create([
|
|
'uploaded_by' => $user->id,
|
|
'title' => '低优先级文档',
|
|
]);
|
|
|
|
// 使用模拟队列
|
|
Queue::fake();
|
|
|
|
// 分发不同优先级的任务
|
|
$highPriorityJob = (new ConvertDocumentToMarkdown($highPriorityDoc))->onQueue('high');
|
|
$lowPriorityJob = (new ConvertDocumentToMarkdown($lowPriorityDoc))->onQueue('default');
|
|
|
|
Queue::push($lowPriorityJob);
|
|
Queue::push($highPriorityJob);
|
|
|
|
// 验证任务已正确分发
|
|
Queue::assertPushed(ConvertDocumentToMarkdown::class, 2);
|
|
}
|
|
|
|
/**
|
|
* 测试队列任务的批处理功能
|
|
*
|
|
* @test
|
|
*/
|
|
public function test_queue_batch_processing()
|
|
{
|
|
// 创建测试数据
|
|
$user = User::factory()->create();
|
|
$documents = Document::factory()->count(3)->create(['uploaded_by' => $user->id]);
|
|
|
|
// 使用模拟队列
|
|
Queue::fake();
|
|
|
|
// 创建批处理任务
|
|
$jobs = $documents->map(function ($document) {
|
|
return new ConvertDocumentToMarkdown($document);
|
|
});
|
|
|
|
// 批量分发任务
|
|
foreach ($jobs as $job) {
|
|
Queue::push($job);
|
|
}
|
|
|
|
// 验证批处理功能
|
|
Queue::assertPushed(ConvertDocumentToMarkdown::class, 3);
|
|
}
|
|
|
|
/**
|
|
* 测试队列任务的超时处理
|
|
*
|
|
* @test
|
|
*/
|
|
public function test_queue_timeout_handling()
|
|
{
|
|
// 创建测试文档
|
|
$user = User::factory()->create();
|
|
$document = Document::factory()->create(['uploaded_by' => $user->id]);
|
|
|
|
// 创建任务并检查超时配置
|
|
$job = new ConvertDocumentToMarkdown($document);
|
|
|
|
$this->assertIsNumeric($job->timeout, '任务超时配置无效');
|
|
$this->assertGreaterThan(0, $job->timeout, '任务超时时间必须大于 0');
|
|
|
|
// 验证超时时间合理
|
|
$this->assertLessThanOrEqual(600, $job->timeout, '任务超时时间过长');
|
|
}
|
|
} |