#include #include #include "core/plan.hpp" using namespace battlefield; // ==================== PlanSubTask 结构体 ==================== TEST(PlanSubTaskTest, DefaultConstruction) { PlanSubTask st; EXPECT_TRUE(st.id.empty()); EXPECT_TRUE(st.parentId.empty()); EXPECT_TRUE(st.name.empty()); EXPECT_TRUE(st.description.empty()); EXPECT_EQ(st.orderIndex, 0); EXPECT_TRUE(st.assignedUnit.empty()); EXPECT_DOUBLE_EQ(st.estimatedDuration, 0.0); EXPECT_EQ(st.resourceCost, 0); } // ==================== Plan 结构体 ==================== TEST(PlanTest, DefaultConstruction) { Plan plan; EXPECT_TRUE(plan.id.empty()); EXPECT_TRUE(plan.name.empty()); EXPECT_TRUE(plan.description.empty()); EXPECT_TRUE(plan.subTasks.empty()); EXPECT_DOUBLE_EQ(plan.score, 0.0); } TEST(PlanTest, SubTaskCountEmpty) { Plan plan; EXPECT_EQ(plan.SubTaskCount(), 0u); } TEST(PlanTest, SubTaskCountWithTasks) { Plan plan; PlanSubTask st; plan.subTasks.push_back(st); plan.subTasks.push_back(st); EXPECT_EQ(plan.SubTaskCount(), 2u); } TEST(PlanTest, TotalEstimatedDurationEmpty) { Plan plan; EXPECT_DOUBLE_EQ(plan.TotalEstimatedDuration(), 0.0); } TEST(PlanTest, TotalEstimatedDuration) { Plan plan; PlanSubTask st1; st1.estimatedDuration = 30.0; PlanSubTask st2; st2.estimatedDuration = 45.5; plan.subTasks.push_back(st1); plan.subTasks.push_back(st2); EXPECT_DOUBLE_EQ(plan.TotalEstimatedDuration(), 75.5); } TEST(PlanTest, TotalResourceCostEmpty) { Plan plan; EXPECT_EQ(plan.TotalResourceCost(), 0); } TEST(PlanTest, TotalResourceCost) { Plan plan; PlanSubTask st1; st1.resourceCost = 10; PlanSubTask st2; st2.resourceCost = 25; plan.subTasks.push_back(st1); plan.subTasks.push_back(st2); EXPECT_EQ(plan.TotalResourceCost(), 35); } // ==================== PlanComparison 结构体 ==================== TEST(PlanComparisonTest, DefaultConstruction) { PlanComparison cmp; EXPECT_TRUE(cmp.differences.empty()); } // ==================== CreatePlan ==================== TEST(PlanManagerTest, CreatePlan) { PlanManager pm; Plan plan = pm.CreatePlan("测试方案", "测试描述"); EXPECT_FALSE(plan.id.empty()); EXPECT_TRUE(plan.id.find("PLN-") != std::string::npos); EXPECT_EQ(plan.name, "测试方案"); EXPECT_EQ(plan.description, "测试描述"); EXPECT_DOUBLE_EQ(plan.score, 0.0); EXPECT_TRUE(plan.subTasks.empty()); EXPECT_EQ(pm.GetPlanCount(), 1u); } TEST(PlanManagerTest, CreateMultiplePlans) { PlanManager pm; pm.CreatePlan("A", "desc A"); pm.CreatePlan("B", "desc B"); pm.CreatePlan("C", "desc C"); EXPECT_EQ(pm.GetPlanCount(), 3u); } // ==================== GetPlan ==================== TEST(PlanManagerTest, GetPlanFound) { PlanManager pm; Plan created = pm.CreatePlan("查找方案", "desc"); Plan found = pm.GetPlan(created.id); EXPECT_EQ(found.id, created.id); EXPECT_EQ(found.name, "查找方案"); } TEST(PlanManagerTest, GetPlanNotFound) { PlanManager pm; Plan plan = pm.GetPlan("nonexistent"); EXPECT_TRUE(plan.id.empty()); } // ==================== GetPlanList ==================== TEST(PlanManagerTest, GetPlanListEmpty) { PlanManager pm; auto list = pm.GetPlanList(); EXPECT_TRUE(list.empty()); } TEST(PlanManagerTest, GetPlanListWithPlans) { PlanManager pm; pm.CreatePlan("A", ""); pm.CreatePlan("B", ""); auto list = pm.GetPlanList(); EXPECT_EQ(list.size(), 2u); } // ==================== AddSubTask ==================== TEST(PlanManagerTest, AddSubTaskValid) { PlanManager pm; Plan plan = pm.CreatePlan("方案", ""); PlanSubTask st{"ST-1", "", "侦察", "无人机侦察", 1, "drone", 30.0, 3}; EXPECT_TRUE(pm.AddSubTask(plan.id, st)); EXPECT_EQ(pm.GetPlan(plan.id).SubTaskCount(), 1u); } TEST(PlanManagerTest, AddSubTaskInvalidPlan) { PlanManager pm; PlanSubTask st{"ST-1", "", "侦察", "", 1, "", 30.0, 3}; EXPECT_FALSE(pm.AddSubTask("nonexistent", st)); } TEST(PlanManagerTest, AddMultipleSubTasks) { PlanManager pm; Plan plan = pm.CreatePlan("方案", ""); for (int i = 0; i < 5; ++i) { PlanSubTask st{"ST-"+std::to_string(i), "", "任务"+std::to_string(i), "", i, "unit", 10.0, 1}; pm.AddSubTask(plan.id, st); } EXPECT_EQ(pm.GetPlan(plan.id).SubTaskCount(), 5u); } // ==================== RemoveSubTask ==================== TEST(PlanManagerTest, RemoveSubTaskValid) { PlanManager pm; Plan plan = pm.CreatePlan("方案", ""); PlanSubTask st{"ST-1", "", "侦察", "", 1, "", 10.0, 1}; PlanSubTask st2{"ST-2", "", "打击", "", 2, "", 20.0, 2}; pm.AddSubTask(plan.id, st); pm.AddSubTask(plan.id, st2); EXPECT_EQ(pm.GetPlan(plan.id).SubTaskCount(), 2u); EXPECT_TRUE(pm.RemoveSubTask(plan.id, "ST-1")); EXPECT_EQ(pm.GetPlan(plan.id).SubTaskCount(), 1u); } TEST(PlanManagerTest, RemoveSubTaskInvalidPlan) { PlanManager pm; EXPECT_FALSE(pm.RemoveSubTask("nonexistent", "ST-1")); } TEST(PlanManagerTest, RemoveSubTaskInvalidSubTask) { PlanManager pm; Plan plan = pm.CreatePlan("方案", ""); EXPECT_FALSE(pm.RemoveSubTask(plan.id, "nonexistent")); } // ==================== ReorganizePlan ==================== TEST(PlanManagerTest, ReorganizePlanValid) { PlanManager pm; Plan plan = pm.CreatePlan("方案", ""); std::vector newTasks = { {"NEW-1", "", "新任务1", "", 1, "unit_a", 10.0, 1}, {"NEW-2", "NEW-1", "新任务2", "", 2, "unit_b", 20.0, 2} }; EXPECT_TRUE(pm.ReorganizePlan(plan.id, newTasks)); EXPECT_EQ(pm.GetPlan(plan.id).SubTaskCount(), 2u); } TEST(PlanManagerTest, ReorganizePlanInvalidPlan) { PlanManager pm; std::vector empty; EXPECT_FALSE(pm.ReorganizePlan("nonexistent", empty)); } // ==================== MergePlans ==================== TEST(PlanManagerTest, MergePlans) { PlanManager pm; Plan a = pm.CreatePlan("方案A", ""); Plan b = pm.CreatePlan("方案B", ""); PlanSubTask stA{"ST-A-1", "", "A1", "", 1, "", 10.0, 1}; PlanSubTask stB1{"ST-B-1", "", "B1", "", 1, "", 20.0, 2}; PlanSubTask stB2{"ST-B-2", "", "B2", "", 2, "", 30.0, 3}; pm.AddSubTask(a.id, stA); pm.AddSubTask(b.id, stB1); pm.AddSubTask(b.id, stB2); Plan merged = pm.MergePlans({a.id, b.id}); EXPECT_TRUE(merged.id.find("PLN-MERGED-") != std::string::npos); EXPECT_EQ(merged.SubTaskCount(), 3u); } TEST(PlanManagerTest, MergePlansEmptyList) { PlanManager pm; Plan merged = pm.MergePlans({}); EXPECT_EQ(merged.SubTaskCount(), 0u); } TEST(PlanManagerTest, MergePlansWithInvalidIds) { PlanManager pm; Plan a = pm.CreatePlan("方案A", ""); PlanSubTask st{"ST-1", "", "task", "", 1, "", 10.0, 1}; pm.AddSubTask(a.id, st); Plan merged = pm.MergePlans({a.id, "nonexistent"}); EXPECT_EQ(merged.SubTaskCount(), 1u); } TEST(PlanManagerTest, MergePlansCalculatesAverageScore) { PlanManager pm; Plan a = pm.CreatePlan("方案A", ""); Plan b = pm.CreatePlan("方案B", ""); PlanSubTask st{"ST-1", "", "task", "", 1, "", 10.0, 5}; pm.AddSubTask(a.id, st); pm.AddSubTask(b.id, st); pm.RecalculateAllScores(); Plan merged = pm.MergePlans({a.id, b.id}); EXPECT_GT(merged.score, 0.0); } // ==================== 排序测试 ==================== TEST(PlanManagerTest, SortPlansByScoreDescending) { PlanManager pm; Plan a = pm.CreatePlan("方案A", ""); Plan b = pm.CreatePlan("方案B", ""); PlanSubTask st{"ST-1", "", "task", "", 1, "unit", 15.0, 3}; pm.AddSubTask(a.id, st); pm.RecalculateAllScores(); pm.SortPlansByScore(false); auto list = pm.GetPlanList(); EXPECT_GE(list[0].score, list[1].score); } TEST(PlanManagerTest, SortPlansByNameAscending) { PlanManager pm; pm.CreatePlan("Gamma", ""); pm.CreatePlan("Alpha", ""); pm.CreatePlan("Beta", ""); pm.SortPlansByName(true); // std::map 以 key(id) 排序,但名称排序逻辑已验证不崩溃 SUCCEED(); } TEST(PlanManagerTest, SortPlansByNameDescending) { PlanManager pm; pm.CreatePlan("Alpha", ""); pm.CreatePlan("Zulu", ""); pm.SortPlansByName(false); // std::map 以 key(id) 排序,无法验证名称排序的 map 遍历顺序 SUCCEED(); } TEST(PlanManagerTest, SortPlansBySubTaskCountDescending) { PlanManager pm; Plan a = pm.CreatePlan("A", ""); Plan b = pm.CreatePlan("B", ""); for (int i = 0; i < 3; ++i) { PlanSubTask st{"S-"+std::to_string(i), "", "", "", i, "", 1.0, 1}; pm.AddSubTask(a.id, st); } pm.SortPlansBySubTaskCount(false); auto list = pm.GetPlanList(); EXPECT_EQ(list[0].SubTaskCount(), 3u); } TEST(PlanManagerTest, SortPlansByDurationAscending) { PlanManager pm; Plan a = pm.CreatePlan("fast", ""); Plan b = pm.CreatePlan("slow", ""); PlanSubTask stFast{"ST-F", "", "", "", 1, "", 10.0, 1}; PlanSubTask stSlow{"ST-S", "", "", "", 1, "", 100.0, 1}; pm.AddSubTask(a.id, stFast); pm.AddSubTask(b.id, stSlow); pm.SortPlansByDuration(true); auto list = pm.GetPlanList(); EXPECT_DOUBLE_EQ(list[0].TotalEstimatedDuration(), 10.0); } // ==================== 评分计算 ==================== TEST(PlanManagerTest, CalculatePlanScoreEmptyPlan) { PlanManager pm; Plan plan; double score = pm.CalculatePlanScore(plan); EXPECT_GE(score, 0.0); } TEST(PlanManagerTest, CalculatePlanScoreWithSubTasks) { PlanManager pm; Plan plan; PlanSubTask st{"ST-1", "", "task", "", 1, "unit_a", 15.0, 2}; plan.subTasks.push_back(st); double score = pm.CalculatePlanScore(plan); EXPECT_GT(score, 0.0); } TEST(PlanManagerTest, CalculatePlanScoreWithMultipleUnits) { PlanManager pm; Plan plan; PlanSubTask st1{"ST-1", "", "", "", 1, "unit_a", 10.0, 1}; PlanSubTask st2{"ST-2", "", "", "", 2, "unit_b", 10.0, 1}; PlanSubTask st3{"ST-3", "", "", "", 3, "unit_c", 10.0, 1}; plan.subTasks.push_back(st1); plan.subTasks.push_back(st2); plan.subTasks.push_back(st3); double score = pm.CalculatePlanScore(plan); EXPECT_GT(score, 30.0); // 3 subTasks * 5 + time bonus + resource bonus + unit bonus } TEST(PlanManagerTest, RecalculateAllScores) { PlanManager pm; Plan a = pm.CreatePlan("A", "desc A"); Plan b = pm.CreatePlan("B", ""); PlanSubTask st{"ST-1", "", "", "", 1, "", 10.0, 1}; pm.AddSubTask(a.id, st); pm.RecalculateAllScores(); EXPECT_GT(pm.GetPlan(a.id).score, 0.0); EXPECT_DOUBLE_EQ(pm.GetPlan(b.id).score, pm.GetPlan(b.id).score); // 不变 } // ==================== 方案对比 ==================== TEST(PlanManagerTest, ComparePlanDetails) { PlanManager pm; Plan a = pm.CreatePlan("方案A", "描述A"); Plan b = pm.CreatePlan("方案B", "描述B不同"); PlanSubTask st1{"ST-A", "", "", "", 1, "unit_a", 10.0, 3}; PlanSubTask st2{"ST-B", "", "", "", 1, "unit_b", 20.0, 5}; pm.AddSubTask(a.id, st1); pm.AddSubTask(b.id, st2); pm.RecalculateAllScores(); PlanComparison cmp = pm.ComparePlanDetails(a.id, b.id); EXPECT_FALSE(cmp.differences.empty()); EXPECT_GE(cmp.differences.size(), 3u); // 评分、子任务数、时间、资源、描述、执行单元 } TEST(PlanManagerTest, ComparePlanDetailsInvalidPlan) { PlanManager pm; pm.CreatePlan("A", ""); PlanComparison cmp = pm.ComparePlanDetails("A", "nonexistent"); EXPECT_EQ(cmp.differences.size(), 1u); EXPECT_THAT(cmp.differences[0], testing::HasSubstr("不存在")); } TEST(PlanManagerTest, ComparePlansString) { PlanManager pm; Plan a = pm.CreatePlan("方案A", ""); Plan b = pm.CreatePlan("方案B", ""); std::string result = pm.ComparePlans(a.id, b.id); EXPECT_FALSE(result.empty()); EXPECT_THAT(result, testing::HasSubstr("Comparison")); } // ==================== GetTopologicalOrder ==================== TEST(PlanManagerTest, GetTopologicalOrderEmpty) { PlanManager pm; Plan plan = pm.CreatePlan("空方案", ""); auto order = pm.GetTopologicalOrder(plan.id); EXPECT_TRUE(order.empty()); } TEST(PlanManagerTest, GetTopologicalOrderSingleRoot) { PlanManager pm; Plan plan = pm.CreatePlan("单根", ""); PlanSubTask root{"ROOT", "", "根任务", "", 0, "", 10.0, 1}; pm.AddSubTask(plan.id, root); auto order = pm.GetTopologicalOrder(plan.id); EXPECT_EQ(order.size(), 1u); EXPECT_EQ(order[0].id, "ROOT"); } TEST(PlanManagerTest, GetTopologicalOrderTree) { PlanManager pm; Plan plan = pm.CreatePlan("树形", ""); PlanSubTask root{"ROOT", "", "根", "", 0, "", 10.0, 1}; PlanSubTask child1{"CH1", "ROOT", "子1", "", 1, "", 10.0, 1}; PlanSubTask child2{"CH2", "ROOT", "子2", "", 2, "", 10.0, 1}; PlanSubTask grandchild{"GC", "CH1", "孙", "", 1, "", 10.0, 1}; pm.AddSubTask(plan.id, root); pm.AddSubTask(plan.id, child1); pm.AddSubTask(plan.id, child2); pm.AddSubTask(plan.id, grandchild); auto order = pm.GetTopologicalOrder(plan.id); EXPECT_EQ(order.size(), 4u); EXPECT_EQ(order[0].id, "ROOT"); // 根节点优先 } TEST(PlanManagerTest, GetTopologicalOrderInvalidPlan) { PlanManager pm; auto order = pm.GetTopologicalOrder("nonexistent"); EXPECT_TRUE(order.empty()); } // ==================== 边界与压力测试 ==================== TEST(PlanManagerTest, CreateManyPlans) { PlanManager pm; for (int i = 0; i < 50; ++i) { pm.CreatePlan("Plan-" + std::to_string(i), ""); } EXPECT_EQ(pm.GetPlanCount(), 50u); } TEST(PlanManagerTest, LargeSubTaskTree) { PlanManager pm; Plan plan = pm.CreatePlan("大树", ""); for (int i = 0; i < 100; ++i) { PlanSubTask st{"ST-"+std::to_string(i), "", "Task"+std::to_string(i), "", i, "u"+std::to_string(i%5), static_cast(i), i%10}; pm.AddSubTask(plan.id, st); } EXPECT_EQ(pm.GetPlan(plan.id).SubTaskCount(), 100u); }