plan_execute_t1/tests/test_app.cpp

325 lines
10 KiB
C++
Raw Permalink 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 "app.hpp"
#include <string>
#include <vector>
// ============================================================
// 测试夹具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<TaskPlan>& 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<TaskPlan>& 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<TaskPlan>& 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<TaskPlan>& 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<std::chrono::seconds>(now - plan.createTime).count();
EXPECT_LE(diff, 1); // 创建时间应该在 1 秒内
// 验证:方案已被添加到方案库
const std::vector<TaskPlan>& 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<TaskPlan>& 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<TaskPlan>& 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<TaskPlan>& 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");
}