From b52552cd65a2f93d195c277871359500df31254f Mon Sep 17 00:00:00 2001 From: linianlin Date: Wed, 20 May 2026 16:35:09 +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 | 163 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 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..ff2e94c --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.10.0) +project(test_task_plan) +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_task_plan test_app.cpp ../src/app.cpp) + +target_link_libraries(test_task_plan gtest gmock gtest_main) +include(GoogleTest) +gtest_discover_tests(test_task_plan) \ No newline at end of file diff --git a/tests/test_app.cpp b/tests/test_app.cpp new file mode 100644 index 0000000..795c000 --- /dev/null +++ b/tests/test_app.cpp @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include + +// 模拟 app.hpp 中的类型定义,确保测试文件可独立编译 +namespace etms { +enum class EventStatus { Received, Processed, PendingTask, Rejected, TaskGenerated, Unknown }; +struct Event { + int id; std::string event_id; std::string event_type; std::time_t timestamp; + int level; double longitude; double latitude; std::string description; + EventStatus status; std::time_t create_time; +}; +struct KbVersion { std::string version_id; std::string description; std::time_t release_time; std::string status; }; +struct TaskTemplate { std::string template_id; std::string name; std::string kb_version_id; std::string path; std::string applicable_type; std::time_t create_time; }; + +// 声明被测函数 +std::vector GetAvailableKbVersions(); +std::vector GetAvailableTemplates(); +bool AdvanceEventStatus(Event& evt); +void SortEventsByLevelDesc(std::vector& events); +void SortEventsByTimeAsc(std::vector& events); +} // namespace etms + +// ================= 测试用例实现 ================= + +// 1. GetAvailableKbVersions +TEST(testGetAvailableKbVersions, NormalInput_ReturnsThreeVersions) { + auto versions = etms::GetAvailableKbVersions(); + EXPECT_EQ(versions.size(), 3); + EXPECT_EQ(versions[0].version_id, "KB-V1.0"); + EXPECT_EQ(versions[1].version_id, "KB-V1.1"); + EXPECT_EQ(versions[2].version_id, "KB-V2.0"); +} + +TEST(testGetAvailableKbVersions, Boundary_CheckStatusField) { + auto versions = etms::GetAvailableKbVersions(); + EXPECT_EQ(versions[0].status, "Active"); + EXPECT_EQ(versions[2].status, "Deprecated"); +} + +// 2. GetAvailableTemplates +TEST(testGetAvailableTemplates, NormalInput_ReturnsThreeTemplates) { + auto templates = etms::GetAvailableTemplates(); + EXPECT_EQ(templates.size(), 3); + EXPECT_EQ(templates[0].template_id, "TMPL-RECON-001"); + EXPECT_EQ(templates[1].template_id, "TMPL-STRIKE-001"); + EXPECT_EQ(templates[2].template_id, "TMPL-WARN-001"); +} + +TEST(testGetAvailableTemplates, Boundary_CheckApplicableType) { + auto templates = etms::GetAvailableTemplates(); + EXPECT_EQ(templates[0].applicable_type, "侦察"); + EXPECT_EQ(templates[1].applicable_type, "打击"); + EXPECT_EQ(templates[2].applicable_type, "预警"); +} + +// 3. AdvanceEventStatus +TEST(testAdvanceEventStatus, Normal_ReceivedToProcessed) { + etms::Event evt{}; + evt.status = etms::EventStatus::Received; + EXPECT_TRUE(etms::AdvanceEventStatus(evt)); + EXPECT_EQ(evt.status, etms::EventStatus::Processed); +} + +TEST(testAdvanceEventStatus, Normal_ProcessedToPendingTask) { + etms::Event evt{}; + evt.status = etms::EventStatus::Processed; + EXPECT_TRUE(etms::AdvanceEventStatus(evt)); + EXPECT_EQ(evt.status, etms::EventStatus::PendingTask); +} + +TEST(testAdvanceEventStatus, Normal_PendingTaskToTaskGenerated) { + etms::Event evt{}; + evt.status = etms::EventStatus::PendingTask; + EXPECT_TRUE(etms::AdvanceEventStatus(evt)); + EXPECT_EQ(evt.status, etms::EventStatus::TaskGenerated); +} + +TEST(testAdvanceEventStatus, Abnormal_RejectedStateReturnsFalse) { + etms::Event evt{}; + evt.status = etms::EventStatus::Rejected; + EXPECT_FALSE(etms::AdvanceEventStatus(evt)); + EXPECT_EQ(evt.status, etms::EventStatus::Rejected); +} + +TEST(testAdvanceEventStatus, Abnormal_TaskGeneratedStateReturnsFalse) { + etms::Event evt{}; + evt.status = etms::EventStatus::TaskGenerated; + EXPECT_FALSE(etms::AdvanceEventStatus(evt)); + EXPECT_EQ(evt.status, etms::EventStatus::TaskGenerated); +} + +TEST(testAdvanceEventStatus, Abnormal_UnknownStateReturnsFalse) { + etms::Event evt{}; + evt.status = etms::EventStatus::Unknown; + EXPECT_FALSE(etms::AdvanceEventStatus(evt)); + EXPECT_EQ(evt.status, etms::EventStatus::Unknown); +} + +// 4. SortEventsByLevelDesc +TEST(testSortEventsByLevelDesc, Normal_UnsortedToDescending) { + std::vector events = { + {1, "", "", 0, 5, 0, 0, "", etms::EventStatus::Received, 0}, + {2, "", "", 0, 9, 0, 0, "", etms::EventStatus::Received, 0}, + {3, "", "", 0, 7, 0, 0, "", etms::EventStatus::Received, 0} + }; + etms::SortEventsByLevelDesc(events); + EXPECT_EQ(events[0].level, 9); + EXPECT_EQ(events[1].level, 7); + EXPECT_EQ(events[2].level, 5); +} + +TEST(testSortEventsByLevelDesc, Boundary_EmptyVector) { + std::vector events; + etms::SortEventsByLevelDesc(events); + EXPECT_TRUE(events.empty()); +} + +TEST(testSortEventsByLevelDesc, Special_DuplicateLevels) { + std::vector events = { + {1, "", "", 0, 8, 0, 0, "", etms::EventStatus::Received, 0}, + {2, "", "", 0, 8, 0, 0, "", etms::EventStatus::Received, 0}, + {3, "", "", 0, 6, 0, 0, "", etms::EventStatus::Received, 0} + }; + etms::SortEventsByLevelDesc(events); + EXPECT_EQ(events[0].level, 8); + EXPECT_EQ(events[1].level, 8); + EXPECT_EQ(events[2].level, 6); +} + +// 5. SortEventsByTimeAsc +TEST(testSortEventsByTimeAsc, Normal_UnsortedToAscending) { + std::vector events = { + {1, "", "", 100, 0, 0, 0, "", etms::EventStatus::Received, 0}, + {2, "", "", 50, 0, 0, 0, "", etms::EventStatus::Received, 0}, + {3, "", "", 150, 0, 0, 0, "", etms::EventStatus::Received, 0} + }; + etms::SortEventsByTimeAsc(events); + EXPECT_EQ(events[0].timestamp, 50); + EXPECT_EQ(events[1].timestamp, 100); + EXPECT_EQ(events[2].timestamp, 150); +} + +TEST(testSortEventsByTimeAsc, Boundary_SingleElement) { + std::vector events = { + {1, "", "", 100, 0, 0, 0, "", etms::EventStatus::Received, 0} + }; + etms::SortEventsByTimeAsc(events); + EXPECT_EQ(events.size(), 1); + EXPECT_EQ(events[0].timestamp, 100); +} + +TEST(testSortEventsByTimeAsc, Special_AlreadySorted) { + std::vector events = { + {1, "", "", 10, 0, 0, 0, "", etms::EventStatus::Received, 0}, + {2, "", "", 20, 0, 0, 0, "", etms::EventStatus::Received, 0} + }; + etms::SortEventsByTimeAsc(events); + EXPECT_EQ(events[0].timestamp, 10); + EXPECT_EQ(events[1].timestamp, 20); +} \ No newline at end of file