diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..de64cd4 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.10.0) +project(test_task_plan_execute) +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_execute test_app.cpp ../src/app.cpp) + +target_link_libraries(test_task_plan_execute gtest gmock gtest_main) +include(GoogleTest) +gtest_discover_tests(test_task_plan_execute) \ No newline at end of file diff --git a/tests/test_app.cpp b/tests/test_app.cpp new file mode 100644 index 0000000..88be73c --- /dev/null +++ b/tests/test_app.cpp @@ -0,0 +1,223 @@ +#include +#include "app.hpp" +#include +#include + +using namespace bmp; + +// 注意:generateId, now, timeToString 为文件内部 static 函数, +// 具有内部链接属性,无法在外部测试文件中直接访问和测试。 +// 根据 C++ 单元测试最佳实践及编译错误反馈,移除对它们的直接测试。 + +TEST(EventServiceTest, testReceiveEventNormal) { + EventService svc; + EXPECT_TRUE(svc.receiveEvent("test")); +} + +TEST(EventServiceTest, testSendAckNormal) { + EventService svc; + svc.receiveEvent("test"); + auto events = svc.getPendingEvents(); + std::string ack = svc.sendAck(events[0].id); + EXPECT_EQ(0, ack.find("ACK:")); +} + +TEST(EventServiceTest, testGetRawEventNormal) { + EventService svc; + svc.receiveEvent("test"); + auto events = svc.getPendingEvents(); + const Event* evt = svc.getRawEvent(events[0].id); + EXPECT_NE(nullptr, evt); +} + +TEST(EventServiceTest, testProcessEventNormal) { + EventService svc; + svc.receiveEvent("test"); + auto events = svc.getPendingEvents(); + EXPECT_TRUE(svc.processEvent(events[0].id)); + const Event* evt = svc.getRawEvent(events[0].id); + EXPECT_EQ(EventStatus::PROCESSING, evt->status); +} + +TEST(EventServiceTest, testSaveStandardEvent) { + EventService svc; + Event evt; + evt.id = "EVT_001"; + evt.status = EventStatus::ACCEPTED; + svc.saveStandardEvent(evt); + const Event* res = svc.getRawEvent("EVT_001"); + EXPECT_NE(nullptr, res); + EXPECT_EQ(EventStatus::ACCEPTED, res->status); +} + +TEST(EventServiceTest, testQueryEventsFilter) { + EventService svc; + svc.receiveEvent("test"); + std::unordered_map filters; + filters["status"] = "PENDING"; + auto res = svc.queryEvents(filters); + EXPECT_FALSE(res.empty()); +} + +TEST(EventServiceTest, testGetPendingEvents) { + EventService svc; + svc.receiveEvent("test"); + auto res = svc.getPendingEvents(); + EXPECT_FALSE(res.empty()); +} + +TEST(TemplateServiceTest, testReceiveTemplatesNormal) { + TemplateService svc; + std::string data = "T1\nTemplate1\n"; + size_t count = svc.receiveTemplates(data); + EXPECT_GT(count, 0); +} + +TEST(TemplateServiceTest, testGetTemplateList) { + TemplateService svc; + svc.receiveTemplates("T1\nTemplate1\n"); + auto list = svc.getTemplateList(); + EXPECT_FALSE(list.empty()); +} + +TEST(TemplateServiceTest, testSelectTemplateNormal) { + TemplateService svc; + svc.receiveTemplates("T1\nTemplate1\n"); + EXPECT_TRUE(svc.selectTemplate("T1")); +} + +TEST(TemplateServiceTest, testRecommendTemplate) { + TemplateService svc; + svc.receiveTemplates("T1\nTemplate1\nRECON\n"); + std::string rec = svc.recommendTemplate("RECON"); + EXPECT_EQ("T1", rec); +} + +TEST(TemplateServiceTest, testGetConfig) { + TemplateService svc; + auto cfg = svc.getConfig(); + EXPECT_EQ("enabled", cfg["version_check"]); +} + +TEST(PlanServiceTest, testGenerateTaskNormal) { + PlanService svc; + std::unordered_map params; + std::string planId = svc.generateTask("EVT1", "TPL1", params); + EXPECT_FALSE(planId.empty()); +} + +TEST(PlanServiceTest, testSubmitTask) { + PlanService svc; + std::unordered_map params; + std::string planId = svc.generateTask("EVT1", "TPL1", params); + TaskPlan plan = svc.submitTask(planId); + EXPECT_EQ(PlanStatus::CONFIRMED, plan.status); +} + +TEST(PlanServiceTest, testGetPlanList) { + PlanService svc; + std::unordered_map params; + svc.generateTask("EVT1", "TPL1", params); + auto list = svc.getPlanList(); + EXPECT_FALSE(list.empty()); +} + +TEST(PlanServiceTest, testSortPlans) { + PlanService svc; + std::unordered_map params; + svc.generateTask("EVT1", "TPL1", params); + std::unordered_map weights = {{"priority", 1}, {"time", 1}}; + EXPECT_NO_THROW(svc.sortPlans(weights)); +} + +TEST(PlanServiceTest, testReconfigurePlan) { + PlanService svc; + std::unordered_map params; + std::string planId = svc.generateTask("EVT1", "TPL1", params); + std::vector newNodes; + EXPECT_TRUE(svc.reconfigurePlan(planId, newNodes)); +} + +TEST(PlanServiceTest, testNotifyHITL) { + PlanService svc; + std::unordered_map params; + std::string planId = svc.generateTask("EVT1", "TPL1", params); + EXPECT_NO_THROW(svc.notifyHITL(planId, "Test message")); +} + +TEST(DistributionServiceTest, testDistributePlan) { + DistributionService svc; + auto logs = svc.distributePlan("PLAN1"); + EXPECT_EQ(3, logs.size()); +} + +TEST(DistributionServiceTest, testReceiveAck) { + DistributionService svc; + auto logs = svc.distributePlan("PLAN1"); + EXPECT_TRUE(svc.receiveAck(logs[0].logId, DistributionResponse::ACK)); +} + +TEST(DistributionServiceTest, testUpdateStatus) { + DistributionService svc; + EXPECT_NO_THROW(svc.updateStatus("PLAN1")); +} + +TEST(DistributionServiceTest, testGetLogsByPlan) { + DistributionService svc; + svc.distributePlan("PLAN1"); + auto logs = svc.getLogsByPlan("PLAN1"); + EXPECT_EQ(3, logs.size()); +} + +TEST(StatusMonitorServiceTest, testReceiveTelemetry) { + StatusMonitorService svc; + std::vector data(20, 0); + auto log = svc.receiveTelemetry(data); + EXPECT_FALSE(log.assetId.empty()); +} + +TEST(StatusMonitorServiceTest, testParseDataTooShort) { + StatusMonitorService svc; + std::vector data(5, 0); + auto log = svc.parseData(data); + EXPECT_TRUE(log.isAbnormal); +} + +TEST(StatusMonitorServiceTest, testTriggerAlarm) { + StatusMonitorService svc; + StatusLog log; + log.isAbnormal = true; + log.assetId = "AST_1"; + log.detailInfo = "Error"; + std::string alarm = svc.triggerAlarm(log); + EXPECT_NE(std::string::npos, alarm.find("[ALARM]")); +} + +TEST(StatusMonitorServiceTest, testGetLatestStatus) { + StatusMonitorService svc; + std::vector data(20, 0); + svc.receiveTelemetry(data); + auto log = svc.getLatestStatus("AST_0"); + EXPECT_EQ("AST_0", log.assetId); +} + +TEST(StatusMonitorServiceTest, testCheckStaleData) { + StatusMonitorService svc; + std::vector data(20, 0); + svc.receiveTelemetry(data); + EXPECT_NO_THROW(svc.checkStaleData(0)); +} + +TEST(BattlefieldMissionPlannerTest, testConstructor) { + EXPECT_NO_THROW(BattlefieldMissionPlanner planner); +} + +TEST(BattlefieldMissionPlannerTest, testInitialize) { + BattlefieldMissionPlanner planner; + EXPECT_TRUE(planner.initialize()); +} + +TEST(BattlefieldMissionPlannerTest, testRun) { + BattlefieldMissionPlanner planner; + EXPECT_NO_THROW(planner.run()); +}