feat: 实现TCP Server
This commit is contained in:
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
|
||||
namespace tests\flow;
|
||||
|
||||
use app\flow\ProcessEngine;
|
||||
use app\flow\config\ProcessConfig;
|
||||
|
||||
/**
|
||||
* 批次号一致性测试 - 跨机器部署场景
|
||||
*/
|
||||
class BatchConsistencyTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* 测试单机流程批次号一致性
|
||||
*/
|
||||
public function testSingleMachineBatchConsistency(): void
|
||||
{
|
||||
$engine = ProcessEngine::createStandard();
|
||||
|
||||
// 1. 开始清洗
|
||||
$context1 = $this->createContext([
|
||||
'readerType' => '清洗',
|
||||
'currentStep' => '',
|
||||
'endoscopeId' => '',
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$result1 = $engine->execute($context1);
|
||||
$this->assertSuccess($result1);
|
||||
$batchNo = $result1->batchNo;
|
||||
$this->assertNotEmpty($batchNo);
|
||||
|
||||
// 2. 漂洗 - 批次号应该一致
|
||||
$context2 = $this->createContext([
|
||||
'readerType' => '漂洗',
|
||||
'currentStep' => '清洗',
|
||||
'endoscopeId' => '',
|
||||
'batchNo' => $batchNo,
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$this->setStepTime($context2, '清洗', 400);
|
||||
$result2 = $engine->execute($context2);
|
||||
$this->assertSuccess($result2);
|
||||
$this->assertEquals($batchNo, $result2->batchNo);
|
||||
|
||||
// 3. 消毒 - 批次号应该一致
|
||||
$context3 = $this->createContext([
|
||||
'readerType' => '消毒',
|
||||
'currentStep' => '漂洗',
|
||||
'endoscopeId' => '',
|
||||
'batchNo' => $batchNo,
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$this->setStepTime($context3, '漂洗', 200);
|
||||
$result3 = $engine->execute($context3);
|
||||
$this->assertSuccess($result3);
|
||||
$this->assertEquals($batchNo, $result3->batchNo);
|
||||
|
||||
// 4. 终末漂洗 - 批次号应该一致
|
||||
$context4 = $this->createContext([
|
||||
'readerType' => '终末漂洗',
|
||||
'currentStep' => '消毒',
|
||||
'endoscopeId' => '',
|
||||
'batchNo' => $batchNo,
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$this->setStepTime($context4, '消毒', 400);
|
||||
$result4 = $engine->execute($context4);
|
||||
$this->assertSuccess($result4);
|
||||
$this->assertEquals($batchNo, $result4->batchNo);
|
||||
|
||||
// 5. 干燥 - 批次号应该一致
|
||||
$context5 = $this->createContext([
|
||||
'readerType' => '干燥',
|
||||
'currentStep' => '终末漂洗',
|
||||
'endoscopeId' => '',
|
||||
'batchNo' => $batchNo,
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$this->setStepTime($context5, '终末漂洗', 200);
|
||||
$result5 = $engine->execute($context5);
|
||||
$this->assertSuccess($result5);
|
||||
$this->assertEquals($batchNo, $result5->batchNo);
|
||||
|
||||
// 6. 结束 - 批次号应该一致
|
||||
$context6 = $this->createContext([
|
||||
'readerType' => '结束',
|
||||
'currentStep' => '干燥',
|
||||
'endoscopeId' => '',
|
||||
'batchNo' => $batchNo,
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$this->setStepTime($context6, '干燥', 300);
|
||||
$result6 = $engine->execute($context6);
|
||||
$this->assertSuccess($result6);
|
||||
$this->assertEquals($batchNo, $result6->batchNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试多内镜批次号唯一性
|
||||
*/
|
||||
public function testMultiEndoscopeBatchUniqueness(): void
|
||||
{
|
||||
$engine = ProcessEngine::createStandard();
|
||||
|
||||
$batchNos = [];
|
||||
|
||||
// 模拟5个不同内镜同时开始清洗
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$context = $this->createContext([
|
||||
'readerType' => '清洗',
|
||||
'currentStep' => '',
|
||||
'endoscopeId' => '',
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$result = $engine->execute($context);
|
||||
$this->assertSuccess($result);
|
||||
$batchNos[] = $result->batchNo;
|
||||
}
|
||||
|
||||
// 所有批次号应该唯一
|
||||
$uniqueBatchNos = array_unique($batchNos);
|
||||
$this->assertCount(5, $uniqueBatchNos);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试批次号格式正确性
|
||||
*/
|
||||
public function testBatchNoFormat(): void
|
||||
{
|
||||
$context = $this->createContext([
|
||||
'endoscopeId' => '123',
|
||||
]);
|
||||
|
||||
$batchNo = $context->generateBatchNo();
|
||||
|
||||
// 验证格式:YYYYMMDDHHMMSS + 内镜ID(6位) + 随机数(4位)
|
||||
$this->assertEquals(24, strlen($batchNo));
|
||||
$this->assertMatchesRegularExpression('/^\d{14}\d{6}\d{4}$/', $batchNo);
|
||||
|
||||
// 验证日期部分
|
||||
$datePart = substr($batchNo, 0, 8);
|
||||
$this->assertEquals(date('Ymd'), $datePart);
|
||||
|
||||
// 验证内镜ID部分
|
||||
$endoscopePart = substr($batchNo, 14, 6);
|
||||
$this->assertEquals('000123', $endoscopePart);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试批次号不随时间变化(同一流程内)
|
||||
*/
|
||||
public function testBatchNoStability(): void
|
||||
{
|
||||
$engine = ProcessEngine::createStandard();
|
||||
|
||||
$context1 = $this->createContext([
|
||||
'readerType' => '清洗',
|
||||
'currentStep' => '',
|
||||
'endoscopeId' => '',
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$result1 = $engine->execute($context1);
|
||||
$batchNo1 = $result1->batchNo;
|
||||
|
||||
// 模拟时间流逝(实际测试中无法真正等待,所以直接验证)
|
||||
$context2 = $this->createContext([
|
||||
'readerType' => '漂洗',
|
||||
'currentStep' => '清洗',
|
||||
'endoscopeId' => '',
|
||||
'batchNo' => $batchNo1,
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$this->setStepTime($context2, '清洗', 400);
|
||||
$result2 = $engine->execute($context2);
|
||||
|
||||
// 批次号应该保持不变
|
||||
$this->assertEquals($batchNo1, $result2->batchNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试新流程生成新批次号
|
||||
*/
|
||||
public function testNewProcessGeneratesNewBatchNo(): void
|
||||
{
|
||||
$engine = ProcessEngine::createStandard();
|
||||
|
||||
// 第一个流程
|
||||
$context1 = $this->createContext([
|
||||
'readerType' => '清洗',
|
||||
'currentStep' => '',
|
||||
'endoscopeId' => '',
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$result1 = $engine->execute($context1);
|
||||
$batchNo1 = $result1->batchNo;
|
||||
|
||||
// 完成第一个流程
|
||||
$contextEnd = $this->createContext([
|
||||
'readerType' => '结束',
|
||||
'currentStep' => '清洗',
|
||||
'endoscopeId' => '',
|
||||
'batchNo' => $batchNo1,
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$engine->execute($contextEnd);
|
||||
|
||||
// 第二个流程(新流程)
|
||||
$context2 = $this->createContext([
|
||||
'readerType' => '清洗',
|
||||
'currentStep' => '结束', // 上一步已结束
|
||||
'endoscopeId' => '',
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$result2 = $engine->execute($context2);
|
||||
$batchNo2 = $result2->batchNo;
|
||||
|
||||
// 新流程应该有新的批次号
|
||||
$this->assertNotEquals($batchNo1, $batchNo2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试分布式场景下的批次号一致性(模拟)
|
||||
*/
|
||||
public function testDistributedBatchConsistency(): void
|
||||
{
|
||||
// 模拟机器A(清洗)
|
||||
$engineA = ProcessEngine::createStandard();
|
||||
$contextA = $this->createContext([
|
||||
'readerType' => '清洗',
|
||||
'currentStep' => '',
|
||||
'endoscopeId' => '',
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$resultA = $engineA->execute($contextA);
|
||||
$batchNo = $resultA->batchNo;
|
||||
|
||||
// 模拟机器B(消毒)- 从数据库获取批次号
|
||||
$engineB = ProcessEngine::createStandard();
|
||||
$contextB = $this->createContext([
|
||||
'readerType' => '消毒',
|
||||
'currentStep' => '漂洗',
|
||||
'endoscopeId' => '',
|
||||
'batchNo' => $batchNo, // 从数据库获取的批次号
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$resultB = $engineB->execute($contextB);
|
||||
|
||||
// 批次号应该一致
|
||||
$this->assertEquals($batchNo, $resultB->batchNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试批次号在错误情况下的保持
|
||||
*/
|
||||
public function testBatchNoPreservedOnError(): void
|
||||
{
|
||||
$engine = ProcessEngine::createStandard();
|
||||
|
||||
// 开始清洗
|
||||
$context1 = $this->createContext([
|
||||
'readerType' => '清洗',
|
||||
'currentStep' => '',
|
||||
'endoscopeId' => '',
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$result1 = $engine->execute($context1);
|
||||
$batchNo = $result1->batchNo;
|
||||
|
||||
// 完成漂洗
|
||||
$contextRinse = $this->createContext([
|
||||
'readerType' => '漂洗',
|
||||
'currentStep' => '清洗',
|
||||
'endoscopeId' => '',
|
||||
'batchNo' => $batchNo,
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$this->setStepTime($contextRinse, '清洗', 400); // 清洗时间足够
|
||||
$resultRinse = $engine->execute($contextRinse);
|
||||
$this->assertSuccess($resultRinse);
|
||||
|
||||
// 尝试再次漂洗(重复刷漂洗读卡器,时间验证会失败)
|
||||
$context2 = $this->createContext([
|
||||
'readerType' => '漂洗',
|
||||
'currentStep' => '漂洗', // 当前已经是漂洗
|
||||
'endoscopeId' => '',
|
||||
'batchNo' => $batchNo,
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
// 设置漂洗步骤的上次时间为刚刚(时间不足)
|
||||
$context2->setStepLastTime('漂洗', date('Y-m-d H:i:s', time() - 30));
|
||||
$result2 = $engine->execute($context2);
|
||||
|
||||
// 执行失败(重复步骤或时间不足),但批次号应该保持不变
|
||||
$this->assertEquals($batchNo, $result2->batchNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试不同流程类型的批次号
|
||||
*/
|
||||
public function testBatchNoWithDifferentProcessTypes(): void
|
||||
{
|
||||
$engine = ProcessEngine::createStandard();
|
||||
|
||||
// 手工洗流程
|
||||
$context1 = $this->createContext([
|
||||
'readerType' => '清洗',
|
||||
'currentStep' => '',
|
||||
'endoscopeId' => '',
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$result1 = $engine->execute($context1);
|
||||
$batchNo1 = $result1->batchNo;
|
||||
$this->assertEquals('手工洗', $result1->processType);
|
||||
|
||||
// 机洗流程
|
||||
$engineMachine = ProcessEngine::createMachineWash();
|
||||
$context2 = $this->createContext([
|
||||
'readerType' => '机洗', // 使用机洗读卡器
|
||||
'currentStep' => '',
|
||||
'endoscopeId' => '',
|
||||
'morningWashed' => true,
|
||||
]);
|
||||
$result2 = $engineMachine->execute($context2);
|
||||
$batchNo2 = $result2->batchNo;
|
||||
$this->assertEquals('机洗', $result2->processType);
|
||||
|
||||
// 不同流程的批次号应该不同
|
||||
$this->assertNotEquals($batchNo1, $batchNo2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user