From df0fff4ed85305c0dd90545f2521775682fce6dc Mon Sep 17 00:00:00 2001 From: lids <1713278948@qq.com> Date: Mon, 25 May 2026 16:33:59 +0800 Subject: [PATCH] =?UTF-8?q?AI=20=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/CMakeLists.txt | 25 +++ tests/test_app.cpp | 429 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 454 insertions(+) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/test_app.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..4cb68f5 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.10.0) +project(test_plan_execute_t1) +include(FetchContent) +if (MSVC) + add_compile_options(/utf-8) +endif() +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include) + +include(CTest) +enable_testing() + +add_executable(test_plan_execute_t1 test_app.cpp ../src/app.cpp) + +target_link_libraries(test_plan_execute_t1 gtest gmock gtest_main) +include(GoogleTest) +gtest_discover_tests(test_plan_execute_t1) \ No newline at end of file diff --git a/tests/test_app.cpp b/tests/test_app.cpp new file mode 100644 index 0000000..b542427 --- /dev/null +++ b/tests/test_app.cpp @@ -0,0 +1,429 @@ +#include +#include +#include "app.hpp" +#include +#include +#include + +using namespace testing; + +// ============================================================================ +// 测试套件:CmsEngine::processPendingEvents +// ============================================================================ + +/** + * @brief 测试 processPendingEvents 处理多个Pending事件 + */ +TEST(CmsEngineProcessPendingEventsTest, ProcessMultiplePendingEvents) { + CmsEngine engine; + for (size_t i = 0; i < 3; ++i) { + EventRecord evt; + evt.id = "EVT-" + std::to_string(i); + evt.priority = 100; + evt.status = EventStatus::Pending; + engine.ingestEvent(evt); + } + + size_t processed = engine.processPendingEvents(); + + EXPECT_EQ(processed, 3); + + // 验证所有事件状态已更新为Generated + for (size_t i = 0; i < 3; ++i) { + std::string eventId = "EVT-" + std::to_string(i); + const EventRecord* evt = engine.findEventById(eventId); + ASSERT_NE(evt, nullptr); + EXPECT_EQ(evt->status, EventStatus::Generated); + } + + // 验证生成了对应的TaskPlan + const auto& plans = engine.getAllPlans(); + EXPECT_EQ(plans.size(), 3); + for (size_t i = 0; i < 3; ++i) { + EXPECT_EQ(plans[i].relatedEventId, "EVT-" + std::to_string(i)); + EXPECT_EQ(plans[i].status, PlanStatus::Drafting); + EXPECT_EQ(plans[i].type, PlanType::Centralized); + EXPECT_FALSE(plans[i].name.empty()); + EXPECT_FALSE(plans[i].id.empty()); + } +} + +/** + * @brief 测试 processPendingEvents 处理0个Pending事件(所有事件已处理) + */ +TEST(CmsEngineProcessPendingEventsTest, ProcessZeroPendingEvents) { + CmsEngine engine; + for (size_t i = 0; i < 3; ++i) { + EventRecord evt; + evt.id = "EVT-" + std::to_string(i); + evt.priority = 100; + evt.status = EventStatus::Generated; + engine.ingestEvent(evt); + } + + size_t processed = engine.processPendingEvents(); + + EXPECT_EQ(processed, 0); + + // 验证没有生成新的TaskPlan + const auto& plans = engine.getAllPlans(); + EXPECT_TRUE(plans.empty()); +} + +/** + * @brief 测试 processPendingEvents 处理空事件库 + */ +TEST(CmsEngineProcessPendingEventsTest, ProcessEmptyEventList) { + CmsEngine engine; + + size_t processed = engine.processPendingEvents(); + + EXPECT_EQ(processed, 0); + + const auto& plans = engine.getAllPlans(); + EXPECT_TRUE(plans.empty()); +} + +/** + * @brief 测试 processPendingEvents 处理混合状态事件 + */ +TEST(CmsEngineProcessPendingEventsTest, ProcessMixedStatusEvents) { + CmsEngine engine; + + // 添加2个Pending事件 + for (size_t i = 0; i < 2; ++i) { + EventRecord evt; + evt.id = "PENDING-" + std::to_string(i); + evt.priority = 100; + evt.status = EventStatus::Pending; + engine.ingestEvent(evt); + } + + // 添加2个Generated事件 + for (size_t i = 0; i < 2; ++i) { + EventRecord evt; + evt.id = "GENERATED-" + std::to_string(i); + evt.priority = 100; + evt.status = EventStatus::Generated; + engine.ingestEvent(evt); + } + + size_t processed = engine.processPendingEvents(); + + EXPECT_EQ(processed, 2); + + // 验证只有Pending事件被处理 + const EventRecord* pendingEvt0 = engine.findEventById("PENDING-0"); + ASSERT_NE(pendingEvt0, nullptr); + EXPECT_EQ(pendingEvt0->status, EventStatus::Generated); + + const EventRecord* generatedEvt0 = engine.findEventById("GENERATED-0"); + ASSERT_NE(generatedEvt0, nullptr); + EXPECT_EQ(generatedEvt0->status, EventStatus::Generated); + + // 验证生成了2个TaskPlan + const auto& plans = engine.getAllPlans(); + EXPECT_EQ(plans.size(), 2); +} + +/** + * @brief 测试 processPendingEvents 处理大量Pending事件 + */ +TEST(CmsEngineProcessPendingEventsTest, ProcessLargeNumberOfPendingEvents) { + const size_t largeCount = 1000; + CmsEngine engine; + for (size_t i = 0; i < largeCount; ++i) { + EventRecord evt; + evt.id = "EVT-" + std::to_string(i); + evt.priority = 100; + evt.status = EventStatus::Pending; + engine.ingestEvent(evt); + } + + size_t processed = engine.processPendingEvents(); + + EXPECT_EQ(processed, largeCount); + + const auto& plans = engine.getAllPlans(); + EXPECT_EQ(plans.size(), largeCount); + + // 验证ID生成正确(递增) + for (size_t i = 0; i < largeCount; ++i) { + std::string expectedId = "ID-" + std::string(5 - std::to_string(i + 1).length(), '0') + std::to_string(i + 1); + EXPECT_EQ(plans[i].id, expectedId); + } +} + +// ============================================================================ +// 测试套件:CmsEngine::findEventById +// ============================================================================ + +/** + * @brief 测试 findEventById 查找存在的普通事件 + */ +TEST(CmsEngineFindEventByIdTest, FindExistingEvent) { + CmsEngine engine; + EventRecord evt; + evt.id = "EVT-001"; + evt.priority = 100; + evt.status = EventStatus::Pending; + 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); +} + +/** + * @brief 测试 findEventById 查找不存在的ID + */ +TEST(CmsEngineFindEventByIdTest, FindNonExistentEvent) { + CmsEngine engine; + EventRecord evt; + evt.id = "EVT-001"; + evt.priority = 100; + evt.status = EventStatus::Pending; + engine.ingestEvent(evt); + + const EventRecord* found = engine.findEventById("NONEXISTENT"); + + EXPECT_EQ(found, nullptr); +} + +/** + * @brief 测试 findEventById 查找空字符串ID + */ +TEST(CmsEngineFindEventByIdTest, FindEventWithEmptyId) { + CmsEngine engine; + EventRecord evt; + evt.id = "EVT-001"; + evt.priority = 100; + evt.status = EventStatus::Pending; + engine.ingestEvent(evt); + + const EventRecord* found = engine.findEventById(""); + + EXPECT_EQ(found, nullptr); +} + +/** + * @brief 测试 findEventById 在空事件库中查找 + */ +TEST(CmsEngineFindEventByIdTest, FindEventInEmptyEngine) { + const CmsEngine engine; + + const EventRecord* found = engine.findEventById("ANY-ID"); + + EXPECT_EQ(found, nullptr); +} + +/** + * @brief 测试 findEventById 查找多个事件中的特定事件 + */ +TEST(CmsEngineFindEventByIdTest, FindSpecificEventAmongMany) { + CmsEngine engine; + + // 添加多个事件 + for (int i = 0; i < 10; ++i) { + EventRecord evt; + evt.id = "EVT-" + std::to_string(i); + evt.priority = 50 + i * 10; + evt.status = EventStatus::Pending; + engine.ingestEvent(evt); + } + + const EventRecord* found = engine.findEventById("EVT-5"); + + ASSERT_NE(found, nullptr); + EXPECT_EQ(found->id, "EVT-5"); + EXPECT_EQ(found->priority, 100); +} + +/** + * @brief 测试 findEventById 查找大小写敏感的ID + */ +TEST(CmsEngineFindEventByIdTest, FindEventCaseSensitive) { + CmsEngine engine; + EventRecord evt; + evt.id = "Event-001"; + evt.priority = 100; + evt.status = EventStatus::Pending; + engine.ingestEvent(evt); + + const EventRecord* found = engine.findEventById("event-001"); + + EXPECT_EQ(found, nullptr); + + found = engine.findEventById("Event-001"); + ASSERT_NE(found, nullptr); + EXPECT_EQ(found->id, "Event-001"); +} + +// ============================================================================ +// 测试套件:CmsEngine::createTaskPlan +// ============================================================================ + +/** + * @brief 测试 createTaskPlan 创建有效的任务方案 + */ +TEST(CmsEngineCreateTaskPlanTest, CreateValidTaskPlan) { + CmsEngine engine; + 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"); +} + +/** + * @brief 测试 createTaskPlan 创建名称为空的方案 + */ +TEST(CmsEngineCreateTaskPlanTest, CreateTaskPlanWithEmptyName) { + CmsEngine engine; + 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()); + + // 验证没有方案被添加 + const auto& plans = engine.getAllPlans(); + EXPECT_TRUE(plans.empty()); +} + +/** + * @brief 测试 createTaskPlan 创建名称为空格的方案 + */ +TEST(CmsEngineCreateTaskPlanTest, CreateTaskPlanWithWhitespaceName) { + CmsEngine engine; + 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, " "); +} + +/** + * @brief 测试 createTaskPlan 创建多个方案并验证ID递增 + */ +TEST(CmsEngineCreateTaskPlanTest, CreateMultipleTaskPlans) { + CmsEngine engine; + + TaskPlan plan1; + plan1.name = "Plan1"; + bool result1 = engine.createTaskPlan(plan1); + EXPECT_TRUE(result1); + EXPECT_EQ(plan1.id, "ID-00001"); + + TaskPlan plan2; + plan2.name = "Plan2"; + bool result2 = engine.createTaskPlan(plan2); + EXPECT_TRUE(result2); + EXPECT_EQ(plan2.id, "ID-00002"); + + TaskPlan plan3; + plan3.name = "Plan3"; + bool result3 = engine.createTaskPlan(plan3); + EXPECT_TRUE(result3); + EXPECT_EQ(plan3.id, "ID-00003"); + + const auto& plans = engine.getAllPlans(); + ASSERT_EQ(plans.size(), 3); + EXPECT_EQ(plans[0].id, "ID-00001"); + EXPECT_EQ(plans[1].id, "ID-00002"); + EXPECT_EQ(plans[2].id, "ID-00003"); +} + +/** + * @brief 测试 createTaskPlan 创建包含特殊字符名称的方案 + */ +TEST(CmsEngineCreateTaskPlanTest, CreateTaskPlanWithSpecialCharacters) { + CmsEngine engine; + TaskPlan plan; + plan.name = "Plan_With_Special_Chars!@#$%^&*()"; + 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, "Plan_With_Special_Chars!@#$%^&*()"); +} + +/** + * @brief 测试 createTaskPlan 创建包含超长名称的方案 + */ +TEST(CmsEngineCreateTaskPlanTest, CreateTaskPlanWithLongName) { + CmsEngine engine; + TaskPlan plan; + std::string longName(1000, 'A'); + plan.name = longName; + 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, longName); +} + +/** + * @brief 测试 createTaskPlan 创建方案后通过findPlanById验证 + */ +TEST(CmsEngineCreateTaskPlanTest, CreateAndFindTaskPlan) { + CmsEngine engine; + TaskPlan plan; + plan.name = "TestPlan"; + plan.type = PlanType::Centralized; + plan.status = PlanStatus::Drafting; + + bool result = engine.createTaskPlan(plan); + EXPECT_TRUE(result); + + const TaskPlan* found = engine.findPlanById(plan.id); + ASSERT_NE(found, nullptr); + EXPECT_EQ(found->name, "TestPlan"); + EXPECT_EQ(found->id, plan.id); + EXPECT_EQ(found->type, PlanType::Centralized); + EXPECT_EQ(found->status, PlanStatus::Drafting); +}