383 lines
11 KiB
C++
383 lines
11 KiB
C++
#include <gtest/gtest.h>
|
|
#include <gmock/gmock.h>
|
|
#include "core/task.hpp"
|
|
|
|
using namespace battlefield;
|
|
|
|
// ==================== DraftStatus 枚举 ====================
|
|
TEST(TaskEnumTest, DraftStatusValues) {
|
|
EXPECT_EQ(static_cast<int>(DraftStatus::DRAFT), 0);
|
|
EXPECT_EQ(static_cast<int>(DraftStatus::SUBMITTED), 1);
|
|
EXPECT_EQ(static_cast<int>(DraftStatus::APPROVED), 2);
|
|
EXPECT_EQ(static_cast<int>(DraftStatus::REJECTED), 3);
|
|
}
|
|
|
|
// ==================== TaskDraft 结构体 ====================
|
|
TEST(TaskDraftTest, DefaultConstruction) {
|
|
TaskDraft draft;
|
|
EXPECT_TRUE(draft.id.empty());
|
|
EXPECT_TRUE(draft.title.empty());
|
|
EXPECT_TRUE(draft.description.empty());
|
|
EXPECT_EQ(draft.priority, 0);
|
|
EXPECT_EQ(draft.status, DraftStatus::DRAFT);
|
|
EXPECT_TRUE(draft.relatedEventId.empty());
|
|
EXPECT_TRUE(draft.taskType.empty());
|
|
EXPECT_TRUE(draft.requiredResources.empty());
|
|
}
|
|
|
|
// ==================== CreateTaskFromEvent (INTEL) ====================
|
|
TEST(TaskGeneratorTest, CreateIntelligenceTask) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "EVT-INTEL-001";
|
|
evt.type = EventType::INTEL;
|
|
evt.priority = 6;
|
|
evt.location = "sector-7";
|
|
evt.source = "recon_unit";
|
|
|
|
TaskDraft draft = tg.CreateTaskFromEvent(evt);
|
|
EXPECT_EQ(draft.relatedEventId, "EVT-INTEL-001");
|
|
EXPECT_EQ(draft.taskType, "INTEL_ANALYSIS");
|
|
EXPECT_GE(draft.priority, 5);
|
|
EXPECT_EQ(draft.status, DraftStatus::DRAFT);
|
|
EXPECT_FALSE(draft.title.empty());
|
|
EXPECT_FALSE(draft.description.empty());
|
|
EXPECT_FALSE(draft.requiredResources.empty());
|
|
EXPECT_NE(draft.title.find("情报"), std::string::npos);
|
|
}
|
|
|
|
// ==================== CreateTaskFromEvent (THREAT) ====================
|
|
TEST(TaskGeneratorTest, CreateThreatTask) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "EVT-THREAT-001";
|
|
evt.type = EventType::THREAT;
|
|
evt.priority = 8;
|
|
evt.location = "hot-zone";
|
|
evt.source = "early_warning";
|
|
|
|
TaskDraft draft = tg.CreateTaskFromEvent(evt);
|
|
EXPECT_EQ(draft.relatedEventId, "EVT-THREAT-001");
|
|
EXPECT_EQ(draft.taskType, "THREAT_RESPONSE");
|
|
EXPECT_EQ(draft.priority, 10); // 8+2 capped at 10
|
|
EXPECT_EQ(draft.status, DraftStatus::DRAFT);
|
|
EXPECT_FALSE(draft.title.empty());
|
|
EXPECT_FALSE(draft.requiredResources.empty());
|
|
}
|
|
|
|
// ==================== CreateTaskFromEvent (MISSION) ====================
|
|
TEST(TaskGeneratorTest, CreateMissionTask) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "EVT-MISSION-001";
|
|
evt.type = EventType::MISSION;
|
|
evt.priority = 5;
|
|
evt.location = "battlefront";
|
|
|
|
TaskDraft draft = tg.CreateTaskFromEvent(evt);
|
|
EXPECT_EQ(draft.relatedEventId, "EVT-MISSION-001");
|
|
EXPECT_EQ(draft.taskType, "COMBAT_MISSION");
|
|
EXPECT_EQ(draft.priority, 5);
|
|
}
|
|
|
|
// ==================== CreateTaskFromEvent (LOGISTIC) ====================
|
|
TEST(TaskGeneratorTest, CreateLogisticTask) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "EVT-LOG-001";
|
|
evt.type = EventType::LOGISTIC;
|
|
evt.priority = 6;
|
|
evt.location = "base-alpha";
|
|
|
|
TaskDraft draft = tg.CreateTaskFromEvent(evt);
|
|
EXPECT_EQ(draft.relatedEventId, "EVT-LOG-001");
|
|
EXPECT_EQ(draft.taskType, "LOGISTIC_SUPPORT");
|
|
EXPECT_EQ(draft.priority, 5); // 6-1
|
|
}
|
|
|
|
TEST(TaskGeneratorTest, CreateLogisticTaskLowPriority) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "EVT-LOG-002";
|
|
evt.type = EventType::LOGISTIC;
|
|
evt.priority = 1;
|
|
|
|
TaskDraft draft = tg.CreateTaskFromEvent(evt);
|
|
EXPECT_EQ(draft.priority, 1); // max(1-1, 1)
|
|
}
|
|
|
|
// ==================== CreateTaskFromEvent (UNKNOWN) ====================
|
|
TEST(TaskGeneratorTest, CreateUnknownTypeTask) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "EVT-UNK-001";
|
|
evt.type = EventType::UNKNOWN;
|
|
evt.priority = 4;
|
|
|
|
TaskDraft draft = tg.CreateTaskFromEvent(evt);
|
|
EXPECT_EQ(draft.relatedEventId, "EVT-UNK-001");
|
|
// UNKNOWN falls back to first strategy (Intel)
|
|
EXPECT_EQ(draft.taskType, "INTEL_ANALYSIS");
|
|
}
|
|
|
|
// ==================== GetDraftList ====================
|
|
TEST(TaskGeneratorTest, GetDraftListEmpty) {
|
|
TaskGenerator tg;
|
|
auto list = tg.GetDraftList();
|
|
EXPECT_TRUE(list.empty());
|
|
}
|
|
|
|
TEST(TaskGeneratorTest, GetDraftListAfterGeneration) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "e1";
|
|
evt.type = EventType::INTEL;
|
|
evt.priority = 5;
|
|
tg.CreateTaskFromEvent(evt);
|
|
tg.CreateTaskFromEvent(evt);
|
|
auto list = tg.GetDraftList();
|
|
EXPECT_EQ(list.size(), 2u);
|
|
}
|
|
|
|
// ==================== SubmitDraft ====================
|
|
TEST(TaskGeneratorTest, SubmitDraftSuccess) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "e1";
|
|
evt.type = EventType::INTEL;
|
|
evt.priority = 5;
|
|
TaskDraft draft = tg.CreateTaskFromEvent(evt);
|
|
|
|
bool submitted = tg.SubmitDraft(draft.id, "http://engine.local/submit");
|
|
EXPECT_TRUE(submitted);
|
|
}
|
|
|
|
TEST(TaskGeneratorTest, SubmitDraftNotFound) {
|
|
TaskGenerator tg;
|
|
bool submitted = tg.SubmitDraft("nonexistent", "http://engine.local");
|
|
EXPECT_FALSE(submitted);
|
|
}
|
|
|
|
TEST(TaskGeneratorTest, SubmitDraftTwice) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "e1";
|
|
evt.type = EventType::INTEL;
|
|
evt.priority = 5;
|
|
TaskDraft draft = tg.CreateTaskFromEvent(evt);
|
|
|
|
EXPECT_TRUE(tg.SubmitDraft(draft.id, "url1"));
|
|
EXPECT_FALSE(tg.SubmitDraft(draft.id, "url2")); // 已提交后不能再提交
|
|
}
|
|
|
|
// ==================== SubmitDraftAsJson ====================
|
|
TEST(TaskGeneratorTest, SubmitDraftAsJsonSuccess) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "e1";
|
|
evt.type = EventType::THREAT;
|
|
evt.priority = 8;
|
|
TaskDraft draft = tg.CreateTaskFromEvent(evt);
|
|
|
|
nlohmann::json result = tg.SubmitDraftAsJson(draft.id);
|
|
EXPECT_FALSE(result.empty());
|
|
EXPECT_EQ(result["draftId"], draft.id);
|
|
EXPECT_EQ(result["priority"], draft.priority);
|
|
EXPECT_EQ(result["status"], "SUBMITTED");
|
|
EXPECT_TRUE(result.contains("resources"));
|
|
EXPECT_TRUE(result["resources"].is_array());
|
|
}
|
|
|
|
TEST(TaskGeneratorTest, SubmitDraftAsJsonNotFound) {
|
|
TaskGenerator tg;
|
|
nlohmann::json result = tg.SubmitDraftAsJson("nonexistent");
|
|
EXPECT_TRUE(result.empty());
|
|
}
|
|
|
|
TEST(TaskGeneratorTest, SubmitDraftAsJsonTwice) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "e1";
|
|
evt.type = EventType::INTEL;
|
|
evt.priority = 5;
|
|
TaskDraft draft = tg.CreateTaskFromEvent(evt);
|
|
|
|
auto r1 = tg.SubmitDraftAsJson(draft.id);
|
|
EXPECT_FALSE(r1.empty());
|
|
auto r2 = tg.SubmitDraftAsJson(draft.id);
|
|
EXPECT_TRUE(r2.empty());
|
|
}
|
|
|
|
// ==================== SortDraftsByPriority ====================
|
|
TEST(TaskGeneratorTest, SortDraftsByPriorityAscending) {
|
|
TaskGenerator tg;
|
|
for (int p : {3, 9, 1, 7}) {
|
|
Event evt;
|
|
evt.id = "e" + std::to_string(p);
|
|
evt.type = EventType::THREAT;
|
|
evt.priority = p;
|
|
tg.CreateTaskFromEvent(evt);
|
|
}
|
|
tg.SortDraftsByPriority(true);
|
|
auto list = tg.GetDraftList();
|
|
// Threat strategy: p' = min(p+2, 10):
|
|
// 3→5, 9→10, 1→3, 7→9 → ascending: [3,5,9,10]
|
|
EXPECT_EQ(list[0].priority, 3);
|
|
EXPECT_EQ(list[3].priority, 10);
|
|
}
|
|
|
|
TEST(TaskGeneratorTest, SortDraftsByPriorityDescending) {
|
|
TaskGenerator tg;
|
|
for (int p : {2, 8, 4, 6}) {
|
|
Event evt;
|
|
evt.id = "e" + std::to_string(p);
|
|
evt.type = EventType::INTEL;
|
|
evt.priority = p;
|
|
tg.CreateTaskFromEvent(evt);
|
|
}
|
|
tg.SortDraftsByPriority(false);
|
|
auto list = tg.GetDraftList();
|
|
// Intel strategy: p' = max(p, 5):
|
|
// 2→5, 8→8, 4→5, 6→6 → descending: [8, 6, 5, 5]
|
|
EXPECT_EQ(list[0].priority, 8);
|
|
EXPECT_EQ(list[3].priority, 5);
|
|
}
|
|
|
|
// ==================== Observer Pattern ====================
|
|
TEST(TaskGeneratorTest, OnEventReceivedAutoGenerateEnabled) {
|
|
TaskGenerator tg;
|
|
tg.SetAutoGenerate(true);
|
|
|
|
Event evt;
|
|
evt.id = "OBS-1";
|
|
evt.type = EventType::MISSION;
|
|
evt.priority = 5;
|
|
|
|
tg.OnEventReceived(evt);
|
|
EXPECT_EQ(tg.GetDraftCount(), 1u);
|
|
|
|
auto drafts = tg.GetDraftList();
|
|
EXPECT_EQ(drafts[0].relatedEventId, "OBS-1");
|
|
EXPECT_EQ(drafts[0].taskType, "COMBAT_MISSION");
|
|
}
|
|
|
|
TEST(TaskGeneratorTest, OnEventReceivedAutoGenerateDisabled) {
|
|
TaskGenerator tg;
|
|
tg.SetAutoGenerate(false);
|
|
|
|
Event evt;
|
|
evt.id = "OBS-2";
|
|
evt.type = EventType::THREAT;
|
|
evt.priority = 9;
|
|
|
|
tg.OnEventReceived(evt);
|
|
EXPECT_EQ(tg.GetDraftCount(), 0u);
|
|
}
|
|
|
|
TEST(TaskGeneratorTest, OnEventReceivedWithArchivedEvent) {
|
|
TaskGenerator tg;
|
|
tg.SetAutoGenerate(true);
|
|
|
|
Event evt;
|
|
evt.id = "OBS-3";
|
|
evt.type = EventType::INTEL;
|
|
evt.priority = 5;
|
|
evt.status = EventStatus::ARCHIVED;
|
|
|
|
tg.OnEventReceived(evt);
|
|
EXPECT_EQ(tg.GetDraftCount(), 0u);
|
|
}
|
|
|
|
// ==================== SetAutoGenerate / GetDraftCount ====================
|
|
TEST(TaskGeneratorTest, DefaultAutoGenerateIsOff) {
|
|
TaskGenerator tg;
|
|
Event evt;
|
|
evt.id = "e1";
|
|
evt.type = EventType::INTEL;
|
|
evt.priority = 5;
|
|
tg.OnEventReceived(evt);
|
|
EXPECT_EQ(tg.GetDraftCount(), 0u);
|
|
}
|
|
|
|
// ==================== Strategy Names ====================
|
|
TEST(StrategyTest, StrategyNames) {
|
|
IntelTaskStrategy intel;
|
|
EXPECT_EQ(intel.Name(), "IntelTaskStrategy");
|
|
|
|
ThreatTaskStrategy threat;
|
|
EXPECT_EQ(threat.Name(), "ThreatTaskStrategy");
|
|
|
|
MissionTaskStrategy mission;
|
|
EXPECT_EQ(mission.Name(), "MissionTaskStrategy");
|
|
|
|
LogisticTaskStrategy logistic;
|
|
EXPECT_EQ(logistic.Name(), "LogisticTaskStrategy");
|
|
}
|
|
|
|
TEST(StrategyTest, IntelStrategyResources) {
|
|
IntelTaskStrategy strat;
|
|
Event evt;
|
|
evt.id = "e1";
|
|
evt.priority = 5;
|
|
evt.location = "zone";
|
|
evt.source = "src";
|
|
TaskDraft draft = strat.Generate(evt, "DRF-1");
|
|
EXPECT_EQ(draft.requiredResources.size(), 3u);
|
|
EXPECT_THAT(draft.requiredResources, testing::Contains("ANALYST_TEAM"));
|
|
EXPECT_THAT(draft.requiredResources, testing::Contains("SAT_IMAGERY"));
|
|
EXPECT_THAT(draft.requiredResources, testing::Contains("SIGINT_UNIT"));
|
|
}
|
|
|
|
TEST(StrategyTest, ThreatStrategyResources) {
|
|
ThreatTaskStrategy strat;
|
|
Event evt;
|
|
evt.id = "e1";
|
|
evt.priority = 5;
|
|
evt.location = "zone";
|
|
evt.source = "src";
|
|
TaskDraft draft = strat.Generate(evt, "DRF-1");
|
|
EXPECT_EQ(draft.requiredResources.size(), 3u);
|
|
EXPECT_THAT(draft.requiredResources, testing::Contains("STRIKE_UNIT"));
|
|
}
|
|
|
|
TEST(StrategyTest, MissionStrategyResources) {
|
|
MissionTaskStrategy strat;
|
|
Event evt;
|
|
evt.id = "e1";
|
|
evt.priority = 5;
|
|
evt.location = "zone";
|
|
evt.source = "src";
|
|
TaskDraft draft = strat.Generate(evt, "DRF-1");
|
|
EXPECT_EQ(draft.requiredResources.size(), 3u);
|
|
EXPECT_THAT(draft.requiredResources, testing::Contains("INFANTRY_PLT"));
|
|
}
|
|
|
|
TEST(StrategyTest, LogisticStrategyResources) {
|
|
LogisticTaskStrategy strat;
|
|
Event evt;
|
|
evt.id = "e1";
|
|
evt.priority = 5;
|
|
evt.location = "zone";
|
|
evt.source = "src";
|
|
TaskDraft draft = strat.Generate(evt, "DRF-1");
|
|
EXPECT_EQ(draft.requiredResources.size(), 3u);
|
|
EXPECT_THAT(draft.requiredResources, testing::Contains("SUPPLY_CONVOY"));
|
|
}
|
|
|
|
// ==================== 边界与压力测试 ====================
|
|
TEST(TaskGeneratorTest, CreateManyTasks) {
|
|
TaskGenerator tg;
|
|
for (int i = 0; i < 100; ++i) {
|
|
Event evt;
|
|
evt.id = "bulk-" + std::to_string(i);
|
|
evt.type = EventType::INTEL;
|
|
evt.priority = (i % 10) + 1;
|
|
tg.CreateTaskFromEvent(evt);
|
|
}
|
|
EXPECT_EQ(tg.GetDraftCount(), 100u);
|
|
|
|
tg.SortDraftsByPriority(false);
|
|
auto list = tg.GetDraftList();
|
|
EXPECT_GE(list[0].priority, list.back().priority);
|
|
}
|