presentation/tests/test_app.cpp

253 lines
8.2 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "app.hpp"
#include <gtest/gtest.h>
#include <vector>
#include <string>
#include <functional>
#include <algorithm>
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<std::string> 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<std::string> 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);
}