356 lines
11 KiB
C++
356 lines
11 KiB
C++
|
|
#include <gtest/gtest.h>
|
||
|
|
#include <gmock/gmock.h>
|
||
|
|
#include "core/template.hpp"
|
||
|
|
#include <fstream>
|
||
|
|
|
||
|
|
using namespace battlefield;
|
||
|
|
|
||
|
|
// ==================== TaskTemplate 结构体 ====================
|
||
|
|
TEST(TemplateStructTest, DefaultConstruction) {
|
||
|
|
TaskTemplate tmpl;
|
||
|
|
EXPECT_TRUE(tmpl.versionId.empty());
|
||
|
|
EXPECT_TRUE(tmpl.name.empty());
|
||
|
|
EXPECT_TRUE(tmpl.description.empty());
|
||
|
|
EXPECT_TRUE(tmpl.content.empty());
|
||
|
|
EXPECT_TRUE(tmpl.dateIndex.empty());
|
||
|
|
EXPECT_FALSE(tmpl.isActive);
|
||
|
|
EXPECT_FALSE(tmpl.isRecommended);
|
||
|
|
EXPECT_DOUBLE_EQ(tmpl.score, 0.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== VersionDiff 结构体 ====================
|
||
|
|
TEST(VersionDiffTest, DefaultConstruction) {
|
||
|
|
VersionDiff diff;
|
||
|
|
EXPECT_TRUE(diff.versionA.empty());
|
||
|
|
EXPECT_TRUE(diff.versionB.empty());
|
||
|
|
EXPECT_TRUE(diff.addedFields.empty());
|
||
|
|
EXPECT_TRUE(diff.removedFields.empty());
|
||
|
|
EXPECT_TRUE(diff.changedFields.empty());
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== LoadTemplates (simulated) ====================
|
||
|
|
TEST(TemplateManagerTest, LoadTemplatesSimulated) {
|
||
|
|
TemplateManager tm;
|
||
|
|
size_t count = tm.LoadTemplates("/nonexistent/path/simulated");
|
||
|
|
EXPECT_GE(count, 3u);
|
||
|
|
EXPECT_EQ(tm.GetTemplateCount(), count);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== ReceiveTemplatePush ====================
|
||
|
|
TEST(TemplateManagerTest, ReceiveTemplatePushSingle) {
|
||
|
|
TemplateManager tm;
|
||
|
|
bool ok = tm.ReceiveTemplatePush(
|
||
|
|
R"({"versionId":"v1.0","name":"突击模板","description":"测试","isActive":true})");
|
||
|
|
EXPECT_TRUE(ok);
|
||
|
|
EXPECT_EQ(tm.GetTemplateCount(), 1u);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, ReceiveTemplatePushArray) {
|
||
|
|
TemplateManager tm;
|
||
|
|
bool ok = tm.ReceiveTemplatePush(
|
||
|
|
R"([{"versionId":"v1.0","name":"T1"},{"versionId":"v2.0","name":"T2"},{"versionId":"v3.0","name":"T3"}])");
|
||
|
|
EXPECT_TRUE(ok);
|
||
|
|
EXPECT_EQ(tm.GetTemplateCount(), 3u);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, ReceiveTemplatePushInvalidJson) {
|
||
|
|
TemplateManager tm;
|
||
|
|
bool ok = tm.ReceiveTemplatePush("not json{{}");
|
||
|
|
EXPECT_FALSE(ok);
|
||
|
|
EXPECT_EQ(tm.GetTemplateCount(), 0u);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== SaveTemplateToFile ====================
|
||
|
|
TEST(TemplateManagerTest, SaveTemplateToFile) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
auto list = tm.GetTemplateList();
|
||
|
|
|
||
|
|
if (!list.empty()) {
|
||
|
|
bool ok = tm.SaveTemplateToFile(list[0], ".");
|
||
|
|
EXPECT_TRUE(ok);
|
||
|
|
// cleanup
|
||
|
|
std::remove(("./template_" + list[0].versionId + ".json").c_str());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== GetTemplateList ====================
|
||
|
|
TEST(TemplateManagerTest, GetTemplateListEmpty) {
|
||
|
|
TemplateManager tm;
|
||
|
|
auto list = tm.GetTemplateList();
|
||
|
|
EXPECT_TRUE(list.empty());
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, GetTemplateListAfterLoad) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
auto list = tm.GetTemplateList();
|
||
|
|
EXPECT_GE(list.size(), 3u);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== 排序 ====================
|
||
|
|
TEST(TemplateManagerTest, SortTemplatesByNameAscending) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
tm.ReceiveTemplatePush(
|
||
|
|
R"([{"versionId":"v10","name":"AAA"},{"versionId":"v20","name":"ZZZ"},{"versionId":"v30","name":"MMM"}])");
|
||
|
|
tm.SortTemplatesByName(true);
|
||
|
|
auto list = tm.GetTemplateList();
|
||
|
|
if (list.size() >= 3) {
|
||
|
|
EXPECT_LE(list[0].name, list[1].name);
|
||
|
|
EXPECT_LE(list[1].name, list[2].name);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, SortTemplatesByNameDescending) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.ReceiveTemplatePush(
|
||
|
|
R"([{"versionId":"v1","name":"A"},{"versionId":"v2","name":"Z"},{"versionId":"v3","name":"M"}])");
|
||
|
|
tm.SortTemplatesByName(false);
|
||
|
|
auto list = tm.GetTemplateList();
|
||
|
|
EXPECT_GE(list[0].name, list[1].name);
|
||
|
|
EXPECT_GE(list[1].name, list[2].name);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, SortTemplatesByScoreAscending) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
|
||
|
|
// Assign known scores
|
||
|
|
auto list = tm.GetTemplateList();
|
||
|
|
for (auto& t : list) { t.score = 50.0; }
|
||
|
|
// Push additional with different scores
|
||
|
|
tm.ReceiveTemplatePush(R"({"versionId":"vX","name":"X","isActive":true})");
|
||
|
|
tm.ReceiveTemplatePush(R"({"versionId":"vY","name":"Y"})");
|
||
|
|
|
||
|
|
tm.SortTemplatesByScore(true);
|
||
|
|
auto sorted = tm.GetTemplateList();
|
||
|
|
for (size_t i = 1; i < sorted.size(); ++i) {
|
||
|
|
EXPECT_LE(sorted[i-1].score, sorted[i].score);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, SortTemplatesByScoreDescending) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
tm.ReceiveTemplatePush(R"({"versionId":"vX","name":"X","isActive":true})");
|
||
|
|
tm.ReceiveTemplatePush(R"({"versionId":"vY","name":"Y"})");
|
||
|
|
|
||
|
|
tm.SortTemplatesByScore(false);
|
||
|
|
auto sorted = tm.GetTemplateList();
|
||
|
|
for (size_t i = 1; i < sorted.size(); ++i) {
|
||
|
|
EXPECT_GE(sorted[i-1].score, sorted[i].score);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, SortTemplatesByVersionAscending) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.ReceiveTemplatePush(
|
||
|
|
R"([{"versionId":"v3.0","name":"C"},{"versionId":"v1.0","name":"A"},{"versionId":"v2.0","name":"B"}])");
|
||
|
|
tm.SortTemplatesByVersion(true);
|
||
|
|
auto list = tm.GetTemplateList();
|
||
|
|
EXPECT_EQ(list[0].versionId, "v1.0");
|
||
|
|
EXPECT_EQ(list[1].versionId, "v2.0");
|
||
|
|
EXPECT_EQ(list[2].versionId, "v3.0");
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, SortTemplatesByVersionDescending) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.ReceiveTemplatePush(
|
||
|
|
R"([{"versionId":"v1.0","name":"A"},{"versionId":"v2.0","name":"B"},{"versionId":"v3.0","name":"C"}])");
|
||
|
|
tm.SortTemplatesByVersion(false);
|
||
|
|
auto list = tm.GetTemplateList();
|
||
|
|
EXPECT_EQ(list[0].versionId, "v3.0");
|
||
|
|
EXPECT_EQ(list.back().versionId, "v1.0");
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== FilterByCategory ====================
|
||
|
|
TEST(TemplateManagerTest, FilterByCategoryMatch) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
auto filtered = tm.FilterByCategory("作战");
|
||
|
|
EXPECT_GE(filtered.size(), 1u);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, FilterByCategoryNoMatch) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
auto filtered = tm.FilterByCategory("不可能匹配的关键词xyz");
|
||
|
|
EXPECT_TRUE(filtered.empty());
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, FilterByCategoryContentMatch) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.ReceiveTemplatePush(
|
||
|
|
R"({"versionId":"v1","name":"模版","description":"test","content":"{\"type\":\"mission\"}"})");
|
||
|
|
auto filtered = tm.FilterByCategory("mission");
|
||
|
|
EXPECT_EQ(filtered.size(), 1u);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== SelectTemplate ====================
|
||
|
|
TEST(TemplateManagerTest, SelectTemplateFound) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
auto selected = tm.SelectTemplate("v2.1");
|
||
|
|
EXPECT_EQ(selected.versionId, "v2.1");
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, SelectTemplateNotFound) {
|
||
|
|
TemplateManager tm;
|
||
|
|
auto selected = tm.SelectTemplate("nonexistent");
|
||
|
|
EXPECT_TRUE(selected.versionId.empty());
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== SetActiveVersion ====================
|
||
|
|
TEST(TemplateManagerTest, SetActiveVersion) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
EXPECT_TRUE(tm.SetActiveVersion("v2.2"));
|
||
|
|
|
||
|
|
auto list = tm.GetTemplateList();
|
||
|
|
int activeCount = 0;
|
||
|
|
for (const auto& t : list) {
|
||
|
|
if (t.isActive) {
|
||
|
|
EXPECT_EQ(t.versionId, "v2.2");
|
||
|
|
++activeCount;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EXPECT_EQ(activeCount, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== RecommendTemplate ====================
|
||
|
|
TEST(TemplateManagerTest, RecommendTemplateEmpty) {
|
||
|
|
TemplateManager tm;
|
||
|
|
auto recommended = tm.RecommendTemplate();
|
||
|
|
EXPECT_TRUE(recommended.versionId.empty());
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, RecommendTemplateWithTemplates) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
auto recommended = tm.RecommendTemplate();
|
||
|
|
EXPECT_FALSE(recommended.versionId.empty());
|
||
|
|
EXPECT_GT(recommended.score, 0.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== RecommendTopTemplates ====================
|
||
|
|
TEST(TemplateManagerTest, RecommendTopTemplatesEmpty) {
|
||
|
|
TemplateManager tm;
|
||
|
|
auto top = tm.RecommendTopTemplates(3);
|
||
|
|
EXPECT_TRUE(top.empty());
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, RecommendTopTemplates) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
auto top = tm.RecommendTopTemplates(2);
|
||
|
|
EXPECT_LE(top.size(), 2u);
|
||
|
|
if (top.size() >= 2) {
|
||
|
|
EXPECT_GE(top[0].score, top[1].score);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, RecommendTopTemplatesMoreThanAvailable) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
auto top = tm.RecommendTopTemplates(100);
|
||
|
|
EXPECT_LE(top.size(), tm.GetTemplateCount());
|
||
|
|
// scores should be sorted descending
|
||
|
|
for (size_t i = 1; i < top.size(); ++i) {
|
||
|
|
EXPECT_GE(top[i-1].score, top[i].score);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== CalculateTemplateScore ====================
|
||
|
|
TEST(TemplateManagerTest, CalculateTemplateScoreActive) {
|
||
|
|
TemplateManager tm;
|
||
|
|
TaskTemplate t;
|
||
|
|
t.versionId = "v1.0";
|
||
|
|
t.isActive = true;
|
||
|
|
t.name = "作战模板";
|
||
|
|
t.description = "详细描述文字";
|
||
|
|
t.content = R"({"type":"mission","subtasks":[{"name":"A"},{"name":"B"},{"name":"C"}]})";
|
||
|
|
|
||
|
|
double score = tm.CalculateTemplateScore(t);
|
||
|
|
EXPECT_GT(score, 40.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, CalculateTemplateScoreInactive) {
|
||
|
|
TemplateManager tm;
|
||
|
|
TaskTemplate t;
|
||
|
|
t.versionId = "v1.0";
|
||
|
|
t.isActive = false;
|
||
|
|
t.name = "T";
|
||
|
|
t.description = "";
|
||
|
|
t.content = "{}";
|
||
|
|
|
||
|
|
double score = tm.CalculateTemplateScore(t);
|
||
|
|
EXPECT_GE(score, 0.0);
|
||
|
|
EXPECT_LT(score, 15.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, CalculateTemplateScoreWithSubTasks) {
|
||
|
|
TemplateManager tm;
|
||
|
|
TaskTemplate t;
|
||
|
|
t.isActive = true;
|
||
|
|
t.name = "作战模板";
|
||
|
|
t.description = "标准作战流程";
|
||
|
|
t.versionId = "v3.5";
|
||
|
|
t.content = R"({"type":"mission","subtasks":[{"name":"A"},{"name":"B"},{"name":"C"},{"name":"D"},{"name":"E"}]})";
|
||
|
|
|
||
|
|
double score = tm.CalculateTemplateScore(t);
|
||
|
|
EXPECT_GT(score, 50.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== CompareVersions ====================
|
||
|
|
TEST(TemplateManagerTest, CompareVersions) {
|
||
|
|
TemplateManager tm;
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
|
||
|
|
auto diff = tm.CompareVersions("v2.1", "v2.2");
|
||
|
|
EXPECT_EQ(diff.versionA, "v2.1");
|
||
|
|
EXPECT_EQ(diff.versionB, "v2.2");
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, CompareVersionsNonExistent) {
|
||
|
|
TemplateManager tm;
|
||
|
|
auto diff = tm.CompareVersions("nope1", "nope2");
|
||
|
|
EXPECT_EQ(diff.versionA, "nope1");
|
||
|
|
EXPECT_EQ(diff.versionB, "nope2");
|
||
|
|
EXPECT_TRUE(diff.addedFields.empty());
|
||
|
|
EXPECT_TRUE(diff.removedFields.empty());
|
||
|
|
EXPECT_TRUE(diff.changedFields.empty());
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, CompareVersionsWithDifferences) {
|
||
|
|
TemplateManager tm;
|
||
|
|
// Push two templates with different content
|
||
|
|
tm.ReceiveTemplatePush(
|
||
|
|
R"({"versionId":"vA","name":"A","content":"{\"a\":1,\"b\":2,\"c\":3}"})");
|
||
|
|
tm.ReceiveTemplatePush(
|
||
|
|
R"({"versionId":"vB","name":"B","content":"{\"a\":1,\"c\":3,\"d\":4}"})");
|
||
|
|
|
||
|
|
auto diff = tm.CompareVersions("vA", "vB");
|
||
|
|
if (!diff.addedFields.empty() || !diff.removedFields.empty()) {
|
||
|
|
// vA 有 'b', vB 没有 → removed
|
||
|
|
// vB 有 'd', vA 没有 → added
|
||
|
|
SUCCEED();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== 边界测试 ====================
|
||
|
|
TEST(TemplateManagerTest, GetTemplateCount) {
|
||
|
|
TemplateManager tm;
|
||
|
|
EXPECT_EQ(tm.GetTemplateCount(), 0u);
|
||
|
|
tm.LoadTemplates("/simulated");
|
||
|
|
EXPECT_GT(tm.GetTemplateCount(), 0u);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(TemplateManagerTest, MultipleLoadsAccumulate) {
|
||
|
|
TemplateManager tm;
|
||
|
|
size_t first = tm.LoadTemplates("/simulated");
|
||
|
|
size_t second = tm.LoadTemplates("/simulated2");
|
||
|
|
// 每次模拟加载固定生成3个模板
|
||
|
|
EXPECT_EQ(tm.GetTemplateCount(), 6u);
|
||
|
|
}
|