#include #include #include #include "app.hpp" // ============================================================ // 测试夹具:CmsEngineTest // ============================================================ class CmsEngineTest : public ::testing::Test { protected: CmsEngine engine; void SetUp() override { // 每个测试用例开始前重置引擎状态 // 注意:CmsEngine 构造函数已初始化,但 plans_ 为空 } void TearDown() override { // 清理(如果需要) } }; // ============================================================ // 测试用例:createTaskPlan // ============================================================ /** * @requirement(name="任务方案创建", id="REQ-PLAN-CREATE-001") * 系统需校验方案名称非空后,为其分配系统 ID 并存入方案库, * 确保方案数据的完整性和可追溯性。 */ // 正常输入测试:创建有效方案 TEST_F(CmsEngineTest, testCreateTaskPlanNormal) { TaskPlan plan; plan.name = "TestPlan"; plan.type = PlanType::Centralized; plan.status = PlanStatus::Drafting; plan.resourceQuota = 0.8; plan.constraints = "无约束"; bool result = engine.createTaskPlan(plan); EXPECT_TRUE(result); EXPECT_FALSE(plan.id.empty()); EXPECT_EQ(plan.name, "TestPlan"); EXPECT_EQ(plan.type, PlanType::Centralized); EXPECT_EQ(plan.status, PlanStatus::Drafting); EXPECT_EQ(plan.resourceQuota, 0.8); EXPECT_EQ(plan.constraints, "无约束"); // 验证方案已存入引擎 const auto& plans = engine.getAllPlans(); ASSERT_EQ(plans.size(), 1); EXPECT_EQ(plans[0].id, plan.id); EXPECT_EQ(plans[0].name, "TestPlan"); } // 边界值测试:名称为空字符串 TEST_F(CmsEngineTest, testCreateTaskPlanEmptyName) { TaskPlan plan; plan.name = ""; plan.type = PlanType::Centralized; plan.status = PlanStatus::Drafting; bool result = engine.createTaskPlan(plan); EXPECT_FALSE(result); EXPECT_TRUE(plan.id.empty()); // 不应分配 ID // 验证方案未存入引擎 const auto& plans = engine.getAllPlans(); EXPECT_EQ(plans.size(), 0); } // 边界值测试:名称为空白字符串(仅空格) TEST_F(CmsEngineTest, testCreateTaskPlanWhitespaceName) { TaskPlan plan; plan.name = " "; plan.type = PlanType::Centralized; plan.status = PlanStatus::Drafting; bool result = engine.createTaskPlan(plan); EXPECT_TRUE(result); // 空白字符串不为空,应视为合法 EXPECT_FALSE(plan.id.empty()); const auto& plans = engine.getAllPlans(); ASSERT_EQ(plans.size(), 1); EXPECT_EQ(plans[0].name, " "); } // 边界值测试:名称长度极长 TEST_F(CmsEngineTest, testCreateTaskPlanLongName) { TaskPlan plan; plan.name = std::string(1000, 'A'); // 1000 个字符 plan.type = PlanType::Centralized; plan.status = PlanStatus::Drafting; bool result = engine.createTaskPlan(plan); EXPECT_TRUE(result); EXPECT_FALSE(plan.id.empty()); const auto& plans = engine.getAllPlans(); ASSERT_EQ(plans.size(), 1); EXPECT_EQ(plans[0].name, std::string(1000, 'A')); } // 异常输入测试:创建多个方案,验证 ID 唯一性 TEST_F(CmsEngineTest, testCreateTaskPlanMultiplePlans) { TaskPlan plan1; plan1.name = "Plan1"; TaskPlan plan2; plan2.name = "Plan2"; TaskPlan plan3; plan3.name = "Plan3"; EXPECT_TRUE(engine.createTaskPlan(plan1)); EXPECT_TRUE(engine.createTaskPlan(plan2)); EXPECT_TRUE(engine.createTaskPlan(plan3)); // 验证 ID 唯一性 EXPECT_NE(plan1.id, plan2.id); EXPECT_NE(plan1.id, plan3.id); EXPECT_NE(plan2.id, plan3.id); // 验证方案数量 const auto& plans = engine.getAllPlans(); ASSERT_EQ(plans.size(), 3); } // 特殊场景测试:创建方案后,验证 createTime 被设置 TEST_F(CmsEngineTest, testCreateTaskPlanCreateTimeSet) { TaskPlan plan; plan.name = "TimeTest"; plan.type = PlanType::Centralized; plan.status = PlanStatus::Drafting; auto before = std::chrono::system_clock::now(); bool result = engine.createTaskPlan(plan); auto after = std::chrono::system_clock::now(); EXPECT_TRUE(result); EXPECT_GE(plan.createTime, before); EXPECT_LE(plan.createTime, after); } // ============================================================ // 测试用例:getAllPlans // ============================================================ /** * @requirement(name="任务方案列表查询", id="REQ-PLAN-LIST-001") * 系统需返回全部任务方案列表的引用,以支撑方案全局视图展示。 */ // 正常输入测试:空列表 TEST_F(CmsEngineTest, testGetAllPlansEmpty) { const auto& plans = engine.getAllPlans(); EXPECT_TRUE(plans.empty()); EXPECT_EQ(plans.size(), 0); } // 正常输入测试:包含多个方案 TEST_F(CmsEngineTest, testGetAllPlansWithPlans) { TaskPlan plan1; plan1.name = "Plan1"; TaskPlan plan2; plan2.name = "Plan2"; TaskPlan plan3; plan3.name = "Plan3"; engine.createTaskPlan(plan1); engine.createTaskPlan(plan2); engine.createTaskPlan(plan3); const auto& plans = engine.getAllPlans(); ASSERT_EQ(plans.size(), 3); EXPECT_EQ(plans[0].name, "Plan1"); EXPECT_EQ(plans[1].name, "Plan2"); EXPECT_EQ(plans[2].name, "Plan3"); } // 边界值测试:验证返回的是常量引用,不可修改 TEST_F(CmsEngineTest, testGetAllPlansConstReference) { // 编译时验证:const auto& 可以绑定,auto& 会编译错误 const auto& plans = engine.getAllPlans(); EXPECT_TRUE(plans.empty()); // 以下代码如果取消注释,编译会失败(因为返回 const 引用) // plans.push_back(TaskPlan()); // 编译错误 } // 特殊场景测试:多次调用返回相同引用 TEST_F(CmsEngineTest, testGetAllPlansSameReference) { const auto& plans1 = engine.getAllPlans(); const auto& plans2 = engine.getAllPlans(); EXPECT_EQ(&plans1, &plans2); // 应为同一对象 } // ============================================================ // 测试用例:findPlanById // ============================================================ /** * @requirement(name="任务方案查找", id="REQ-PLAN-FIND-001") * 系统需支持根据任务 ID 在方案库中遍历查找对应方案, * 找到返回方案指针,未找到返回 nullptr。 */ // 正常输入测试:查找存在的方案 TEST_F(CmsEngineTest, testFindPlanByIdExisting) { TaskPlan plan; plan.name = "TestPlan"; plan.type = PlanType::Centralized; plan.status = PlanStatus::Drafting; engine.createTaskPlan(plan); const TaskPlan* found = engine.findPlanById(plan.id); ASSERT_NE(found, nullptr); EXPECT_EQ(found->id, plan.id); EXPECT_EQ(found->name, "TestPlan"); EXPECT_EQ(found->type, PlanType::Centralized); EXPECT_EQ(found->status, PlanStatus::Drafting); } // 边界值测试:查找不存在的 ID TEST_F(CmsEngineTest, testFindPlanByIdNonExisting) { const TaskPlan* found = engine.findPlanById("NON_EXISTENT_ID"); EXPECT_EQ(found, nullptr); } // 边界值测试:查找空字符串 ID TEST_F(CmsEngineTest, testFindPlanByIdEmptyId) { TaskPlan plan; plan.name = "TestPlan"; engine.createTaskPlan(plan); const TaskPlan* found = engine.findPlanById(""); EXPECT_EQ(found, nullptr); } // 边界值测试:在空列表中查找 TEST_F(CmsEngineTest, testFindPlanByIdEmptyList) { const TaskPlan* found = engine.findPlanById("ANY_ID"); EXPECT_EQ(found, nullptr); } // 异常输入测试:查找 ID 格式异常 TEST_F(CmsEngineTest, testFindPlanByIdInvalidFormat) { TaskPlan plan; plan.name = "TestPlan"; engine.createTaskPlan(plan); // 查找类似但不同的 ID const TaskPlan* found = engine.findPlanById(plan.id + "_extra"); EXPECT_EQ(found, nullptr); } // 特殊场景测试:多个方案中查找特定方案 TEST_F(CmsEngineTest, testFindPlanByIdMultiplePlans) { TaskPlan plan1; plan1.name = "Plan1"; TaskPlan plan2; plan2.name = "Plan2"; TaskPlan plan3; plan3.name = "Plan3"; engine.createTaskPlan(plan1); engine.createTaskPlan(plan2); engine.createTaskPlan(plan3); // 查找中间方案 const TaskPlan* found = engine.findPlanById(plan2.id); ASSERT_NE(found, nullptr); EXPECT_EQ(found->name, "Plan2"); // 查找最后一个方案 found = engine.findPlanById(plan3.id); ASSERT_NE(found, nullptr); EXPECT_EQ(found->name, "Plan3"); } // 特殊场景测试:查找后修改方案(通过非 const 方法) TEST_F(CmsEngineTest, testFindPlanByIdAndModify) { TaskPlan plan; plan.name = "TestPlan"; engine.createTaskPlan(plan); // 通过 findPlanById 获取 const 指针,不能修改 const TaskPlan* found = engine.findPlanById(plan.id); ASSERT_NE(found, nullptr); EXPECT_EQ(found->status, PlanStatus::Drafting); // 通过 updatePlanStatus 修改状态 bool updated = engine.updatePlanStatus(plan.id, PlanStatus::Completed); EXPECT_TRUE(updated); // 再次查找,验证状态已更新 found = engine.findPlanById(plan.id); ASSERT_NE(found, nullptr); EXPECT_EQ(found->status, PlanStatus::Completed); }