#include #include #include #include #include #include "dto/NavDto.hpp" using namespace geopro::data; namespace { QJsonArray arrOf(const char* json) { return QJsonDocument::fromJson(QByteArray(json)).array(); } } // namespace TEST(NavDto, ParseWorkspacesMapsFieldsAndCurrentFlag) { const auto arr = arrOf(R"([ {"id":"t1","name":"个人空间","ownerType":1,"isCurTenant":1}, {"id":"t2","name":"企业A","ownerType":2,"isCurTenant":0} ])"); const auto ws = dto::parseWorkspaces(arr); ASSERT_EQ(ws.size(), 2u); EXPECT_EQ(ws[0].id, "t1"); EXPECT_EQ(ws[0].ownerType, 1); EXPECT_TRUE(ws[0].isCurrent); EXPECT_FALSE(ws[1].isCurrent); } namespace { QJsonObject objOf(const char* json) { return QJsonDocument::fromJson(QByteArray(json)).object(); } } // namespace TEST(NavDto, ParseProjectsMapsCrsAndPaging) { const auto data = objOf(R"({ "hasNextPage": true, "projectList": [ {"id":"p1","projectName":"青海湖北岸","projectTypeName":"ERT", "referenceCRSCode":"EPSG:4547","referenceCRSName":"CGCS2000","status":1} ] })"); const auto page = dto::parseProjects(data); EXPECT_TRUE(page.hasNextPage); ASSERT_EQ(page.projects.size(), 1u); EXPECT_EQ(page.projects[0].id, "p1"); EXPECT_EQ(page.projects[0].name, "青海湖北岸"); EXPECT_EQ(page.projects[0].typeName, "ERT"); EXPECT_EQ(page.projects[0].crsCode, "EPSG:4547"); EXPECT_EQ(page.projects[0].status, 1); } TEST(NavDto, ParseStructNodesMapsParentAndType) { const auto arr = arrOf(R"([ {"id":"gs1","name":"工区1","parentId":"","type":1,"typeName":"GS","confCode":""}, {"id":"tm1","name":"测线1","parentId":"gs1","type":2,"typeName":"TM","confCode":"ERT"} ])"); const auto ns = dto::parseStructNodes(arr); ASSERT_EQ(ns.size(), 2u); EXPECT_EQ(ns[0].id, "gs1"); EXPECT_EQ(ns[1].parentId, "gs1"); EXPECT_EQ(ns[1].confCode, "ERT"); EXPECT_EQ(ns[1].type, 2); } TEST(NavDto, ParseDatasetsMapsDdCodeToDdType) { const auto arr = arrOf(R"([ {"id":"ds1","name":"批次1","ddCode":"dd_section","typeName":"剖面"} ])"); const auto ds = dto::parseDatasets(arr); ASSERT_EQ(ds.size(), 1u); EXPECT_EQ(ds[0].id, "ds1"); EXPECT_EQ(ds[0].name, "批次1"); EXPECT_EQ(ds[0].ddType, "dd_section"); } TEST(NavDto, BuildStructTreeNestsGsTmAndDirectTm) { const std::vector flat = { {"gs1", "工区1", "", "GS", "", 1}, {"tm1", "测线1", "gs1", "TM", "", 2}, {"tm2", "测线2", "gs1", "TM", "", 2}, {"tmD", "直挂测线", "", "TM", "", 2}, // TM 直挂项目(无 GS) }; const auto roots = dto::buildStructTree(flat); ASSERT_EQ(roots.size(), 2u); // gs1 + tmD EXPECT_EQ(roots[0].node.id, "gs1"); EXPECT_FALSE(roots[0].isTm); // 非叶 = GS ASSERT_EQ(roots[0].children.size(), 2u); EXPECT_EQ(roots[0].children[0].node.id, "tm1"); EXPECT_TRUE(roots[0].children[0].isTm); // 叶 = TM EXPECT_EQ(roots[1].node.id, "tmD"); EXPECT_TRUE(roots[1].isTm); // 直挂项目的叶子 = TM } TEST(NavDto, BuildStructTreeOrphanParentBecomesRoot) { const std::vector flat = { {"tmX", "孤儿测线", "ghost", "TM", "", 2}, // parentId 不在集合内 }; const auto roots = dto::buildStructTree(flat); ASSERT_EQ(roots.size(), 1u); EXPECT_EQ(roots[0].node.id, "tmX"); EXPECT_TRUE(roots[0].isTm); } TEST(NavDto, BuildStructTreeEmpty) { EXPECT_TRUE(dto::buildStructTree({}).empty()); } TEST(NavDto, BuildStructTreeHandlesCycleWithoutInfiniteRecursion) { // 不可信数据:重复 id 形成可达环(R→X→Y→重复X…)。必须终止、不崩。 const std::vector flat = { {"R", "根", "", "GS", "", 1}, {"X", "x", "R", "GS", "", 1}, {"Y", "y", "X", "GS", "", 1}, {"X", "x2", "Y", "TM", "", 2}, // 重复 id X,父=Y → 若不防环将无限递归 }; const auto roots = dto::buildStructTree(flat); // 不挂起即通过 ASSERT_EQ(roots.size(), 1u); EXPECT_EQ(roots[0].node.id, "R"); } TEST(NavDto, ParseProjectsEmptyAndMissingListGraceful) { EXPECT_TRUE(dto::parseProjects(objOf(R"({})")).projects.empty()); EXPECT_FALSE(dto::parseProjects(objOf(R"({"hasNextPage":false})")).hasNextPage); const auto p = dto::parseProjects(objOf(R"({"projectList":[]})")); EXPECT_TRUE(p.projects.empty()); }