task_plan_2/tests/test_event_processor.cpp

452 lines
15 KiB
C++
Raw Permalink Normal View History

2026-05-26 05:33:17 +00:00
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "core/event.hpp"
#include <fstream>
using namespace battlefield;
// ==================== EventType / EventStatus 枚举 ====================
TEST(EventEnumTest, EventTypeToString) {
EXPECT_STREQ(EventTypeToString(EventType::UNKNOWN), "UNKNOWN");
EXPECT_STREQ(EventTypeToString(EventType::INTEL), "INTEL");
EXPECT_STREQ(EventTypeToString(EventType::THREAT), "THREAT");
EXPECT_STREQ(EventTypeToString(EventType::MISSION), "MISSION");
EXPECT_STREQ(EventTypeToString(EventType::LOGISTIC), "LOGISTIC");
}
TEST(EventEnumTest, EventStatusToString) {
EXPECT_STREQ(EventStatusToString(EventStatus::PENDING), "PENDING");
EXPECT_STREQ(EventStatusToString(EventStatus::PROCESSING), "PROCESSING");
EXPECT_STREQ(EventStatusToString(EventStatus::RESOLVED), "RESOLVED");
EXPECT_STREQ(EventStatusToString(EventStatus::ARCHIVED), "ARCHIVED");
}
// ==================== Event 结构体 ====================
TEST(EventStructTest, DefaultConstruction) {
Event evt;
EXPECT_EQ(evt.type, EventType::UNKNOWN);
EXPECT_EQ(evt.priority, 0);
EXPECT_EQ(evt.status, EventStatus::PENDING);
EXPECT_TRUE(evt.id.empty());
EXPECT_TRUE(evt.location.empty());
EXPECT_TRUE(evt.source.empty());
EXPECT_TRUE(evt.summary.empty());
}
// ==================== ReceiveEvent ====================
TEST(EventProcessorTest, ReceiveEventValidJson) {
EventProcessor ep;
bool ok = ep.ReceiveEvent(
R"({"eventId":"evt_001","type":"intel","source":"drone","priority":7,"location":"zone-1","message":"test"})",
"drone");
EXPECT_TRUE(ok);
EXPECT_EQ(ep.GetEventCount(), 1u);
}
TEST(EventProcessorTest, ReceiveEventMultiple) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1","type":"intel","priority":5})");
ep.ReceiveEvent(R"({"eventId":"e2","type":"threat","priority":9})");
ep.ReceiveEvent(R"({"eventId":"e3","type":"logistic","priority":3})");
EXPECT_EQ(ep.GetEventCount(), 3u);
}
TEST(EventProcessorTest, ReceiveEventInvalidJson) {
EventProcessor ep;
bool ok = ep.ReceiveEvent("not a json string{", "test");
EXPECT_FALSE(ok);
EXPECT_EQ(ep.GetEventCount(), 0u);
}
TEST(EventProcessorTest, ReceiveEventWithIdField) {
EventProcessor ep;
ep.ReceiveEvent(R"({"id":"alt_id","type":"mission","priority":5})");
EXPECT_EQ(ep.GetEventCount(), 1u);
auto events = ep.GetPendingEvents();
EXPECT_EQ(events[0].id, "alt_id");
}
TEST(EventProcessorTest, ReceiveEventWithoutId) {
EventProcessor ep;
ep.ReceiveEvent(R"({"type":"threat","priority":8})");
EXPECT_EQ(ep.GetEventCount(), 1u);
auto events = ep.GetPendingEvents();
EXPECT_TRUE(events[0].id.find("EVT-") != std::string::npos);
}
// ==================== TransformEvent ====================
TEST(EventProcessorTest, TransformEventFullFields) {
EventProcessor ep;
Event evt = ep.TransformEvent(
R"({"eventId":"evt_full","type":"threat","source":"radar","priority":9,"location":"zone-alpha","message":"enemy detected","timestamp":1716700000})",
"radar");
EXPECT_EQ(evt.id, "evt_full");
EXPECT_EQ(evt.type, EventType::THREAT);
EXPECT_EQ(evt.priority, 9);
EXPECT_EQ(evt.location, "zone-alpha");
EXPECT_EQ(evt.source, "radar");
EXPECT_EQ(evt.summary, "enemy detected");
}
TEST(EventProcessorTest, TransformEventFloatTimestamp) {
EventProcessor ep;
Event evt = ep.TransformEvent(
R"({"eventId":"evt_ts","timestamp":1234567890.5})");
EXPECT_EQ(evt.id, "evt_ts");
}
TEST(EventProcessorTest, TransformEventIntegerTimestamp) {
EventProcessor ep;
Event evt = ep.TransformEvent(
R"({"eventId":"evt_int","timestamp":1716700000})");
EXPECT_EQ(evt.id, "evt_int");
}
TEST(EventProcessorTest, TransformEventMapExternalIntel) {
EventProcessor ep;
Event evt = ep.TransformEvent(
R"({"id":"e1","eventType":"analysis_started","domain":"codegen"})");
EXPECT_EQ(evt.type, EventType::INTEL);
}
TEST(EventProcessorTest, TransformEventMapExternalThreat) {
EventProcessor ep;
Event evt = ep.TransformEvent(
R"({"id":"e1","eventType":"error_occurred","domain":"generation"})");
EXPECT_EQ(evt.type, EventType::THREAT);
}
TEST(EventProcessorTest, TransformEventMapExternalMission) {
EventProcessor ep;
Event evt = ep.TransformEvent(
R"({"id":"e1","eventType":"generation_start","domain":"codegen"})");
EXPECT_EQ(evt.type, EventType::MISSION);
}
TEST(EventProcessorTest, TransformEventMapExternalLogistic) {
EventProcessor ep;
Event evt = ep.TransformEvent(
R"({"id":"e1","eventType":"done","domain":"generation","priority":3})");
EXPECT_EQ(evt.type, EventType::LOGISTIC);
}
TEST(EventProcessorTest, TransformEventWithoutTimestamp) {
EventProcessor ep;
Event evt = ep.TransformEvent(R"({"eventId":"no_ts"})");
EXPECT_EQ(evt.id, "no_ts");
// timestamp 应被设为当前时间
}
TEST(EventProcessorTest, TransformEventClampPriorityLow) {
EventProcessor ep;
Event evt = ep.TransformEvent(R"({"eventId":"low","priority":-5})");
EXPECT_EQ(evt.priority, 1);
}
TEST(EventProcessorTest, TransformEventClampPriorityHigh) {
EventProcessor ep;
Event evt = ep.TransformEvent(R"({"eventId":"high","priority":999})");
EXPECT_EQ(evt.priority, 10);
}
TEST(EventProcessorTest, TransformEventWithStatus) {
EventProcessor ep;
Event evt = ep.TransformEvent(R"({"eventId":"s1","status":2})");
EXPECT_EQ(evt.status, EventStatus::RESOLVED);
}
// ==================== ValidateEventData ====================
TEST(EventProcessorTest, ValidateEventDataValid) {
EventProcessor ep;
nlohmann::json valid1 = {{"eventId", "evt_001"}};
EXPECT_TRUE(ep.ValidateEventData(valid1));
nlohmann::json valid2 = {{"id", "evt_002"}};
EXPECT_TRUE(ep.ValidateEventData(valid2));
}
TEST(EventProcessorTest, ValidateEventDataInvalidEmptyId) {
EventProcessor ep;
nlohmann::json invalid = {{"eventId", ""}};
EXPECT_FALSE(ep.ValidateEventData(invalid));
}
TEST(EventProcessorTest, ValidateEventDataInvalidLongId) {
EventProcessor ep;
nlohmann::json invalid = {{"eventId", std::string(300, 'x')}};
EXPECT_FALSE(ep.ValidateEventData(invalid));
}
TEST(EventProcessorTest, ValidateEventDataNoId) {
EventProcessor ep;
nlohmann::json invalid = {{"type", "threat"}};
EXPECT_FALSE(ep.ValidateEventData(invalid));
}
// ==================== LoadEventsFromFile ====================
TEST(EventProcessorTest, LoadEventsFromFile) {
EventProcessor ep;
size_t loaded = ep.LoadEventsFromFile("events.ndjson", 10);
if (loaded > 0) {
EXPECT_LE(loaded, 10u);
auto events = ep.GetPendingEvents();
for (const auto& e : events) {
EXPECT_FALSE(e.id.empty());
}
}
}
TEST(EventProcessorTest, LoadEventsFromFileAll) {
EventProcessor ep;
size_t loaded = ep.LoadEventsFromFile("events.ndjson");
EXPECT_EQ(ep.GetEventCount(), loaded);
auto events = ep.GetPendingEvents();
for (const auto& e : events) {
EXPECT_FALSE(e.id.empty());
EXPECT_GE(e.priority, 1);
EXPECT_LE(e.priority, 10);
}
}
TEST(EventProcessorTest, LoadEventsFromFileNotFound) {
EventProcessor ep;
size_t loaded = ep.LoadEventsFromFile("nonexistent_file.ndjson");
EXPECT_EQ(loaded, 0u);
EXPECT_EQ(ep.GetEventCount(), 0u);
}
// ==================== 查询方法 ====================
TEST(EventProcessorTest, GetPendingEventsNew) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1","type":"intel","priority":5})");
ep.ReceiveEvent(R"({"eventId":"e2","type":"threat","priority":8})");
auto pending = ep.GetPendingEvents();
EXPECT_EQ(pending.size(), 2u);
}
TEST(EventProcessorTest, GetEventsByStatus) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1","type":"intel","priority":5})");
ep.ReceiveEvent(R"({"eventId":"e2","type":"threat","priority":8})");
auto pending = ep.GetEventsByStatus(EventStatus::PENDING);
EXPECT_EQ(pending.size(), 2u);
auto resolved = ep.GetEventsByStatus(EventStatus::RESOLVED);
EXPECT_EQ(resolved.size(), 0u);
auto archived = ep.GetEventsByStatus(EventStatus::ARCHIVED);
EXPECT_EQ(archived.size(), 0u);
}
// ==================== 排序 ====================
TEST(EventProcessorTest, SortByPriorityAscending) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1","priority":3})");
ep.ReceiveEvent(R"({"eventId":"e2","priority":9})");
ep.ReceiveEvent(R"({"eventId":"e3","priority":5})");
ep.SortEventsByPriority(true);
auto events = ep.GetPendingEvents();
EXPECT_EQ(events[0].priority, 3);
EXPECT_EQ(events[1].priority, 5);
EXPECT_EQ(events[2].priority, 9);
}
TEST(EventProcessorTest, SortByPriorityDescending) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1","priority":3})");
ep.ReceiveEvent(R"({"eventId":"e2","priority":9})");
ep.ReceiveEvent(R"({"eventId":"e3","priority":5})");
ep.SortEventsByPriority(false);
auto events = ep.GetPendingEvents();
EXPECT_EQ(events[0].priority, 9);
EXPECT_EQ(events[1].priority, 5);
EXPECT_EQ(events[2].priority, 3);
}
TEST(EventProcessorTest, SortByCustomComparator) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"aaa","priority":5})");
ep.ReceiveEvent(R"({"eventId":"bbb","priority":5})");
ep.ReceiveEvent(R"({"eventId":"ccc","priority":5})");
ep.SortEventsBy([](const Event& a, const Event& b) {
return a.id > b.id; // 按 ID 降序
});
auto events = ep.GetPendingEvents();
EXPECT_EQ(events[0].id, "ccc");
EXPECT_EQ(events[1].id, "bbb");
EXPECT_EQ(events[2].id, "aaa");
}
// ==================== 筛选 ====================
TEST(EventProcessorTest, FilterByType) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1","type":"intel","priority":5})");
ep.ReceiveEvent(R"({"eventId":"e2","type":"threat","priority":8})");
ep.ReceiveEvent(R"({"eventId":"e3","type":"intel","priority":3})");
auto intels = ep.FilterByType(EventType::INTEL);
EXPECT_EQ(intels.size(), 2u);
auto threats = ep.FilterByType(EventType::THREAT);
EXPECT_EQ(threats.size(), 1u);
auto missions = ep.FilterByType(EventType::MISSION);
EXPECT_EQ(missions.size(), 0u);
auto unknowns = ep.FilterByType(EventType::UNKNOWN);
EXPECT_EQ(unknowns.size(), 0u);
}
TEST(EventProcessorTest, FilterByPriority) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1","priority":1})");
ep.ReceiveEvent(R"({"eventId":"e2","priority":5})");
ep.ReceiveEvent(R"({"eventId":"e3","priority":10})");
auto low = ep.FilterByPriority(1, 3);
EXPECT_EQ(low.size(), 1u);
auto mid = ep.FilterByPriority(4, 7);
EXPECT_EQ(mid.size(), 1u);
auto high = ep.FilterByPriority(8, 10);
EXPECT_EQ(high.size(), 1u);
auto all = ep.FilterByPriority(1, 10);
EXPECT_EQ(all.size(), 3u);
auto none = ep.FilterByPriority(11, 20);
EXPECT_EQ(none.size(), 0u);
}
TEST(EventProcessorTest, FilterBySource) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1"})", "radar_a");
ep.ReceiveEvent(R"({"eventId":"e2"})", "radar_a");
ep.ReceiveEvent(R"({"eventId":"e3"})", "drone_x");
auto fromRadar = ep.FilterBySource("radar_a");
EXPECT_EQ(fromRadar.size(), 2u);
auto fromDrone = ep.FilterBySource("drone_x");
EXPECT_EQ(fromDrone.size(), 1u);
auto fromNone = ep.FilterBySource("nonexistent");
EXPECT_EQ(fromNone.size(), 0u);
}
// ==================== 状态流转 ====================
TEST(EventProcessorTest, MarkProcessingValid) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1","priority":5})");
EXPECT_TRUE(ep.MarkProcessing("e1"));
auto pending = ep.GetPendingEvents();
EXPECT_EQ(pending.size(), 0u);
auto processing = ep.GetEventsByStatus(EventStatus::PROCESSING);
EXPECT_EQ(processing.size(), 1u);
}
TEST(EventProcessorTest, MarkProcessingInvalid) {
EventProcessor ep;
EXPECT_FALSE(ep.MarkProcessing("nonexistent"));
}
TEST(EventProcessorTest, MarkResolved) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1","priority":5})");
EXPECT_TRUE(ep.MarkResolved("e1"));
auto resolved = ep.GetEventsByStatus(EventStatus::RESOLVED);
EXPECT_EQ(resolved.size(), 1u);
}
TEST(EventProcessorTest, MarkResolvedInvalid) {
EventProcessor ep;
EXPECT_FALSE(ep.MarkResolved("nonexistent"));
}
TEST(EventProcessorTest, MarkArchived) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1","priority":5})");
EXPECT_TRUE(ep.MarkArchived("e1"));
auto archived = ep.GetEventsByStatus(EventStatus::ARCHIVED);
EXPECT_EQ(archived.size(), 1u);
}
TEST(EventProcessorTest, MarkArchivedInvalid) {
EventProcessor ep;
EXPECT_FALSE(ep.MarkArchived("nonexistent"));
}
TEST(EventProcessorTest, FullLifecycle) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"lifecycle","priority":5})");
// PENDING -> PROCESSING
EXPECT_TRUE(ep.MarkProcessing("lifecycle"));
EXPECT_EQ(ep.GetPendingEvents().size(), 0u);
EXPECT_EQ(ep.GetEventsByStatus(EventStatus::PROCESSING).size(), 1u);
// PROCESSING -> RESOLVED
EXPECT_TRUE(ep.MarkResolved("lifecycle"));
EXPECT_EQ(ep.GetEventsByStatus(EventStatus::RESOLVED).size(), 1u);
// RESOLVED -> ARCHIVED
EXPECT_TRUE(ep.MarkArchived("lifecycle"));
EXPECT_EQ(ep.GetEventsByStatus(EventStatus::ARCHIVED).size(), 1u);
}
// ==================== Clear / GetEventCount ====================
TEST(EventProcessorTest, Clear) {
EventProcessor ep;
ep.ReceiveEvent(R"({"eventId":"e1"})");
ep.ReceiveEvent(R"({"eventId":"e2"})");
EXPECT_EQ(ep.GetEventCount(), 2u);
ep.Clear();
EXPECT_EQ(ep.GetEventCount(), 0u);
}
// ==================== 边界和特殊情况 ====================
TEST(EventProcessorTest, EmptyProcessor) {
EventProcessor ep;
EXPECT_EQ(ep.GetEventCount(), 0u);
EXPECT_TRUE(ep.GetPendingEvents().empty());
EXPECT_TRUE(ep.GetEventsByStatus(EventStatus::PENDING).empty());
}
TEST(EventProcessorTest, PriorityDefaultsByType) {
EventProcessor ep;
Event threat = ep.TransformEvent(R"({"eventId":"t1","type":"threat"})");
EXPECT_EQ(threat.priority, 9);
Event intel = ep.TransformEvent(R"({"eventId":"i1","type":"intel"})");
EXPECT_EQ(intel.priority, 7);
Event mission = ep.TransformEvent(R"({"eventId":"m1","type":"mission"})");
EXPECT_EQ(mission.priority, 5);
Event logistic = ep.TransformEvent(R"({"eventId":"l1","type":"logistic"})");
EXPECT_EQ(logistic.priority, 3);
Event unknown = ep.TransformEvent(R"({"eventId":"u1","type":"other"})");
EXPECT_EQ(unknown.priority, 1);
}
TEST(EventProcessorTest, SummaryFromMessageField) {
EventProcessor ep;
Event evt = ep.TransformEvent(R"({"eventId":"s1","message":"test message"})");
EXPECT_EQ(evt.summary, "test message");
}
TEST(EventProcessorTest, SummaryFromSummaryField) {
EventProcessor ep;
Event evt = ep.TransformEvent(R"({"eventId":"s1","summary":"override summary"})");
EXPECT_EQ(evt.summary, "override summary");
}
TEST(EventProcessorTest, LocationDefault) {
EventProcessor ep;
Event evt = ep.TransformEvent(R"({"eventId":"loc"})");
EXPECT_EQ(evt.location, "unknown-zone");
}