plan_execute_t1/tests/test_app.cpp

301 lines
9.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}