320 lines
9.0 KiB
C++
320 lines
9.0 KiB
C++
/**
|
||
* @file basic_test.cpp
|
||
* @brief CMS 核心引擎基本单元测试
|
||
*
|
||
* 使用标准库 assert 进行验证,不依赖外部测试框架。
|
||
*/
|
||
|
||
#include "app.hpp"
|
||
#include <cassert>
|
||
#include <iostream>
|
||
#include <chrono>
|
||
#include <string>
|
||
|
||
/**
|
||
* @brief 测试事件接入与处理
|
||
*/
|
||
static void testEventIngestion()
|
||
{
|
||
std::cout << "[TEST] testEventIngestion ... ";
|
||
|
||
CmsEngine engine;
|
||
|
||
// 空 ID 应被拒绝
|
||
EventRecord bad;
|
||
bad.id = "";
|
||
assert(!engine.ingestEvent(bad));
|
||
|
||
// 有效事件应被接受
|
||
EventRecord evt;
|
||
evt.id = "EVT-TEST-001";
|
||
evt.typeTag = "test_type";
|
||
evt.priority = 100;
|
||
evt.threatLevel = 3;
|
||
evt.status = EventStatus::Pending;
|
||
evt.receiveTime = std::chrono::system_clock::now();
|
||
assert(engine.ingestEvent(evt));
|
||
|
||
// 查找事件
|
||
const auto* found = engine.findEventById("EVT-TEST-001");
|
||
assert(found != nullptr);
|
||
assert(found->typeTag == "test_type");
|
||
|
||
// 处理待处理事件 → 应生成一个任务方案
|
||
size_t count = engine.processPendingEvents();
|
||
assert(count == 1);
|
||
|
||
// 事件状态已变为 Generated
|
||
found = engine.findEventById("EVT-TEST-001");
|
||
assert(found != nullptr);
|
||
assert(found->status == EventStatus::Generated);
|
||
|
||
// 方案列表应有 1 个方案
|
||
assert(engine.getAllPlans().size() == 1);
|
||
|
||
std::cout << "PASSED\n";
|
||
}
|
||
|
||
/**
|
||
* @brief 测试任务方案管理
|
||
*/
|
||
static void testPlanManagement()
|
||
{
|
||
std::cout << "[TEST] testPlanManagement ... ";
|
||
|
||
CmsEngine engine;
|
||
|
||
// 空名称应被拒绝
|
||
TaskPlan badPlan;
|
||
badPlan.name = "";
|
||
assert(!engine.createTaskPlan(badPlan));
|
||
|
||
// 有效方案
|
||
TaskPlan plan;
|
||
plan.name = "Operation-Storm";
|
||
plan.type = PlanType::Distributed;
|
||
plan.status = PlanStatus::Drafting;
|
||
plan.topologyNodes = {"Node-1", "Node-2", "Node-3"};
|
||
plan.resourceQuota = 0.8;
|
||
plan.constraints = "max_delay=5s";
|
||
assert(engine.createTaskPlan(plan));
|
||
|
||
// 创建后应有 ID
|
||
assert(!plan.id.empty());
|
||
|
||
// 按 ID 查找
|
||
const auto* found = engine.findPlanById(plan.id);
|
||
assert(found != nullptr);
|
||
assert(found->name == "Operation-Storm");
|
||
assert(found->type == PlanType::Distributed);
|
||
|
||
// 更新状态
|
||
assert(engine.updatePlanStatus(plan.id, PlanStatus::Confirmed));
|
||
found = engine.findPlanById(plan.id);
|
||
assert(found->status == PlanStatus::Confirmed);
|
||
|
||
// 不存在的 ID 更新应失败
|
||
assert(!engine.updatePlanStatus("NONEXIST", PlanStatus::Completed));
|
||
|
||
std::cout << "PASSED\n";
|
||
}
|
||
|
||
/**
|
||
* @brief 测试模板注册与匹配
|
||
*/
|
||
static void testTemplateMatching()
|
||
{
|
||
std::cout << "[TEST] testTemplateMatching ... ";
|
||
|
||
CmsEngine engine;
|
||
|
||
// 空库匹配应返回 nullptr
|
||
assert(engine.matchTemplate("any") == nullptr);
|
||
|
||
TemplateInstance tmpl;
|
||
tmpl.id = "TMPL-TEST";
|
||
tmpl.scenario = "land_assault";
|
||
tmpl.complexity = 0.8;
|
||
tmpl.version = "1.0.0";
|
||
tmpl.confidence = 0.95;
|
||
engine.registerTemplate(tmpl);
|
||
|
||
const auto* matched = engine.matchTemplate("land_assault");
|
||
assert(matched != nullptr);
|
||
assert(matched->id == "TMPL-TEST");
|
||
assert(matched->confidence == 0.95);
|
||
|
||
std::cout << "PASSED\n";
|
||
}
|
||
|
||
/**
|
||
* @brief 测试执行监控与健康检查
|
||
*/
|
||
static void testExecutionMonitoring()
|
||
{
|
||
std::cout << "[TEST] testExecutionMonitoring ... ";
|
||
|
||
CmsEngine engine;
|
||
|
||
// 健康节点
|
||
ExecutionStatus healthy;
|
||
healthy.nodeId = "NODE-H";
|
||
healthy.healthIndex = 0.95;
|
||
healthy.errorCode = 0;
|
||
healthy.lastReport = std::chrono::system_clock::now();
|
||
engine.reportExecutionStatus(healthy);
|
||
|
||
// 异常节点(健康指数低)
|
||
ExecutionStatus sick;
|
||
sick.nodeId = "NODE-S";
|
||
sick.healthIndex = 0.3;
|
||
sick.errorCode = 0;
|
||
sick.lastReport = std::chrono::system_clock::now();
|
||
engine.reportExecutionStatus(sick);
|
||
|
||
// 异常节点(异常码非零)
|
||
ExecutionStatus error;
|
||
error.nodeId = "NODE-E";
|
||
error.healthIndex = 0.9;
|
||
error.errorCode = 0xA001;
|
||
error.lastReport = std::chrono::system_clock::now();
|
||
engine.reportExecutionStatus(error);
|
||
|
||
// 异常节点(心跳超时 - 45秒前)
|
||
ExecutionStatus timeout;
|
||
timeout.nodeId = "NODE-T";
|
||
timeout.healthIndex = 0.9;
|
||
timeout.errorCode = 0;
|
||
timeout.lastReport = std::chrono::system_clock::now()
|
||
- std::chrono::seconds(45);
|
||
engine.reportExecutionStatus(timeout);
|
||
|
||
auto unhealthy = engine.checkHealth();
|
||
// 应有 3 个异常节点(NODE-S, NODE-E, NODE-T)
|
||
assert(unhealthy.size() == 3);
|
||
|
||
// 验证具体节点
|
||
bool foundS = false, foundE = false, foundT = false;
|
||
for (const auto& u : unhealthy) {
|
||
if (u.nodeId == "NODE-S") foundS = true;
|
||
if (u.nodeId == "NODE-E") foundE = true;
|
||
if (u.nodeId == "NODE-T") foundT = true;
|
||
}
|
||
assert(foundS && foundE && foundT);
|
||
|
||
std::cout << "PASSED\n";
|
||
}
|
||
|
||
/**
|
||
* @brief 测试用户会话与权限
|
||
*/
|
||
static void testUserSession()
|
||
{
|
||
std::cout << "[TEST] testUserSession ... ";
|
||
|
||
CmsEngine engine;
|
||
|
||
// 空用户 ID 应被拒绝
|
||
UserSession bad;
|
||
bad.userId = "";
|
||
assert(!engine.createSession(bad));
|
||
|
||
// 创建有效用户
|
||
UserSession user;
|
||
user.userId = "USER-001";
|
||
user.roleCode = "OPERATOR";
|
||
user.permissionBitmap = 0x0000000000000003ULL; // 位0+位1
|
||
assert(engine.createSession(user));
|
||
|
||
// 重复创建应失败
|
||
assert(!engine.createSession(user));
|
||
|
||
// 权限校验
|
||
assert(engine.checkPermission("USER-001", 0x0000000000000001ULL));
|
||
assert(engine.checkPermission("USER-001", 0x0000000000000002ULL));
|
||
assert(engine.checkPermission("USER-001", 0x0000000000000003ULL));
|
||
assert(!engine.checkPermission("USER-001", 0x0000000000000004ULL));
|
||
|
||
// 不存在的用户
|
||
assert(!engine.checkPermission("GHOST", 0x0000000000000001ULL));
|
||
|
||
std::cout << "PASSED\n";
|
||
}
|
||
|
||
/**
|
||
* @brief 测试通知管理
|
||
*/
|
||
static void testNotification()
|
||
{
|
||
std::cout << "[TEST] testNotification ... ";
|
||
|
||
CmsEngine engine;
|
||
|
||
// 初始无未读通知
|
||
assert(engine.getUnreadNotifications().empty());
|
||
|
||
NotificationMessage msg;
|
||
msg.id = "NTF-001";
|
||
msg.priority = 200;
|
||
msg.type = NotificationType::Alert;
|
||
msg.summary = "Test alert";
|
||
msg.triggerTime = std::chrono::system_clock::now();
|
||
msg.isRead = false;
|
||
engine.pushNotification(msg);
|
||
|
||
assert(engine.getUnreadNotifications().size() == 1);
|
||
|
||
// 推送已读消息
|
||
NotificationMessage readMsg;
|
||
readMsg.id = "NTF-002";
|
||
readMsg.priority = 50;
|
||
readMsg.type = NotificationType::Hint;
|
||
readMsg.summary = "Read message";
|
||
readMsg.triggerTime = std::chrono::system_clock::now();
|
||
readMsg.isRead = true;
|
||
engine.pushNotification(readMsg);
|
||
|
||
// 未读数量仍为 1
|
||
assert(engine.getUnreadNotifications().size() == 1);
|
||
|
||
std::cout << "PASSED\n";
|
||
}
|
||
|
||
/**
|
||
* @brief 测试模式切换
|
||
*/
|
||
static void testModeSwitch()
|
||
{
|
||
std::cout << "[TEST] testModeSwitch ... ";
|
||
|
||
CmsEngine engine;
|
||
|
||
// 初始模式为 Idle
|
||
assert(engine.getSystemContext().currentMode == RunMode::Idle);
|
||
|
||
// 正常切换
|
||
assert(engine.switchMode(RunMode::HumanLoop));
|
||
assert(engine.getSystemContext().currentMode == RunMode::HumanLoop);
|
||
|
||
assert(engine.switchMode(RunMode::AutoExec));
|
||
assert(engine.getSystemContext().currentMode == RunMode::AutoExec);
|
||
|
||
// 进入降级模式
|
||
assert(engine.switchMode(RunMode::Degraded));
|
||
assert(engine.getSystemContext().currentMode == RunMode::Degraded);
|
||
|
||
// 降级模式下不允许切换回其他模式(安全策略)
|
||
assert(!engine.switchMode(RunMode::Idle));
|
||
assert(!engine.switchMode(RunMode::HumanLoop));
|
||
|
||
std::cout << "PASSED\n";
|
||
}
|
||
|
||
/**
|
||
* @brief 主测试入口
|
||
*
|
||
* 依次运行所有测试用例,汇总测试结果。
|
||
*
|
||
* @return int 退出码(0 全部通过,1 有失败)
|
||
*/
|
||
int main()
|
||
{
|
||
std::cout << "╔══════════════════════════════════════════════╗\n";
|
||
std::cout << "║ CMS 单元测试 ║\n";
|
||
std::cout << "╚══════════════════════════════════════════════╝\n\n";
|
||
|
||
testEventIngestion();
|
||
testPlanManagement();
|
||
testTemplateMatching();
|
||
testExecutionMonitoring();
|
||
testUserSession();
|
||
testNotification();
|
||
testModeSwitch();
|
||
|
||
std::cout << "\n╔══════════════════════════════════════════════╗\n";
|
||
std::cout << "║ 全部测试通过 (ALL TESTS PASSED) ║\n";
|
||
std::cout << "╚══════════════════════════════════════════════╝\n";
|
||
|
||
return 0;
|
||
}
|