#include #include "app.hpp" #include #include // ============================================================ // 测试夹具:CmsEngineTest // ============================================================ class CmsEngineTest : public ::testing::Test { protected: CmsEngine engine; void SetUp() override { // 初始化一些事件用于测试 EventRecord evt1; evt1.id = "EVT-001"; evt1.priority = 100; evt1.status = EventStatus::Pending; engine.ingestEvent(evt1); EventRecord evt2; evt2.id = "EVT-002"; evt2.priority = 200; evt2.status = EventStatus::Pending; engine.ingestEvent(evt2); EventRecord evt3; evt3.id = "EVT-003"; evt3.priority = 50; evt3.status = EventStatus::Generated; // 非 Pending 状态 engine.ingestEvent(evt3); } void TearDown() override { // 清理工作(如果需要) } }; // ============================================================ // 测试用例:processPendingEvents // ============================================================ /** * @requirement(name="待处理事件处理", id="REQ-EVENT-PROC-001") * 系统需遍历事件库中所有 Pending 状态的事件,自动将其状态标记为 Generated, * 并据此生成一个对应的 TaskPlan 草案,实现事件到方案的自动转化。 */ // 正常输入测试:处理所有 Pending 事件 TEST_F(CmsEngineTest, testProcessPendingEventsNormal) { // 执行:处理待处理事件 size_t processedCount = engine.processPendingEvents(); // 验证:应该处理了 2 个 Pending 事件(EVT-001 和 EVT-002) EXPECT_EQ(processedCount, 2); // 验证:事件状态已更新 const EventRecord* evt1 = engine.findEventById("EVT-001"); ASSERT_NE(evt1, nullptr); EXPECT_EQ(evt1->status, EventStatus::Generated); const EventRecord* evt2 = engine.findEventById("EVT-002"); ASSERT_NE(evt2, nullptr); EXPECT_EQ(evt2->status, EventStatus::Generated); // 验证:非 Pending 事件状态不变 const EventRecord* evt3 = engine.findEventById("EVT-003"); ASSERT_NE(evt3, nullptr); EXPECT_EQ(evt3->status, EventStatus::Generated); // 原本就是 Generated // 验证:生成了对应的 TaskPlan const std::vector& plans = engine.getAllPlans(); EXPECT_EQ(plans.size(), 2); // 验证第一个方案的属性 EXPECT_EQ(plans[0].name, "AutoPlan-EVT-001"); EXPECT_EQ(plans[0].type, PlanType::Centralized); EXPECT_EQ(plans[0].status, PlanStatus::Drafting); EXPECT_EQ(plans[0].relatedEventId, "EVT-001"); EXPECT_FLOAT_EQ(plans[0].resourceQuota, 0.5); EXPECT_EQ(plans[0].constraints, "自动生成约束"); // 验证第二个方案的属性 EXPECT_EQ(plans[1].name, "AutoPlan-EVT-002"); EXPECT_EQ(plans[1].relatedEventId, "EVT-002"); } // 边界值测试:没有 Pending 事件 TEST_F(CmsEngineTest, testProcessPendingEventsNoPending) { // 先处理所有 Pending 事件 engine.processPendingEvents(); // 再次调用,应该没有 Pending 事件了 size_t processedCount = engine.processPendingEvents(); // 验证:处理数量为 0 EXPECT_EQ(processedCount, 0); // 验证:方案数量没有增加 const std::vector& plans = engine.getAllPlans(); EXPECT_EQ(plans.size(), 2); // 仍然是第一次处理生成的 2 个方案 } // 边界值测试:事件列表为空 TEST_F(CmsEngineTest, testProcessPendingEventsEmptyEvents) { // 创建一个新的空引擎 CmsEngine emptyEngine; // 执行:处理待处理事件 size_t processedCount = emptyEngine.processPendingEvents(); // 验证:处理数量为 0 EXPECT_EQ(processedCount, 0); // 验证:方案列表为空 const std::vector& plans = emptyEngine.getAllPlans(); EXPECT_TRUE(plans.empty()); } // 特殊场景测试:多次调用 processPendingEvents TEST_F(CmsEngineTest, testProcessPendingEventsMultipleCalls) { // 第一次调用 size_t firstCount = engine.processPendingEvents(); EXPECT_EQ(firstCount, 2); // 第二次调用(已经没有 Pending 事件了) size_t secondCount = engine.processPendingEvents(); EXPECT_EQ(secondCount, 0); // 验证:方案数量为 2(只有第一次生成的) const std::vector& plans = engine.getAllPlans(); EXPECT_EQ(plans.size(), 2); } // ============================================================ // 测试用例:findEventById // ============================================================ /** * @requirement(name="事件查询", id="REQ-EVENT-QUERY-001") * 系统需支持根据事件 ID 在事件库中查找对应的事件记录, * 找到则返回事件指针,未找到返回 nullptr。 */ // 正常输入测试:查找存在的事件 TEST_F(CmsEngineTest, testFindEventByIdNormal) { const EventRecord* evt = engine.findEventById("EVT-001"); // 验证:找到事件 ASSERT_NE(evt, nullptr); EXPECT_EQ(evt->id, "EVT-001"); EXPECT_EQ(evt->priority, 100); EXPECT_EQ(evt->status, EventStatus::Pending); } // 边界值测试:查找不存在的事件 TEST_F(CmsEngineTest, testFindEventByIdNotFound) { const EventRecord* evt = engine.findEventById("NONEXISTENT"); // 验证:返回 nullptr EXPECT_EQ(evt, nullptr); } // 边界值测试:查找空字符串 ID TEST_F(CmsEngineTest, testFindEventByIdEmptyId) { const EventRecord* evt = engine.findEventById(""); // 验证:返回 nullptr(因为事件 ID 不能为空,所以不会有空 ID 的事件) EXPECT_EQ(evt, nullptr); } // 边界值测试:查找特殊字符 ID TEST_F(CmsEngineTest, testFindEventByIdSpecialChars) { const EventRecord* evt = engine.findEventById("EVT-@#$"); // 验证:返回 nullptr(不存在该事件) EXPECT_EQ(evt, nullptr); } // 特殊场景测试:查找已处理的事件(状态已改变) TEST_F(CmsEngineTest, testFindEventByIdAfterProcessing) { // 先处理事件 engine.processPendingEvents(); // 查找已处理的事件 const EventRecord* evt = engine.findEventById("EVT-001"); // 验证:找到事件,且状态已更新 ASSERT_NE(evt, nullptr); EXPECT_EQ(evt->id, "EVT-001"); EXPECT_EQ(evt->status, EventStatus::Generated); } // ============================================================ // 测试用例:createTaskPlan // ============================================================ /** * @requirement(name="任务方案创建", id="REQ-PLAN-CREATE-001") * 系统需校验方案名称非空后,为其分配系统 ID 并存入方案库, * 确保方案数据的完整性和可追溯性。 */ // 正常输入测试:创建有效的任务方案 TEST_F(CmsEngineTest, testCreateTaskPlanNormal) { TaskPlan plan; plan.name = "Test Plan"; plan.type = PlanType::Centralized; plan.status = PlanStatus::Drafting; plan.resourceQuota = 0.8; plan.constraints = "测试约束"; // 执行:创建任务方案 bool result = engine.createTaskPlan(plan); // 验证:创建成功 EXPECT_TRUE(result); // 验证:方案 ID 已被填充(格式为 ID-xxxxx) EXPECT_FALSE(plan.id.empty()); EXPECT_EQ(plan.id.substr(0, 3), "ID-"); EXPECT_EQ(plan.id.length(), 8); // "ID-" + 5 位数字 // 验证:创建时间已被填充 // 由于 createTime 是 system_clock::time_point,我们无法直接比较, // 但可以确认它已经被设置(不为默认值) auto now = std::chrono::system_clock::now(); auto diff = std::chrono::duration_cast(now - plan.createTime).count(); EXPECT_LE(diff, 1); // 创建时间应该在 1 秒内 // 验证:方案已被添加到方案库 const std::vector& plans = engine.getAllPlans(); EXPECT_EQ(plans.size(), 1); EXPECT_EQ(plans[0].id, plan.id); EXPECT_EQ(plans[0].name, "Test Plan"); EXPECT_EQ(plans[0].type, PlanType::Centralized); EXPECT_EQ(plans[0].status, PlanStatus::Drafting); EXPECT_FLOAT_EQ(plans[0].resourceQuota, 0.8); EXPECT_EQ(plans[0].constraints, "测试约束"); } // 边界值测试:创建名称为空的方案 TEST_F(CmsEngineTest, testCreateTaskPlanEmptyName) { TaskPlan plan; plan.name = ""; // 空名称 plan.type = PlanType::Centralized; plan.status = PlanStatus::Drafting; // 执行:创建任务方案 bool result = engine.createTaskPlan(plan); // 验证:创建失败 EXPECT_FALSE(result); // 验证:方案 ID 未被填充 EXPECT_TRUE(plan.id.empty()); // 验证:方案未被添加到方案库 const std::vector& plans = engine.getAllPlans(); EXPECT_TRUE(plans.empty()); } // 边界值测试:创建名称为空格的方案 TEST_F(CmsEngineTest, testCreateTaskPlanSpaceName) { TaskPlan plan; plan.name = " "; // 空格名称 plan.type = PlanType::Centralized; plan.status = PlanStatus::Drafting; // 执行:创建任务方案 bool result = engine.createTaskPlan(plan); // 验证:创建成功(因为空格不是空字符串) EXPECT_TRUE(result); // 验证:方案已被添加到方案库 const std::vector& plans = engine.getAllPlans(); EXPECT_EQ(plans.size(), 1); EXPECT_EQ(plans[0].name, " "); } // 特殊场景测试:创建多个方案,验证 ID 自增 TEST_F(CmsEngineTest, testCreateTaskPlanMultiplePlans) { TaskPlan plan1; plan1.name = "Plan 1"; engine.createTaskPlan(plan1); TaskPlan plan2; plan2.name = "Plan 2"; engine.createTaskPlan(plan2); TaskPlan plan3; plan3.name = "Plan 3"; engine.createTaskPlan(plan3); // 验证:生成了 3 个方案 const std::vector& plans = engine.getAllPlans(); EXPECT_EQ(plans.size(), 3); // 验证:ID 自增(ID-00001, ID-00002, ID-00003) EXPECT_EQ(plans[0].id, "ID-00001"); EXPECT_EQ(plans[1].id, "ID-00002"); EXPECT_EQ(plans[2].id, "ID-00003"); // 验证:名称正确 EXPECT_EQ(plans[0].name, "Plan 1"); EXPECT_EQ(plans[1].name, "Plan 2"); EXPECT_EQ(plans[2].name, "Plan 3"); } // 特殊场景测试:创建方案后,通过 findPlanById 验证 TEST_F(CmsEngineTest, testCreateTaskPlanAndFindById) { TaskPlan plan; plan.name = "Findable Plan"; engine.createTaskPlan(plan); // 通过 ID 查找方案 const TaskPlan* foundPlan = engine.findPlanById(plan.id); // 验证:找到方案 ASSERT_NE(foundPlan, nullptr); EXPECT_EQ(foundPlan->id, plan.id); EXPECT_EQ(foundPlan->name, "Findable Plan"); }