301 lines
9.1 KiB
C++
301 lines
9.1 KiB
C++
|
|
#include <gtest/gtest.h>
|
|||
|
|
#include <string>
|
|||
|
|
#include <vector>
|
|||
|
|
#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);
|
|||
|
|
}
|