diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..26bbfb0 --- /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 14) +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..f687176 --- /dev/null +++ b/tests/test_app.cpp @@ -0,0 +1,205 @@ +#include "app.hpp" +#include +#include +#include + +using namespace std; + +class CmsEngineTest : public ::testing::Test { +protected: + CmsEngine engine; +}; + +// 1. CmsEngine 构造函数 +TEST_F(CmsEngineTest, testCmsEngineNormal) { + const auto& ctx = engine.getSystemContext(); + EXPECT_EQ(ctx.currentMode, RunMode::Idle); + EXPECT_EQ(ctx.consistencyMark, 0); + EXPECT_FALSE(ctx.contextSnapshot.empty()); +} + +// 2. generateNextId (通过公开接口间接验证或假设测试友元) +TEST_F(CmsEngineTest, testGenerateNextIdNormal) { + TaskPlan p1, p2; + p1.name = "P1"; p2.name = "P2"; + engine.createTaskPlan(p1); + engine.createTaskPlan(p2); + EXPECT_EQ(p1.id, "ID-00001"); + EXPECT_EQ(p2.id, "ID-00002"); +} + +// 3. ingestEvent +TEST_F(CmsEngineTest, testIngestEventNormal) { + EventRecord evt; evt.id = "evt1"; evt.priority = 100; evt.status = EventStatus::Pending; + EXPECT_TRUE(engine.ingestEvent(evt)); + EXPECT_NE(engine.findEventById("evt1"), nullptr); +} + +TEST_F(CmsEngineTest, testIngestEventBoundary) { + EventRecord e1, e2; + e1.id = ""; e1.priority = 100; + e2.id = "e2"; e2.priority = 256; + EXPECT_FALSE(engine.ingestEvent(e1)); + EXPECT_FALSE(engine.ingestEvent(e2)); +} + +// 4. processPendingEvents +TEST_F(CmsEngineTest, testProcessPendingEventsNormal) { + EventRecord e1, e2; + e1.id = "e1"; e1.priority = 1; e1.status = EventStatus::Pending; + e2.id = "e2"; e2.priority = 1; e2.status = EventStatus::Generated; + engine.ingestEvent(e1); engine.ingestEvent(e2); + EXPECT_EQ(engine.processPendingEvents(), 1); + EXPECT_EQ(engine.findEventById("e1")->status, EventStatus::Generated); + EXPECT_EQ(engine.getAllPlans().size(), 1); +} + +// 5. findEventById +TEST_F(CmsEngineTest, testFindEventByIdNormal) { + EventRecord e; e.id = "findMe"; e.priority = 1; e.status = EventStatus::Pending; + engine.ingestEvent(e); + EXPECT_NE(engine.findEventById("findMe"), nullptr); + EXPECT_EQ(engine.findEventById("notExist"), nullptr); +} + +// 6. createTaskPlan +TEST_F(CmsEngineTest, testCreateTaskPlanNormal) { + TaskPlan p; p.name = "ValidPlan"; + EXPECT_TRUE(engine.createTaskPlan(p)); + EXPECT_FALSE(p.id.empty()); +} + +TEST_F(CmsEngineTest, testCreateTaskPlanBoundary) { + TaskPlan p; p.name = ""; + EXPECT_FALSE(engine.createTaskPlan(p)); +} + +// 7. getAllPlans +TEST_F(CmsEngineTest, testGetAllPlansNormal) { + EXPECT_TRUE(engine.getAllPlans().empty()); + TaskPlan p; p.name = "P1"; + engine.createTaskPlan(p); + EXPECT_EQ(engine.getAllPlans().size(), 1); +} + +// 8. findPlanById +TEST_F(CmsEngineTest, testFindPlanByIdNormal) { + TaskPlan p; p.name = "P1"; + engine.createTaskPlan(p); + EXPECT_NE(engine.findPlanById(p.id), nullptr); + EXPECT_EQ(engine.findPlanById("fake"), nullptr); +} + +// 9. updatePlanStatus +TEST_F(CmsEngineTest, testUpdatePlanStatusNormal) { + TaskPlan p; p.name = "P1"; + engine.createTaskPlan(p); + EXPECT_TRUE(engine.updatePlanStatus(p.id, PlanStatus::Approved)); + EXPECT_EQ(engine.findPlanById(p.id)->status, PlanStatus::Approved); +} + +TEST_F(CmsEngineTest, testUpdatePlanStatusException) { + EXPECT_FALSE(engine.updatePlanStatus("nonexistent", PlanStatus::Approved)); +} + +// 10. registerTemplate +TEST_F(CmsEngineTest, testRegisterTemplateNormal) { + TemplateInstance t; t.confidence = 0.7; + engine.registerTemplate(t); + EXPECT_EQ(engine.matchTemplate("any")->confidence, 0.7); +} + +// 11. matchTemplate +TEST_F(CmsEngineTest, testMatchTemplateNormal) { + TemplateInstance t1, t2; + t1.confidence = 0.5; t2.confidence = 0.9; + engine.registerTemplate(t1); engine.registerTemplate(t2); + EXPECT_EQ(engine.matchTemplate("scene")->confidence, 0.9); +} + +TEST_F(CmsEngineTest, testMatchTemplateBoundary) { + EXPECT_EQ(engine.matchTemplate("empty"), nullptr); +} + +// 12. reportExecutionStatus +TEST_F(CmsEngineTest, testReportExecutionStatusNormal) { + ExecutionStatus s; s.nodeId = "n1"; s.healthIndex = 0.9; s.errorCode = 0; + s.lastReport = chrono::system_clock::now(); + engine.reportExecutionStatus(s); + EXPECT_EQ(engine.checkHealth().size(), 0); +} + +// 13. checkHealth +TEST_F(CmsEngineTest, testCheckHealthSpecial) { + ExecutionStatus s1, s2, s3; + s1.nodeId = "low_health"; s1.healthIndex = 0.4; s1.errorCode = 0; s1.lastReport = chrono::system_clock::now(); + s2.nodeId = "error"; s2.healthIndex = 0.9; s2.errorCode = 1; s2.lastReport = chrono::system_clock::now(); + s3.nodeId = "timeout"; s3.healthIndex = 0.9; s3.errorCode = 0; s3.lastReport = chrono::system_clock::now() - chrono::seconds(31); + engine.reportExecutionStatus(s1); engine.reportExecutionStatus(s2); engine.reportExecutionStatus(s3); + EXPECT_EQ(engine.checkHealth().size(), 3); +} + +// 14. createSession +TEST_F(CmsEngineTest, testCreateSessionNormal) { + UserSession sess; sess.userId = "u1"; sess.permissionBitmap = 0xFF; + EXPECT_TRUE(engine.createSession(sess)); +} + +TEST_F(CmsEngineTest, testCreateSessionBoundary) { + UserSession s1, s2; + s1.userId = ""; s1.permissionBitmap = 1; + s2.userId = "dup"; s2.permissionBitmap = 1; + EXPECT_FALSE(engine.createSession(s1)); + EXPECT_TRUE(engine.createSession(s2)); + EXPECT_FALSE(engine.createSession(s2)); +} + +// 15. checkPermission +TEST_F(CmsEngineTest, testCheckPermissionNormal) { + UserSession sess; sess.userId = "u1"; sess.permissionBitmap = 0x0F; + engine.createSession(sess); + EXPECT_TRUE(engine.checkPermission("u1", 0x03)); + EXPECT_FALSE(engine.checkPermission("u1", 0x10)); + EXPECT_FALSE(engine.checkPermission("u2", 0x01)); +} + +// 16. pushNotification +TEST_F(CmsEngineTest, testPushNotificationNormal) { + NotificationMessage msg; msg.isRead = false; + engine.pushNotification(msg); + EXPECT_EQ(engine.getUnreadNotifications().size(), 1); +} + +// 17. getUnreadNotifications +TEST_F(CmsEngineTest, testGetUnreadNotificationsNormal) { + NotificationMessage m1, m2; + m1.isRead = false; m2.isRead = true; + engine.pushNotification(m1); engine.pushNotification(m2); + EXPECT_EQ(engine.getUnreadNotifications().size(), 1); +} + +// 18. switchMode +TEST_F(CmsEngineTest, testSwitchModeNormal) { + EXPECT_TRUE(engine.switchMode(RunMode::AutoExec)); + EXPECT_EQ(engine.getSystemContext().currentMode, RunMode::AutoExec); +} + +TEST_F(CmsEngineTest, testSwitchModeSpecial) { + engine.switchMode(RunMode::Degraded); + EXPECT_FALSE(engine.switchMode(RunMode::Idle)); + EXPECT_TRUE(engine.switchMode(RunMode::Degraded)); +} + +// 19. getSystemContext +TEST_F(CmsEngineTest, testGetSystemContextNormal) { + const auto& ctx = engine.getSystemContext(); + EXPECT_EQ(ctx.currentMode, RunMode::Idle); +} + +// 20. getSummary +TEST_F(CmsEngineTest, testGetSummaryNormal) { + string summary = engine.getSummary(); + EXPECT_NE(summary.find("CMS Engine Summary"), string::npos); + EXPECT_NE(summary.find("Events"), string::npos); + EXPECT_NE(summary.find("Idle"), string::npos); +}