plan_execute_t1/tests/basic_test.cpp

320 lines
9.0 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.

/**
* @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;
}