plan_execute_t1/tests/test_cms_engine.cpp

380 lines
11 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 <gmock/gmock.h>
#include "app.hpp"
#include <string>
#include <chrono>
using namespace testing;
// ============================================================================
// Test Fixture for CmsEngine
// ============================================================================
class CmsEngineTest : public ::testing::Test {
protected:
void SetUp() override {
engine = std::make_unique<CmsEngine>();
}
void TearDown() override {
engine.reset();
}
std::unique_ptr<CmsEngine> engine;
};
// ============================================================================
// Tests for CmsEngine Constructor
// ============================================================================
/**
* @brief 测试构造函数初始化系统状态上下文
*
* 验证构造函数正确初始化系统状态上下文,包括模式、一致性标记、切换时间和快照。
*/
TEST_F(CmsEngineTest, testConstructorInitializesSystemContext) {
const auto& context = engine->getSystemContext();
EXPECT_EQ(context.currentMode, RunMode::Idle);
EXPECT_EQ(context.consistencyMark, 0);
auto now = std::chrono::system_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::seconds>(now - context.switchTime).count();
EXPECT_GE(diff, 0);
EXPECT_LT(diff, 5);
EXPECT_THAT(context.contextSnapshot, HasSubstr("\"mode\":\"Idle\""));
EXPECT_THAT(context.contextSnapshot, HasSubstr("\"version\":\"1.0.0\""));
}
/**
* @brief 测试构造函数初始化空容器
*
* 验证构造函数正确初始化所有容器为空。
*/
TEST_F(CmsEngineTest, testConstructorInitializesEmptyContainers) {
EXPECT_EQ(engine->getAllPlans().size(), 0);
std::string summary = engine->getSummary();
EXPECT_THAT(summary, HasSubstr("Events : 0"));
EXPECT_THAT(summary, HasSubstr("Plans : 0"));
EXPECT_THAT(summary, HasSubstr("Templates : 0"));
EXPECT_THAT(summary, HasSubstr("Monitor Nodes : 0"));
EXPECT_THAT(summary, HasSubstr("Active Sessions : 0"));
EXPECT_THAT(summary, HasSubstr("Notifications : 0"));
EXPECT_THAT(summary, HasSubstr("Mode : Idle"));
}
// ============================================================================
// Tests for ingestEvent
// ============================================================================
/**
* @brief 测试正常事件接入
*
* 验证具有有效 ID 和合法优先级的事件能够成功接入。
*/
TEST_F(CmsEngineTest, testIngestEventValidEvent) {
EventRecord event;
event.id = "EVT-001";
event.priority = 100;
event.status = EventStatus::Pending;
bool result = engine->ingestEvent(event);
EXPECT_TRUE(result);
const EventRecord* storedEvent = engine->findEventById("EVT-001");
ASSERT_NE(storedEvent, nullptr);
EXPECT_EQ(storedEvent->id, "EVT-001");
EXPECT_EQ(storedEvent->priority, 100);
EXPECT_EQ(storedEvent->status, EventStatus::Pending);
}
/**
* @brief 测试接入优先级为 0 的事件
*
* 验证优先级为 0最小值的事件能够成功接入。
*/
TEST_F(CmsEngineTest, testIngestEventMinPriority) {
EventRecord event;
event.id = "EVT-002";
event.priority = 0;
event.status = EventStatus::Pending;
bool result = engine->ingestEvent(event);
EXPECT_TRUE(result);
const EventRecord* storedEvent = engine->findEventById("EVT-002");
ASSERT_NE(storedEvent, nullptr);
EXPECT_EQ(storedEvent->priority, 0);
}
/**
* @brief 测试接入优先级为 255 的事件
*
* 验证优先级为 255最大值的事件能够成功接入。
*/
TEST_F(CmsEngineTest, testIngestEventMaxPriority) {
EventRecord event;
event.id = "EVT-003";
event.priority = 255;
event.status = EventStatus::Pending;
bool result = engine->ingestEvent(event);
EXPECT_TRUE(result);
const EventRecord* storedEvent = engine->findEventById("EVT-003");
ASSERT_NE(storedEvent, nullptr);
EXPECT_EQ(storedEvent->priority, 255);
}
/**
* @brief 测试接入空 ID 事件
*
* 验证 ID 为空的事件接入失败,返回 false。
*/
TEST_F(CmsEngineTest, testIngestEventEmptyId) {
EventRecord event;
event.id = "";
event.priority = 100;
event.status = EventStatus::Pending;
bool result = engine->ingestEvent(event);
EXPECT_FALSE(result);
const EventRecord* storedEvent = engine->findEventById("");
EXPECT_EQ(storedEvent, nullptr);
}
/**
* @brief 测试接入优先级超限事件
*
* 验证优先级大于 255 的事件接入失败,返回 false。
*/
TEST_F(CmsEngineTest, testIngestEventPriorityExceedsMax) {
EventRecord event;
event.id = "EVT-004";
event.priority = 256;
event.status = EventStatus::Pending;
bool result = engine->ingestEvent(event);
EXPECT_FALSE(result);
const EventRecord* storedEvent = engine->findEventById("EVT-004");
EXPECT_EQ(storedEvent, nullptr);
}
/**
* @brief 测试接入多个事件
*
* 验证多个事件能够依次成功接入,且事件列表正确增长。
*/
TEST_F(CmsEngineTest, testIngestEventMultipleEvents) {
EventRecord event1;
event1.id = "EVT-005";
event1.priority = 50;
event1.status = EventStatus::Pending;
EventRecord event2;
event2.id = "EVT-006";
event2.priority = 150;
event2.status = EventStatus::Pending;
EXPECT_TRUE(engine->ingestEvent(event1));
EXPECT_TRUE(engine->ingestEvent(event2));
const EventRecord* storedEvent1 = engine->findEventById("EVT-005");
ASSERT_NE(storedEvent1, nullptr);
EXPECT_EQ(storedEvent1->priority, 50);
const EventRecord* storedEvent2 = engine->findEventById("EVT-006");
ASSERT_NE(storedEvent2, nullptr);
EXPECT_EQ(storedEvent2->priority, 150);
}
/**
* @brief 测试接入事件后处理待处理事件
*
* 验证接入 Pending 状态的事件后processPendingEvents 能正确处理。
*/
TEST_F(CmsEngineTest, testIngestEventAndProcessPending) {
EventRecord event;
event.id = "EVT-007";
event.priority = 100;
event.status = EventStatus::Pending;
EXPECT_TRUE(engine->ingestEvent(event));
size_t processedCount = engine->processPendingEvents();
EXPECT_EQ(processedCount, 1);
const EventRecord* storedEvent = engine->findEventById("EVT-007");
ASSERT_NE(storedEvent, nullptr);
EXPECT_EQ(storedEvent->status, EventStatus::Generated);
// 通过 getAllPlans 获取方案列表,验证自动生成的方案
const auto& plans = engine->getAllPlans();
ASSERT_EQ(plans.size(), 1);
EXPECT_EQ(plans[0].relatedEventId, "EVT-007");
EXPECT_EQ(plans[0].name, "AutoPlan-EVT-007");
}
// ============================================================================
// Tests for findPlanById
// ============================================================================
/**
* @brief 测试查找存在的方案
*
* 验证能够通过 ID 查找到已创建的任务方案。
*/
TEST_F(CmsEngineTest, testFindPlanByIdExistingPlan) {
TaskPlan plan;
plan.name = "TestPlan";
plan.type = PlanType::Centralized;
plan.status = PlanStatus::Drafting;
plan.resourceQuota = 0.8;
plan.constraints = "测试约束";
EXPECT_TRUE(engine->createTaskPlan(plan));
std::string planId = plan.id;
EXPECT_FALSE(planId.empty());
const TaskPlan* foundPlan = engine->findPlanById(planId);
ASSERT_NE(foundPlan, nullptr);
EXPECT_EQ(foundPlan->id, planId);
EXPECT_EQ(foundPlan->name, "TestPlan");
EXPECT_EQ(foundPlan->type, PlanType::Centralized);
EXPECT_EQ(foundPlan->status, PlanStatus::Drafting);
EXPECT_DOUBLE_EQ(foundPlan->resourceQuota, 0.8);
EXPECT_EQ(foundPlan->constraints, "测试约束");
}
/**
* @brief 测试查找不存在的方案
*
* 验证查找不存在的 ID 时返回 nullptr。
*/
TEST_F(CmsEngineTest, testFindPlanByIdNonExistentPlan) {
const TaskPlan* foundPlan = engine->findPlanById("NONEXISTENT");
EXPECT_EQ(foundPlan, nullptr);
}
/**
* @brief 测试查找空 ID 方案
*
* 验证查找空字符串 ID 时返回 nullptr。
*/
TEST_F(CmsEngineTest, testFindPlanByIdEmptyId) {
const TaskPlan* foundPlan = engine->findPlanById("");
EXPECT_EQ(foundPlan, nullptr);
}
/**
* @brief 测试查找多个方案中的特定方案
*
* 验证在多个方案中能够正确查找到指定 ID 的方案。
*/
TEST_F(CmsEngineTest, testFindPlanByIdAmongMultiplePlans) {
TaskPlan plan1;
plan1.name = "PlanAlpha";
EXPECT_TRUE(engine->createTaskPlan(plan1));
std::string id1 = plan1.id;
TaskPlan plan2;
plan2.name = "PlanBeta";
EXPECT_TRUE(engine->createTaskPlan(plan2));
std::string id2 = plan2.id;
TaskPlan plan3;
plan3.name = "PlanGamma";
EXPECT_TRUE(engine->createTaskPlan(plan3));
std::string id3 = plan3.id;
EXPECT_NE(id1, id2);
EXPECT_NE(id2, id3);
EXPECT_NE(id1, id3);
const TaskPlan* foundPlan = engine->findPlanById(id2);
ASSERT_NE(foundPlan, nullptr);
EXPECT_EQ(foundPlan->id, id2);
EXPECT_EQ(foundPlan->name, "PlanBeta");
foundPlan = engine->findPlanById(id1);
ASSERT_NE(foundPlan, nullptr);
EXPECT_EQ(foundPlan->id, id1);
EXPECT_EQ(foundPlan->name, "PlanAlpha");
foundPlan = engine->findPlanById(id3);
ASSERT_NE(foundPlan, nullptr);
EXPECT_EQ(foundPlan->id, id3);
EXPECT_EQ(foundPlan->name, "PlanGamma");
}
/**
* @brief 测试查找已更新状态的方案
*
* 验证方案状态更新后仍能查找到,且状态正确。
*/
TEST_F(CmsEngineTest, testFindPlanByIdAfterStatusUpdate) {
TaskPlan plan;
plan.name = "StatusTestPlan";
EXPECT_TRUE(engine->createTaskPlan(plan));
std::string planId = plan.id;
EXPECT_TRUE(engine->updatePlanStatus(planId, PlanStatus::Approved));
const TaskPlan* foundPlan = engine->findPlanById(planId);
ASSERT_NE(foundPlan, nullptr);
EXPECT_EQ(foundPlan->status, PlanStatus::Approved);
}
/**
* @brief 测试查找通过事件处理生成的方案
*
* 验证通过 processPendingEvents 自动生成的方案能够被正确查找。
*/
TEST_F(CmsEngineTest, testFindPlanByIdGeneratedFromEvent) {
EventRecord event;
event.id = "EVT-GEN-001";
event.priority = 100;
event.status = EventStatus::Pending;
EXPECT_TRUE(engine->ingestEvent(event));
size_t processedCount = engine->processPendingEvents();
EXPECT_EQ(processedCount, 1);
// 通过 getAllPlans 获取方案列表,验证自动生成的方案
const auto& plans = engine->getAllPlans();
ASSERT_EQ(plans.size(), 1);
std::string planId = plans[0].id;
EXPECT_FALSE(planId.empty());
const TaskPlan* foundPlan = engine->findPlanById(planId);
ASSERT_NE(foundPlan, nullptr);
EXPECT_EQ(foundPlan->relatedEventId, "EVT-GEN-001");
EXPECT_EQ(foundPlan->name, "AutoPlan-EVT-GEN-001");
EXPECT_EQ(foundPlan->type, PlanType::Centralized);
EXPECT_EQ(foundPlan->status, PlanStatus::Drafting);
EXPECT_DOUBLE_EQ(foundPlan->resourceQuota, 0.5);
EXPECT_EQ(foundPlan->constraints, "自动生成约束");
}
/**
* @brief 测试查找方案时的常量正确性
*
* 验证 const 版本的 findPlanById 返回的指针指向常量对象。
*/
TEST_F(CmsEngineTest, testFindPlanByIdConstCorrectness) {
TaskPlan plan;
plan.name = "ConstTestPlan";
EXPECT_TRUE(engine->createTaskPlan(plan));
std::string planId = plan.id;
const CmsEngine& constEngine = *engine;
const TaskPlan* foundPlan = constEngine.findPlanById(planId);
ASSERT_NE(foundPlan, nullptr);
EXPECT_EQ(foundPlan->id, planId);
EXPECT_EQ(foundPlan->name, "ConstTestPlan");
}