#include "app.hpp" #include #include #include #include #include using namespace ocpm; // 测试夹具 class PlanManagerTest : public ::testing::Test { protected: PlanManager manager; void SetUp() override { manager.loadSampleData(); } }; class DistributedPlanManagerTest : public ::testing::Test { protected: DistributedPlanManager dpm; void SetUp() override { dpm.loadSampleData(); } }; class DispatchManagerTest : public ::testing::Test { protected: DispatchManager dm; void SetUp() override { dm.loadSampleData(); } }; // 1. queryPlans 测试 TEST_F(PlanManagerTest, testQueryPlansNormal) { PlanQueryRequest req; req.status_filter = -1; req.priority_min = 0; req.keyword = ""; req.page = 1; req.page_size = 10; SortParam sort; sort.field = "priority"; sort.direction = SortDirection::DESC; auto res = manager.queryPlans(req, sort); EXPECT_FALSE(res.empty()); EXPECT_LE(res.size(), 10); EXPECT_GE(res[0].priority, res.back().priority); } TEST_F(PlanManagerTest, testQueryPlansBoundaryEmptyResult) { PlanQueryRequest req; req.status_filter = -1; req.priority_min = 100; req.keyword = ""; req.page = 1; req.page_size = 5; SortParam sort; sort.field = "priority"; sort.direction = SortDirection::ASC; auto res = manager.queryPlans(req, sort); EXPECT_TRUE(res.empty()); } TEST_F(PlanManagerTest, testQueryPlansPaginationOutOfBounds) { PlanQueryRequest req; req.status_filter = -1; req.priority_min = 0; req.keyword = ""; req.page = 100; req.page_size = 5; SortParam sort; sort.field = "create_time"; sort.direction = SortDirection::ASC; auto res = manager.queryPlans(req, sort); EXPECT_TRUE(res.empty()); } // 2. getPlanDetail 测试 TEST_F(PlanManagerTest, testGetPlanDetailNormal) { auto p = manager.getPlanDetail("PLAN-001"); EXPECT_EQ(p.plan_id, "PLAN-001"); EXPECT_EQ(p.plan_name, "突击行动-甲"); } TEST_F(PlanManagerTest, testGetPlanDetailExceptionNotFound) { EXPECT_THROW(manager.getPlanDetail("INVALID-ID"), std::invalid_argument); } // 3. comparePlans 测试 TEST_F(PlanManagerTest, testComparePlansNormalDifferent) { auto diffs = manager.comparePlans("PLAN-001", "PLAN-002"); EXPECT_FALSE(diffs.empty()); EXPECT_NE(diffs[0], "(no differences)"); } TEST_F(PlanManagerTest, testComparePlansBoundaryIdentical) { auto diffs = manager.comparePlans("PLAN-001", "PLAN-001"); EXPECT_EQ(diffs.size(), 1); EXPECT_EQ(diffs[0], "(no differences)"); } // 4. reconstruct 测试 TEST_F(PlanManagerTest, testReconstructNormal) { ReconstructCommand cmd; cmd.plan_id = "PLAN-001"; auto res = manager.reconstruct(cmd); EXPECT_TRUE(res.success); EXPECT_EQ(res.new_version, "PLAN-001-v2"); } TEST_F(PlanManagerTest, testReconstructBoundaryNotFound) { ReconstructCommand cmd; cmd.plan_id = "NON-EXIST"; auto res = manager.reconstruct(cmd); EXPECT_FALSE(res.success); EXPECT_NE(res.message.find("未找到"), std::string::npos); } // 5. notifyHitlEvent 测试 TEST_F(PlanManagerTest, testNotifyHitlEventNormal) { HitlEvent evt; EXPECT_NO_THROW(manager.notifyHitlEvent(evt)); } // 6. setAlgorithmProgressCallback 测试 TEST_F(PlanManagerTest, testSetAlgorithmProgressCallbackNormal) { bool called = false; auto cb = [&called](const std::string&, int) { called = true; }; EXPECT_NO_THROW(manager.setAlgorithmProgressCallback(cb)); EXPECT_NO_THROW(manager.setAlgorithmProgressCallback(nullptr)); } // 7. loadSampleData (PlanManager) 测试 TEST_F(PlanManagerTest, testLoadSampleDataNormal) { manager.loadSampleData(); PlanQueryRequest req; req.status_filter = -1; req.priority_min = 0; req.keyword = ""; req.page = 1; req.page_size = 100; SortParam sort; sort.field = "priority"; sort.direction = SortDirection::ASC; auto res = manager.queryPlans(req, sort); EXPECT_EQ(res.size(), 5); } // 8. addNode 测试 TEST_F(DistributedPlanManagerTest, testAddNodeNormal) { TopoNode n{"NODE-NEW", "Test", 0.0, 0.0}; EXPECT_NO_THROW(dpm.addNode(n)); } TEST_F(DistributedPlanManagerTest, testAddNodeBoundaryDuplicate) { TopoNode n{"NODE-01", "Dup", 0.0, 0.0}; EXPECT_NO_THROW(dpm.addNode(n)); EXPECT_NO_THROW(dpm.addNode(n)); // 重复添加应被忽略 } // 9. removeNode 测试 TEST_F(DistributedPlanManagerTest, testRemoveNodeNormal) { EXPECT_NO_THROW(dpm.removeNode("NODE-02")); } TEST_F(DistributedPlanManagerTest, testRemoveNodeBoundaryNonExistent) { EXPECT_NO_THROW(dpm.removeNode("NON-EXIST")); } // 10. addEdge 测试 TEST_F(DistributedPlanManagerTest, testAddEdgeNormal) { TopoEdge e{"EDGE-NEW", "NODE-01", "NODE-04", 10}; EXPECT_NO_THROW(dpm.addEdge(e)); } TEST_F(DistributedPlanManagerTest, testAddEdgeBoundaryDuplicate) { TopoEdge e{"EDGE-01", "NODE-01", "NODE-02", 100}; EXPECT_NO_THROW(dpm.addEdge(e)); EXPECT_NO_THROW(dpm.addEdge(e)); // 重复添加应被忽略 } // 11. removeEdge 测试 TEST_F(DistributedPlanManagerTest, testRemoveEdgeNormal) { EXPECT_NO_THROW(dpm.removeEdge("EDGE-01")); } TEST_F(DistributedPlanManagerTest, testRemoveEdgeBoundaryNonExistent) { EXPECT_NO_THROW(dpm.removeEdge("NON-EXIST")); } // 12. isConnected 测试(通过公共接口间接验证) TEST_F(DistributedPlanManagerTest, testIsConnectedIndirectly) { // 加载样本数据后图应连通,通过添加/删除操作验证行为 dpm.loadSampleData(); EXPECT_NO_THROW(dpm.removeNode("NODE-02")); // 移除节点后仍应连通 EXPECT_NO_THROW(dpm.removeEdge("EDGE-03")); // 移除边后可能断开,但无直接验证方法 } // 13. loadSampleData (DistributedPlanManager) 测试 TEST_F(DistributedPlanManagerTest, testDpmLoadSampleDataNormal) { dpm.loadSampleData(); // 验证节点和边数量 // 注意:无法直接访问graph_,通过操作验证 EXPECT_NO_THROW(dpm.removeNode("NODE-01")); } // 14. dispatchPlan 测试 TEST_F(DispatchManagerTest, testDispatchPlanNormal) { std::vector assets = {"ASSET-001", "ASSET-002", "ASSET-004"}; int count = dm.dispatchPlan("PLAN-001", assets); EXPECT_EQ(count, 2); // ASSET-001, ASSET-004 为 READY } TEST_F(DispatchManagerTest, testDispatchPlanBoundaryEmptyAssets) { std::vector assets; int count = dm.dispatchPlan("PLAN-001", assets); EXPECT_EQ(count, 0); } // 15. getAssetStatus 测试 TEST_F(DispatchManagerTest, testGetAssetStatusNormal) { EXPECT_EQ(dm.getAssetStatus("ASSET-001"), AssetStatusCode::READY); EXPECT_EQ(dm.getAssetStatus("ASSET-002"), AssetStatusCode::BUSY); } TEST_F(DispatchManagerTest, testGetAssetStatusBoundaryOffline) { EXPECT_EQ(dm.getAssetStatus("UNKNOWN"), AssetStatusCode::OFFLINE); } // 16. getExecutionStats 测试 TEST_F(DispatchManagerTest, testGetExecutionStatsNormal) { auto stats = dm.getExecutionStats(); EXPECT_EQ(stats.total_tasks, 5); EXPECT_EQ(stats.completed_tasks, 1); EXPECT_DOUBLE_EQ(stats.remaining_time, 28.5); } // 17. getDashboardData 测试 TEST_F(DispatchManagerTest, testGetDashboardDataNormal) { auto dd = dm.getDashboardData(); EXPECT_EQ(dd.execution.total_tasks, 5); EXPECT_DOUBLE_EQ(dd.resource_rate, 0.72); EXPECT_EQ(dd.recent_alerts.size(), 2); } // 18. getTaskFlow 测试 TEST_F(DispatchManagerTest, testGetTaskFlowNormal) { auto flow = dm.getTaskFlow(); EXPECT_EQ(flow.size(), 5); EXPECT_EQ(flow[0].task_id, "TASK-01"); EXPECT_EQ(flow[0].status, "completed"); } // 19. getAlerts 测试 TEST_F(DispatchManagerTest, testGetAlertsNormalNoFilter) { auto alerts = dm.getAlerts(nullptr); EXPECT_EQ(alerts.size(), 2); } TEST_F(DispatchManagerTest, testGetAlertsBoundaryWithFilter) { AlertLevel lvl = AlertLevel::ERROR; auto alerts = dm.getAlerts(&lvl); EXPECT_EQ(alerts.size(), 1); EXPECT_EQ(alerts[0].level, AlertLevel::ERROR); } // 20. clearAlerts 测试 TEST_F(DispatchManagerTest, testClearAlertsNormal) { dm.clearAlerts(); auto alerts = dm.getAlerts(nullptr); EXPECT_TRUE(alerts.empty()); } // 21. loadSampleData (DispatchManager) 测试 TEST_F(DispatchManagerTest, testDispatchLoadSampleDataNormal) { dm.loadSampleData(); EXPECT_EQ(dm.getAssetStatus("ASSET-001"), AssetStatusCode::READY); EXPECT_EQ(dm.getTaskFlow().size(), 5); EXPECT_EQ(dm.getAlerts(nullptr).size(), 2); }