task_plan/tests/basic_test.cpp

250 lines
8.8 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 ETMS 核心模块单元测试(使用标准库 assert无外部依赖
#include "app.hpp"
#include <cassert>
#include <iostream>
#include <sstream>
#include <string>
/// @brief 测试事件状态枚举与字符串转换。
static void test_EventStatusToString() {
std::cout << " [test] EventStatusToString ... ";
assert(std::string(etms::EventStatusToString(etms::EventStatus::Received)) == "Received");
assert(std::string(etms::EventStatusToString(etms::EventStatus::Processed)) == "Processed");
assert(std::string(etms::EventStatusToString(etms::EventStatus::PendingTask)) == "Pending Task");
assert(std::string(etms::EventStatusToString(etms::EventStatus::Rejected)) == "Rejected");
assert(std::string(etms::EventStatusToString(etms::EventStatus::TaskGenerated)) == "Task Generated");
std::cout << "PASSED\n";
}
/// @brief 测试接收原始事件(正常情况)。
static void test_ReceiveRawEvent_Valid() {
std::cout << " [test] ReceiveRawEvent (valid JSON) ... ";
const std::string json = R"({"event_id":"EVT-TEST-001","event_type":""})";
auto ack = etms::ReceiveRawEvent(json);
assert(ack.accepted == true);
assert(ack.event_id == "EVT-TEST-001");
assert(!ack.message.empty());
std::cout << "PASSED\n";
}
/// @brief 测试接收原始事件(空载荷应拒绝)。
static void test_ReceiveRawEvent_Empty() {
std::cout << " [test] ReceiveRawEvent (empty) ... ";
auto ack = etms::ReceiveRawEvent("");
assert(ack.accepted == false);
assert(ack.event_id.empty());
std::cout << "PASSED\n";
}
/// @brief 测试接收原始事件(缺少 event_id 应拒绝)。
static void test_ReceiveRawEvent_MissingId() {
std::cout << " [test] ReceiveRawEvent (missing event_id) ... ";
const std::string json = R"({"event_type":""})";
auto ack = etms::ReceiveRawEvent(json);
assert(ack.accepted == false);
std::cout << "PASSED\n";
}
/// @brief 测试处理事件:状态从 Received → Processed。
static void test_ProcessEvent() {
std::cout << " [test] ProcessEvent ... ";
etms::Event evt;
evt.event_id = "EVT-PROC-001";
evt.status = etms::EventStatus::Received;
bool ok = etms::ProcessEvent(evt);
assert(ok == true);
assert(evt.status == etms::EventStatus::Processed);
std::cout << "PASSED\n";
}
/// @brief 测试处理事件:非 Received 状态不应被处理。
static void test_ProcessEvent_WrongStatus() {
std::cout << " [test] ProcessEvent (wrong status) ... ";
etms::Event evt;
evt.status = etms::EventStatus::TaskGenerated;
bool ok = etms::ProcessEvent(evt);
assert(ok == false);
assert(evt.status == etms::EventStatus::TaskGenerated);
std::cout << "PASSED\n";
}
/// @brief 测试事件查询返回非空列表。
static void test_QueryAllEvents() {
std::cout << " [test] QueryAllEvents ... ";
auto events = etms::QueryAllEvents();
assert(!events.empty());
// 默认应倒序create_time 递减)
for (size_t i = 1; i < events.size(); ++i) {
assert(events[i - 1].create_time >= events[i].create_time);
}
std::cout << "PASSED (" << events.size() << " events)\n";
}
/// @brief 测试紧迫事件筛选。
static void test_FilterUrgentEvents() {
std::cout << " [test] FilterUrgentEvents ... ";
auto events = etms::QueryAllEvents();
auto urgent = etms::FilterUrgentEvents(events);
for (const auto& e : urgent) {
assert(e.level >= 8);
}
assert(!urgent.empty());
std::cout << "PASSED (" << urgent.size() << " urgent)\n";
}
/// @brief 测试模板推荐(匹配类型应返回对应模板 ID
static void test_RecommendTemplate() {
std::cout << " [test] RecommendTemplate ... ";
auto templates = etms::GetAvailableTemplates();
etms::Event recon_evt;
recon_evt.event_type = "侦察";
auto id1 = etms::RecommendTemplate(recon_evt, templates);
assert(id1 == "TMPL-RECON-001");
etms::Event strike_evt;
strike_evt.event_type = "打击";
auto id2 = etms::RecommendTemplate(strike_evt, templates);
assert(id2 == "TMPL-STRIKE-001");
// 不匹配类型时应返回兜底(第一个模板)
etms::Event unknown_evt;
unknown_evt.event_type = "未知";
auto id3 = etms::RecommendTemplate(unknown_evt, templates);
assert(id3 == templates.front().template_id);
std::cout << "PASSED\n";
}
/// @brief 测试空模板列表时的推荐行为。
static void test_RecommendTemplate_EmptyTemplates() {
std::cout << " [test] RecommendTemplate (empty list) ... ";
std::vector<etms::TaskTemplate> empty;
etms::Event evt;
evt.event_type = "侦察";
auto id = etms::RecommendTemplate(evt, empty);
assert(id.empty());
std::cout << "PASSED\n";
}
/// @brief 测试任务请求组装。
static void test_BuildTaskRequest() {
std::cout << " [test] BuildTaskRequest ... ";
std::map<std::string, std::string> params = {{"key1", "val1"}, {"key2", "val2"}};
auto req = etms::BuildTaskRequest("EVT-REQ-001", "TMPL-001", "KB-V1.0", params);
assert(req.request_id.find("REQ-") == 0);
assert(req.event_id == "EVT-REQ-001");
assert(req.template_id == "TMPL-001");
assert(req.kb_version_id == "KB-V1.0");
assert(req.params.size() == 2);
assert(req.request_time > 0);
std::cout << "PASSED\n";
}
/// @brief 测试知识库版本查询。
static void test_GetAvailableKbVersions() {
std::cout << " [test] GetAvailableKbVersions ... ";
auto versions = etms::GetAvailableKbVersions();
assert(!versions.empty());
bool has_active = false;
for (const auto& v : versions) {
if (v.status == "Active") has_active = true;
}
assert(has_active);
std::cout << "PASSED (" << versions.size() << " versions)\n";
}
/// @brief 测试模板查询。
static void test_GetAvailableTemplates() {
std::cout << " [test] GetAvailableTemplates ... ";
auto templates = etms::GetAvailableTemplates();
assert(!templates.empty());
for (const auto& t : templates) {
assert(!t.template_id.empty());
assert(!t.name.empty());
}
std::cout << "PASSED (" << templates.size() << " templates)\n";
}
/// @brief 测试事件状态推进机。
static void test_AdvanceEventStatus() {
std::cout << " [test] AdvanceEventStatus ... ";
etms::Event evt;
evt.status = etms::EventStatus::Received;
// Received → Processed
assert(etms::AdvanceEventStatus(evt) == true);
assert(evt.status == etms::EventStatus::Processed);
// Processed → PendingTask
assert(etms::AdvanceEventStatus(evt) == true);
assert(evt.status == etms::EventStatus::PendingTask);
// PendingTask → TaskGenerated
assert(etms::AdvanceEventStatus(evt) == true);
assert(evt.status == etms::EventStatus::TaskGenerated);
// TaskGenerated → 不可再推进
assert(etms::AdvanceEventStatus(evt) == false);
assert(evt.status == etms::EventStatus::TaskGenerated);
std::cout << "PASSED\n";
}
/// @brief 测试 Rejected 状态不可推进。
static void test_AdvanceEventStatus_Rejected() {
std::cout << " [test] AdvanceEventStatus (Rejected) ... ";
etms::Event evt;
evt.status = etms::EventStatus::Rejected;
assert(etms::AdvanceEventStatus(evt) == false);
assert(evt.status == etms::EventStatus::Rejected);
std::cout << "PASSED\n";
}
/// @brief 测试排序函数(按等级降序)。
static void test_SortEventsByLevelDesc() {
std::cout << " [test] SortEventsByLevelDesc ... ";
auto events = etms::QueryAllEvents();
etms::SortEventsByLevelDesc(events);
for (size_t i = 1; i < events.size(); ++i) {
assert(events[i - 1].level >= events[i].level);
}
std::cout << "PASSED\n";
}
/// @brief 测试排序函数(按时间升序)。
static void test_SortEventsByTimeAsc() {
std::cout << " [test] SortEventsByTimeAsc ... ";
auto events = etms::QueryAllEvents();
etms::SortEventsByTimeAsc(events);
for (size_t i = 1; i < events.size(); ++i) {
assert(events[i - 1].timestamp <= events[i].timestamp);
}
std::cout << "PASSED\n";
}
/// @brief 主测试入口。
int main() {
std::cout << "=== ETMS Basic Unit Tests ===\n\n";
test_EventStatusToString();
test_ReceiveRawEvent_Valid();
test_ReceiveRawEvent_Empty();
test_ReceiveRawEvent_MissingId();
test_ProcessEvent();
test_ProcessEvent_WrongStatus();
test_QueryAllEvents();
test_FilterUrgentEvents();
test_RecommendTemplate();
test_RecommendTemplate_EmptyTemplates();
test_BuildTaskRequest();
test_GetAvailableKbVersions();
test_GetAvailableTemplates();
test_AdvanceEventStatus();
test_AdvanceEventStatus_Rejected();
test_SortEventsByLevelDesc();
test_SortEventsByTimeAsc();
std::cout << "\n=== All " << 17 << " tests PASSED ===\n";
return 0;
}