#include #include #include #include #include "app.hpp" // ============================================================ // 测试夹具:CmsEngineTest // ============================================================ class CmsEngineTest : public ::testing::Test { protected: CmsEngine engine; // 辅助函数:创建一个有效的事件(注意:EventRecord 没有 timestamp 成员) EventRecord createValidEvent(const std::string& id = "EVT-001", int priority = 100) { EventRecord evt; evt.id = id; evt.priority = priority; evt.status = EventStatus::Pending; return evt; } // 辅助函数:创建多个事件并接入 void ingestMultipleEvents(size_t count) { for (size_t i = 0; i < count; ++i) { std::string id = "EVT-" + std::to_string(i + 1); EventRecord evt = createValidEvent(id, 100); engine.ingestEvent(evt); } } }; // ============================================================ // ingestEvent 测试用例 // ============================================================ /** * @requirement(name="战场事件接入", id="REQ-EVENT-INGEST-001") * 系统需支持从外部事件总线接入原始战场事件,执行基本合法性校验 * (ID 不能为空、优先级范围检查),通过后存入事件库。 */ // 正常输入测试:接入有效事件 TEST_F(CmsEngineTest, testIngestEventValid) { EventRecord evt = createValidEvent("EVT-001", 100); bool result = engine.ingestEvent(evt); EXPECT_TRUE(result); // 验证事件已存入事件库 const EventRecord* found = engine.findEventById("EVT-001"); ASSERT_NE(found, nullptr); EXPECT_EQ(found->id, "EVT-001"); EXPECT_EQ(found->priority, 100); EXPECT_EQ(found->status, EventStatus::Pending); } // 正常输入测试:接入多个事件 TEST_F(CmsEngineTest, testIngestEventMultiple) { EventRecord evt1 = createValidEvent("EVT-001", 50); EventRecord evt2 = createValidEvent("EVT-002", 150); EventRecord evt3 = createValidEvent("EVT-003", 200); EXPECT_TRUE(engine.ingestEvent(evt1)); EXPECT_TRUE(engine.ingestEvent(evt2)); EXPECT_TRUE(engine.ingestEvent(evt3)); // 验证所有事件都已存储 EXPECT_NE(engine.findEventById("EVT-001"), nullptr); EXPECT_NE(engine.findEventById("EVT-002"), nullptr); EXPECT_NE(engine.findEventById("EVT-003"), nullptr); } // 边界值测试:优先级为 0(最小值) TEST_F(CmsEngineTest, testIngestEventPriorityMin) { EventRecord evt = createValidEvent("EVT-001", 0); bool result = engine.ingestEvent(evt); EXPECT_TRUE(result); const EventRecord* found = engine.findEventById("EVT-001"); ASSERT_NE(found, nullptr); EXPECT_EQ(found->priority, 0); } // 边界值测试:优先级为 255(最大值) TEST_F(CmsEngineTest, testIngestEventPriorityMax) { EventRecord evt = createValidEvent("EVT-001", 255); bool result = engine.ingestEvent(evt); EXPECT_TRUE(result); const EventRecord* found = engine.findEventById("EVT-001"); ASSERT_NE(found, nullptr); EXPECT_EQ(found->priority, 255); } // 异常输入测试:空 ID TEST_F(CmsEngineTest, testIngestEventEmptyId) { EventRecord evt = createValidEvent("", 100); bool result = engine.ingestEvent(evt); EXPECT_FALSE(result); // 验证事件未被存储 const EventRecord* found = engine.findEventById(""); EXPECT_EQ(found, nullptr); } // 异常输入测试:优先级超过 255 TEST_F(CmsEngineTest, testIngestEventPriorityOverflow) { EventRecord evt = createValidEvent("EVT-001", 256); bool result = engine.ingestEvent(evt); EXPECT_FALSE(result); // 验证事件未被存储 const EventRecord* found = engine.findEventById("EVT-001"); EXPECT_EQ(found, nullptr); } // 异常输入测试:优先级为负数 TEST_F(CmsEngineTest, testIngestEventPriorityNegative) { EventRecord evt = createValidEvent("EVT-001", -1); bool result = engine.ingestEvent(evt); EXPECT_FALSE(result); const EventRecord* found = engine.findEventById("EVT-001"); EXPECT_EQ(found, nullptr); } // 特殊场景测试:接入重复 ID 的事件(允许重复) TEST_F(CmsEngineTest, testIngestEventDuplicateId) { EventRecord evt1 = createValidEvent("EVT-001", 100); EventRecord evt2 = createValidEvent("EVT-001", 200); EXPECT_TRUE(engine.ingestEvent(evt1)); EXPECT_TRUE(engine.ingestEvent(evt2)); // 验证两个事件都已存储(允许重复 ID) const EventRecord* found = engine.findEventById("EVT-001"); ASSERT_NE(found, nullptr); // findEventById 返回第一个匹配的事件 EXPECT_EQ(found->priority, 100); } // ============================================================ // processPendingEvents 测试用例 // ============================================================ /** * @requirement(name="待处理事件处理", id="REQ-EVENT-PROC-001") * 系统需遍历事件库中所有 Pending 状态的事件,自动将其状态标记为 Generated, * 并据此生成一个对应的 TaskPlan 草案,实现事件到方案的自动转化。 */ // 正常输入测试:处理单个待处理事件 TEST_F(CmsEngineTest, testProcessPendingEventsSingle) { EventRecord evt = createValidEvent("EVT-001", 100); engine.ingestEvent(evt); size_t count = engine.processPendingEvents(); EXPECT_EQ(count, 1); // 验证事件状态已更新 const EventRecord* found = engine.findEventById("EVT-001"); ASSERT_NE(found, nullptr); EXPECT_EQ(found->status, EventStatus::Generated); // 验证生成了对应的方案 const std::vector& plans = engine.getAllPlans(); ASSERT_EQ(plans.size(), 1); EXPECT_EQ(plans[0].relatedEventId, "EVT-001"); EXPECT_EQ(plans[0].name, "AutoPlan-EVT-001"); EXPECT_EQ(plans[0].type, PlanType::Centralized); EXPECT_EQ(plans[0].status, PlanStatus::Drafting); EXPECT_FLOAT_EQ(plans[0].resourceQuota, 0.5f); EXPECT_EQ(plans[0].constraints, "自动生成约束"); } // 正常输入测试:处理多个待处理事件 TEST_F(CmsEngineTest, testProcessPendingEventsMultiple) { ingestMultipleEvents(5); size_t count = engine.processPendingEvents(); EXPECT_EQ(count, 5); // 验证所有事件状态已更新 for (size_t i = 0; i < 5; ++i) { std::string id = "EVT-" + std::to_string(i + 1); const EventRecord* found = engine.findEventById(id); ASSERT_NE(found, nullptr); EXPECT_EQ(found->status, EventStatus::Generated); } // 验证生成了对应数量的方案 const std::vector& plans = engine.getAllPlans(); ASSERT_EQ(plans.size(), 5); for (size_t i = 0; i < 5; ++i) { std::string expectedId = "EVT-" + std::to_string(i + 1); EXPECT_EQ(plans[i].relatedEventId, expectedId); } } // 边界值测试:没有待处理事件 TEST_F(CmsEngineTest, testProcessPendingEventsNone) { size_t count = engine.processPendingEvents(); EXPECT_EQ(count, 0); // 验证没有生成方案 const std::vector& plans = engine.getAllPlans(); EXPECT_TRUE(plans.empty()); } // 边界值测试:事件状态不是 Pending TEST_F(CmsEngineTest, testProcessPendingEventsNonPending) { EventRecord evt = createValidEvent("EVT-001", 100); evt.status = EventStatus::Generated; // 设置为非 Pending 状态 engine.ingestEvent(evt); size_t count = engine.processPendingEvents(); EXPECT_EQ(count, 0); // 验证事件状态未改变 const EventRecord* found = engine.findEventById("EVT-001"); ASSERT_NE(found, nullptr); EXPECT_EQ(found->status, EventStatus::Generated); // 验证没有生成方案 const std::vector& plans = engine.getAllPlans(); EXPECT_TRUE(plans.empty()); } // 特殊场景测试:混合状态的事件 TEST_F(CmsEngineTest, testProcessPendingEventsMixed) { EventRecord evt1 = createValidEvent("EVT-001", 100); // Pending EventRecord evt2 = createValidEvent("EVT-002", 100); evt2.status = EventStatus::Generated; // 非 Pending EventRecord evt3 = createValidEvent("EVT-003", 100); // Pending engine.ingestEvent(evt1); engine.ingestEvent(evt2); engine.ingestEvent(evt3); size_t count = engine.processPendingEvents(); EXPECT_EQ(count, 2); // 只处理了 2 个 Pending 事件 // 验证只有 Pending 事件被处理 const EventRecord* found1 = engine.findEventById("EVT-001"); ASSERT_NE(found1, nullptr); EXPECT_EQ(found1->status, EventStatus::Generated); const EventRecord* found2 = engine.findEventById("EVT-002"); ASSERT_NE(found2, nullptr); EXPECT_EQ(found2->status, EventStatus::Generated); // 保持不变 const EventRecord* found3 = engine.findEventById("EVT-003"); ASSERT_NE(found3, nullptr); EXPECT_EQ(found3->status, EventStatus::Generated); // 验证生成了 2 个方案 const std::vector& plans = engine.getAllPlans(); ASSERT_EQ(plans.size(), 2); EXPECT_EQ(plans[0].relatedEventId, "EVT-001"); EXPECT_EQ(plans[1].relatedEventId, "EVT-003"); } // 特殊场景测试:多次调用 processPendingEvents TEST_F(CmsEngineTest, testProcessPendingEventsMultipleCalls) { EventRecord evt = createValidEvent("EVT-001", 100); engine.ingestEvent(evt); // 第一次调用 size_t count1 = engine.processPendingEvents(); EXPECT_EQ(count1, 1); // 第二次调用,没有 Pending 事件了 size_t count2 = engine.processPendingEvents(); EXPECT_EQ(count2, 0); // 验证只生成了一个方案 const std::vector& plans = engine.getAllPlans(); ASSERT_EQ(plans.size(), 1); } // ============================================================ // findEventById 测试用例 // ============================================================ /** * @requirement(name="事件查询", id="REQ-EVENT-QUERY-001") * 系统需支持根据事件 ID 在事件库中查找对应的事件记录, * 找到则返回事件指针,未找到返回 nullptr。 */ // 正常输入测试:查找存在的事件 TEST_F(CmsEngineTest, testFindEventByIdExisting) { EventRecord evt = createValidEvent("EVT-001", 100); engine.ingestEvent(evt); const EventRecord* found = engine.findEventById("EVT-001"); ASSERT_NE(found, nullptr); EXPECT_EQ(found->id, "EVT-001"); EXPECT_EQ(found->priority, 100); EXPECT_EQ(found->status, EventStatus::Pending); } // 正常输入测试:查找多个事件中的某一个 TEST_F(CmsEngineTest, testFindEventByIdAmongMultiple) { ingestMultipleEvents(10); const EventRecord* found = engine.findEventById("EVT-005"); ASSERT_NE(found, nullptr); EXPECT_EQ(found->id, "EVT-005"); } // 边界值测试:查找空字符串 ID TEST_F(CmsEngineTest, testFindEventByIdEmptyString) { EventRecord evt = createValidEvent("", 100); engine.ingestEvent(evt); const EventRecord* found = engine.findEventById(""); ASSERT_NE(found, nullptr); EXPECT_EQ(found->id, ""); } // 异常输入测试:查找不存在的 ID TEST_F(CmsEngineTest, testFindEventByIdNonExisting) { ingestMultipleEvents(5); const EventRecord* found = engine.findEventById("NONEXISTENT"); EXPECT_EQ(found, nullptr); } // 异常输入测试:在空事件库中查找 TEST_F(CmsEngineTest, testFindEventByIdEmptyStore) { const EventRecord* found = engine.findEventById("EVT-001"); EXPECT_EQ(found, nullptr); } // 特殊场景测试:查找重复 ID 的事件(返回第一个) TEST_F(CmsEngineTest, testFindEventByIdDuplicateIds) { EventRecord evt1 = createValidEvent("EVT-001", 100); EventRecord evt2 = createValidEvent("EVT-001", 200); engine.ingestEvent(evt1); engine.ingestEvent(evt2); const EventRecord* found = engine.findEventById("EVT-001"); ASSERT_NE(found, nullptr); EXPECT_EQ(found->priority, 100); // 返回第一个 } // 特殊场景测试:查找特殊字符 ID TEST_F(CmsEngineTest, testFindEventByIdSpecialChars) { std::string specialId = "EVT-@#$%^&"; EventRecord evt = createValidEvent(specialId, 100); engine.ingestEvent(evt); const EventRecord* found = engine.findEventById(specialId); ASSERT_NE(found, nullptr); EXPECT_EQ(found->id, specialId); } // 特殊场景测试:查找长 ID 字符串 TEST_F(CmsEngineTest, testFindEventByIdLongId) { std::string longId = "EVT-" + std::string(1000, 'a'); EventRecord evt = createValidEvent(longId, 100); engine.ingestEvent(evt); const EventRecord* found = engine.findEventById(longId); ASSERT_NE(found, nullptr); EXPECT_EQ(found->id, longId); }