174 lines
5.2 KiB
C++
174 lines
5.2 KiB
C++
|
|
#include "app.hpp"
|
||
|
|
#include <cassert>
|
||
|
|
#include <iostream>
|
||
|
|
#include <string>
|
||
|
|
|
||
|
|
/// @brief 测试 PlanManager 基本功能
|
||
|
|
static void test_plan_manager() {
|
||
|
|
std::cout << "[测试] PlanManager\n";
|
||
|
|
|
||
|
|
ocpm::PlanManager pm;
|
||
|
|
pm.loadSampleData();
|
||
|
|
|
||
|
|
// 测试查询全部
|
||
|
|
ocpm::PlanQueryRequest all_q;
|
||
|
|
all_q.page_size = 100;
|
||
|
|
auto plans = pm.queryPlans(all_q);
|
||
|
|
assert(plans.size() == 5 && "应加载 5 个示例计划");
|
||
|
|
|
||
|
|
// 测试按状态过滤
|
||
|
|
ocpm::PlanQueryRequest active_q;
|
||
|
|
active_q.status_filter = static_cast<int>(ocpm::PlanStatus::ACTIVE);
|
||
|
|
auto active = pm.queryPlans(active_q);
|
||
|
|
assert(active.size() == 2 && "应有 2 个生效计划");
|
||
|
|
|
||
|
|
// 测试按关键字过滤
|
||
|
|
ocpm::PlanQueryRequest kw_q;
|
||
|
|
kw_q.keyword = "侦察";
|
||
|
|
auto kw = pm.queryPlans(kw_q);
|
||
|
|
assert(kw.size() == 1 && "关键字 '侦察' 应匹配 1 个计划");
|
||
|
|
assert(kw[0].plan_id == "PLAN-003");
|
||
|
|
|
||
|
|
// 测试排序 (按优先级降序)
|
||
|
|
ocpm::SortParam desc_prio{"priority", ocpm::SortDirection::DESC};
|
||
|
|
auto sorted = pm.queryPlans(all_q, desc_prio);
|
||
|
|
assert(!sorted.empty());
|
||
|
|
assert(sorted[0].priority >= sorted[1].priority);
|
||
|
|
|
||
|
|
// 测试获取详情
|
||
|
|
auto detail = pm.getPlanDetail("PLAN-001");
|
||
|
|
assert(detail.plan_id == "PLAN-001");
|
||
|
|
assert(detail.plan_name == "突击行动-甲");
|
||
|
|
|
||
|
|
// 测试获取不存在的计划
|
||
|
|
bool caught = false;
|
||
|
|
try {
|
||
|
|
pm.getPlanDetail("NONEXIST");
|
||
|
|
} catch (const std::invalid_argument&) {
|
||
|
|
caught = true;
|
||
|
|
}
|
||
|
|
assert(caught && "应抛出 invalid_argument");
|
||
|
|
|
||
|
|
// 测试对比
|
||
|
|
auto diffs = pm.comparePlans("PLAN-001", "PLAN-002");
|
||
|
|
assert(!diffs.empty());
|
||
|
|
|
||
|
|
// 测试重构
|
||
|
|
ocpm::ReconstructCommand rc;
|
||
|
|
rc.plan_id = "PLAN-002";
|
||
|
|
rc.modifications = {"测试修改"};
|
||
|
|
auto result = pm.reconstruct(rc);
|
||
|
|
assert(result.success);
|
||
|
|
assert(result.new_version.find("v2") != std::string::npos);
|
||
|
|
|
||
|
|
// 测试 HITL 通知不会崩溃
|
||
|
|
ocpm::HitlEvent hitl;
|
||
|
|
hitl.request_id = "REQ-001";
|
||
|
|
hitl.reason = "需要人工确认目标";
|
||
|
|
hitl.options = {"方案A", "方案B"};
|
||
|
|
pm.notifyHitlEvent(hitl); // 确保不崩溃
|
||
|
|
|
||
|
|
std::cout << " ✓ 所有 PlanManager 测试通过\n";
|
||
|
|
}
|
||
|
|
|
||
|
|
/// @brief 测试 DistributedPlanManager 基本功能
|
||
|
|
static void test_distributed_plan_manager() {
|
||
|
|
std::cout << "[测试] DistributedPlanManager\n";
|
||
|
|
|
||
|
|
ocpm::DistributedPlanManager dpm;
|
||
|
|
dpm.loadSampleData();
|
||
|
|
assert(dpm.getGraph().nodes.size() == 4);
|
||
|
|
assert(dpm.getGraph().edges.size() == 4);
|
||
|
|
|
||
|
|
// 添加节点
|
||
|
|
ocpm::TopoNode n{"NODE-X", "测试节点", 0, 0};
|
||
|
|
dpm.addNode(n);
|
||
|
|
assert(dpm.getGraph().nodes.size() == 5);
|
||
|
|
|
||
|
|
// 重复添加不应增加
|
||
|
|
dpm.addNode(n);
|
||
|
|
assert(dpm.getGraph().nodes.size() == 5);
|
||
|
|
|
||
|
|
// 添加边
|
||
|
|
ocpm::TopoEdge e{"EDGE-X", "NODE-X", "NODE-01", 100};
|
||
|
|
dpm.addEdge(e);
|
||
|
|
assert(dpm.getGraph().edges.size() == 5);
|
||
|
|
|
||
|
|
// 移除边
|
||
|
|
dpm.removeEdge("EDGE-X");
|
||
|
|
assert(dpm.getGraph().edges.size() == 4);
|
||
|
|
|
||
|
|
// 移除节点 (应同时移除关联边)
|
||
|
|
dpm.removeNode("NODE-X");
|
||
|
|
assert(dpm.getGraph().nodes.size() == 4);
|
||
|
|
|
||
|
|
std::cout << " ✓ 所有 DistributedPlanManager 测试通过\n";
|
||
|
|
}
|
||
|
|
|
||
|
|
/// @brief 测试 DispatchManager 基本功能
|
||
|
|
static void test_dispatch_manager() {
|
||
|
|
std::cout << "[测试] DispatchManager\n";
|
||
|
|
|
||
|
|
ocpm::DispatchManager dm;
|
||
|
|
dm.loadSampleData();
|
||
|
|
|
||
|
|
// 资产状态
|
||
|
|
assert(dm.getAssetStatus("ASSET-001") == ocpm::AssetStatusCode::READY);
|
||
|
|
assert(dm.getAssetStatus("ASSET-003") == ocpm::AssetStatusCode::FAULT);
|
||
|
|
assert(dm.getAssetStatus("UNKNOWN") == ocpm::AssetStatusCode::OFFLINE);
|
||
|
|
|
||
|
|
// 分发
|
||
|
|
int sent = dm.dispatchPlan("PLAN-001", {"ASSET-001", "ASSET-002", "ASSET-003"});
|
||
|
|
assert(sent == 1); // 只有 ASSET-001 是 READY
|
||
|
|
|
||
|
|
// 执行统计
|
||
|
|
auto stats = dm.getExecutionStats();
|
||
|
|
assert(stats.total_tasks == 5);
|
||
|
|
assert(stats.completed_tasks == 1);
|
||
|
|
assert(stats.remaining_time > 0.0);
|
||
|
|
|
||
|
|
// 仪表盘
|
||
|
|
auto dash = dm.getDashboardData();
|
||
|
|
assert(dash.execution.total_tasks == 5);
|
||
|
|
assert(dash.resource_rate > 0.0);
|
||
|
|
|
||
|
|
// 告警
|
||
|
|
auto alerts = dm.getAlerts();
|
||
|
|
assert(alerts.size() == 2);
|
||
|
|
|
||
|
|
// 按等级过滤告警
|
||
|
|
ocpm::AlertLevel err = ocpm::AlertLevel::ERROR;
|
||
|
|
auto err_alerts = dm.getAlerts(&err);
|
||
|
|
assert(err_alerts.size() == 1);
|
||
|
|
assert(err_alerts[0].code == 1002);
|
||
|
|
|
||
|
|
// 清除告警
|
||
|
|
dm.clearAlerts();
|
||
|
|
assert(dm.getAlerts().empty());
|
||
|
|
|
||
|
|
// 子任务流程图
|
||
|
|
auto tasks = dm.getTaskFlow();
|
||
|
|
assert(tasks.size() == 5);
|
||
|
|
assert(tasks[0].task_id == "TASK-01");
|
||
|
|
assert(tasks[1].dependency_ids.size() == 1);
|
||
|
|
assert(tasks[1].dependency_ids[0] == "TASK-01");
|
||
|
|
|
||
|
|
std::cout << " ✓ 所有 DispatchManager 测试通过\n";
|
||
|
|
}
|
||
|
|
|
||
|
|
/// @brief 主测试入口
|
||
|
|
int main() {
|
||
|
|
std::cout << "========================================\n";
|
||
|
|
std::cout << " OCPM 单元测试\n";
|
||
|
|
std::cout << "========================================\n\n";
|
||
|
|
|
||
|
|
test_plan_manager();
|
||
|
|
test_distributed_plan_manager();
|
||
|
|
test_dispatch_manager();
|
||
|
|
|
||
|
|
std::cout << "\n========================================\n";
|
||
|
|
std::cout << " 所有测试通过!\n";
|
||
|
|
std::cout << "========================================\n";
|
||
|
|
return 0;
|
||
|
|
}
|