402 lines
17 KiB
C++
402 lines
17 KiB
C++
#include <gtest/gtest.h>
|
||
#include <QByteArray>
|
||
#include <QJsonArray>
|
||
#include <QJsonDocument>
|
||
#include <QJsonObject>
|
||
|
||
#include <vector>
|
||
|
||
#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, BuildStructTreeNestsGsTmAndDirectTm) {
|
||
const std::vector<StructNode> 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<StructNode> 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<StructNode> 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());
|
||
}
|
||
|
||
TEST(NavDto, ParseProjectListArrayMapsItem) {
|
||
const auto arr = arrOf(R"([
|
||
{"id":"p1","projectName":"演示","projectTypeName":"ERT","referenceCRSCode":"EPSG:4547","status":1}
|
||
])");
|
||
const auto v = dto::parseProjectList(arr);
|
||
ASSERT_EQ(v.size(), 1u);
|
||
EXPECT_EQ(v[0].id, "p1");
|
||
EXPECT_EQ(v[0].name, "演示");
|
||
EXPECT_EQ(v[0].crsCode, "EPSG:4547");
|
||
}
|
||
|
||
TEST(NavDto, BuildStructTreeDropsDsAndTmStaysLeaf) {
|
||
// 真实形态:项目(1) → TM(2) → DS(3)。DS 不进树;带 DS 子节点的 TM 仍是 TM 叶子。
|
||
// 字段序:id,name,parentId,typeName,confCode,typeId,type(typeId 为新增,测试填空串)。
|
||
const std::vector<StructNode> flat = {
|
||
{"P", "项目", "0", "PRJ", "", "", 1},
|
||
{"T1", "ERT1", "P", "ERT", "ERT", "", 2},
|
||
{"D1", "批次1","T1", "", "", "", 3}, // DS:应被过滤
|
||
{"T2", "ERT2", "P", "ERT", "ERT", "", 2},
|
||
};
|
||
const auto roots = dto::buildStructTree(flat);
|
||
ASSERT_EQ(roots.size(), 1u); // 仅项目根(parentId "0")
|
||
EXPECT_EQ(roots[0].node.id, "P");
|
||
EXPECT_FALSE(roots[0].isTm); // 项目根 type1
|
||
ASSERT_EQ(roots[0].children.size(), 2u); // T1、T2(D1 被过滤)
|
||
EXPECT_EQ(roots[0].children[0].node.id, "T1");
|
||
EXPECT_TRUE(roots[0].children[0].isTm); // TM type2
|
||
EXPECT_TRUE(roots[0].children[0].children.empty()); // DS 不进树
|
||
}
|
||
|
||
TEST(NavDto, ParseDsRowsDataAndFile) {
|
||
const auto d = dto::parseDsRows(arrOf(R"([
|
||
{"id":"d1","dsName":"ERT1-WS","name":"电阻率数据","ddCode":"dd_inversion_data","createTime":"2026-03-25 16:48:57"}
|
||
])"));
|
||
ASSERT_EQ(d.size(), 1u);
|
||
EXPECT_EQ(d[0].id, "d1");
|
||
EXPECT_EQ(d[0].dsName, "ERT1-WS");
|
||
EXPECT_EQ(d[0].typeName, "电阻率数据");
|
||
EXPECT_EQ(d[0].createTime, "2026-03-25 16:48:57");
|
||
EXPECT_TRUE(d[0].fileName.empty());
|
||
|
||
const auto f = dto::parseDsRows(arrOf(R"([
|
||
{"id":"f1","dsName":"ERT1-WS.xlsx","name":"","ddCode":"dd_file",
|
||
"file":{"name":"ERT1-WS.xlsx","size":62760,"url":"/common/file/x.xlsx"}}
|
||
])"));
|
||
ASSERT_EQ(f.size(), 1u);
|
||
EXPECT_EQ(f[0].fileName, "ERT1-WS.xlsx");
|
||
EXPECT_EQ(f[0].fileSize, 62760);
|
||
EXPECT_EQ(f[0].fileUrl, "/common/file/x.xlsx");
|
||
|
||
const auto page = dto::parseDsPage(objOf(R"({
|
||
"total": 18,
|
||
"list": [{"id":"x","dsName":"a","name":"t","ddCode":"dd","createTime":"2026-01-01 00:00:00"}]
|
||
})"));
|
||
EXPECT_EQ(page.total, 18);
|
||
ASSERT_EQ(page.rows.size(), 1u);
|
||
EXPECT_EQ(page.rows[0].dsName, "a");
|
||
}
|
||
|
||
// 数据集树父节点:sourceShowParentId 优先(=显示树父),缺失回退 parentId,皆无则空(=树根)。
|
||
TEST(NavDto, ParseDsRowsParentIdForTree) {
|
||
const auto d = dto::parseDsRows(arrOf(R"([
|
||
{"id":"raw","dsName":"E3原始","name":"ERT原始数据","ddCode":"dd_ert_measurement_data",
|
||
"parentId":"srcFile","sourceShowParentId":"srcFile"},
|
||
{"id":"inv","dsName":"E3反演","name":"电阻率数据","ddCode":"dd_inversion_data",
|
||
"parentId":"raw","sourceShowParentId":"raw"},
|
||
{"id":"fallback","dsName":"仅parentId","name":"t","ddCode":"dd",
|
||
"parentId":"raw"},
|
||
{"id":"root","dsName":"无父","name":"t","ddCode":"dd"}
|
||
])"));
|
||
ASSERT_EQ(d.size(), 4u);
|
||
EXPECT_EQ(d[0].parentId, "srcFile"); // 原始数据→源文件节点(不在本批→树根)
|
||
EXPECT_EQ(d[1].parentId, "raw"); // 派生反演→挂原始数据下
|
||
EXPECT_EQ(d[2].parentId, "raw"); // 无 sourceShowParentId → 回退 parentId
|
||
EXPECT_TRUE(d[3].parentId.empty()); // 二者皆无 → 空(树根)
|
||
}
|
||
|
||
// 大类分类主键 dsTypeCode、层级 structParent*、原始属性 properties[] 的解析。
|
||
TEST(NavDto, ParseDsRowsExtractsTypeCodeAndProperties) {
|
||
const auto d = dto::parseDsRows(arrOf(R"([
|
||
{"id":"d1","dsName":"ERT1-WS","name":"电阻率数据",
|
||
"ddCode":"dd_inversion_data","dsTypeCode":"ERT platform inversion data",
|
||
"createTime":"2026-03-25 16:48:57","structParentId":"tm1","structParentConfType":2,
|
||
"properties":[
|
||
{"confFieldId":"1450495001706500","value":"1429468249448449"},
|
||
{"confFieldId":"1455083478786048","value":"2026-03-25 16:48:57"}
|
||
]}
|
||
])"));
|
||
ASSERT_EQ(d.size(), 1u);
|
||
EXPECT_EQ(d[0].dsTypeCode, "ERT platform inversion data");
|
||
EXPECT_EQ(d[0].structParentId, "tm1");
|
||
EXPECT_EQ(d[0].structParentConfType, 2);
|
||
EXPECT_EQ(d[0].ddCode, "dd_inversion_data");
|
||
ASSERT_EQ(d[0].properties.size(), 2u);
|
||
EXPECT_EQ(d[0].properties[0].confFieldId, "1450495001706500");
|
||
EXPECT_EQ(d[0].properties[0].value, "1429468249448449");
|
||
// 日期型 value 经 toVariant().toString() 原样保留(JSON 中本就是字符串)。
|
||
EXPECT_EQ(d[0].properties[1].confFieldId, "1455083478786048");
|
||
EXPECT_EQ(d[0].properties[1].value, "2026-03-25 16:48:57");
|
||
}
|
||
|
||
TEST(NavDto, ParseProjectItemFullFields) {
|
||
const auto v = dto::parseProjectList(arrOf(R"([
|
||
{"id":"p1","projectName":"演示","projectCode":"001","status":2,
|
||
"projectTypeId":"t1","projectTypeName":"全量类型",
|
||
"ownerCompanyName":"华南所","responsiblePersonName":"张三","createTime":"2026-01-01 00:00:00"}
|
||
])"));
|
||
ASSERT_EQ(v.size(), 1u);
|
||
EXPECT_EQ(v[0].code, "001");
|
||
EXPECT_EQ(v[0].status, 2);
|
||
EXPECT_EQ(v[0].projectTypeId, "t1");
|
||
EXPECT_EQ(v[0].typeName, "全量类型");
|
||
EXPECT_EQ(v[0].ownerCompany, "华南所");
|
||
EXPECT_EQ(v[0].responsiblePerson, "张三");
|
||
EXPECT_EQ(v[0].createTime, "2026-01-01 00:00:00");
|
||
}
|
||
|
||
TEST(NavDto, ParseProjectPageAndTypes) {
|
||
const auto page =
|
||
dto::parseProjectPage(objOf(R"({"total":20,"list":[{"id":"p1","projectName":"a"}]})"));
|
||
EXPECT_EQ(page.total, 20);
|
||
ASSERT_EQ(page.rows.size(), 1u);
|
||
EXPECT_EQ(page.rows[0].name, "a");
|
||
const auto types = dto::parseProjectTypes(arrOf(R"([{"id":"t1","name":"全量类型"}])"));
|
||
ASSERT_EQ(types.size(), 1u);
|
||
EXPECT_EQ(types[0].id, "t1");
|
||
EXPECT_EQ(types[0].name, "全量类型");
|
||
}
|
||
|
||
TEST(NavDto, ParseDynamicFormMergesFieldsValuesAndSorts) {
|
||
const auto data = objOf(R"({
|
||
"name": "测线1",
|
||
"properties": { "depth": "120", "len": "300", "owner": "张三" },
|
||
"formList": [
|
||
{ "groupName": "几何", "groupSort": 1, "values": [
|
||
{ "fieldName": "长度", "fieldCode": "len", "displaySort": 2 },
|
||
{ "fieldName": "深度", "fieldCode": "depth", "displaySort": 1 }
|
||
]},
|
||
{ "groupName": "归属", "groupSort": 2, "values": [
|
||
{ "fieldName": "负责人", "fieldCode": "owner", "displaySort": 1 },
|
||
{ "fieldName": "缺失项", "fieldCode": "nope", "displaySort": 2 }
|
||
]}
|
||
]
|
||
})");
|
||
const auto form = dto::parseDynamicForm(data);
|
||
EXPECT_EQ(form.name, "测线1");
|
||
ASSERT_EQ(form.groups.size(), 2u);
|
||
EXPECT_EQ(form.groups[0].name, "几何");
|
||
ASSERT_EQ(form.groups[0].fields.size(), 2u);
|
||
EXPECT_EQ(form.groups[0].fields[0].name, "深度");
|
||
EXPECT_EQ(form.groups[0].fields[0].value, "120");
|
||
EXPECT_EQ(form.groups[0].fields[1].name, "长度");
|
||
EXPECT_EQ(form.groups[0].fields[1].value, "300");
|
||
EXPECT_EQ(form.groups[1].fields[1].value, "");
|
||
}
|
||
|
||
TEST(NavDto, ParseDynamicFormEmptyFormListYieldsNoGroups) {
|
||
const auto data = objOf(R"({ "name":"空", "properties":{}, "formList":[] })");
|
||
const auto form = dto::parseDynamicForm(data);
|
||
EXPECT_EQ(form.name, "空");
|
||
EXPECT_TRUE(form.groups.empty());
|
||
}
|
||
|
||
TEST(NavDto, ParseExceptionsMapsFieldsAndSummary) {
|
||
const auto arr = arrOf(R"([
|
||
{ "id":"e1", "exceptionName":"空洞A", "exceptionTypeName":"空洞",
|
||
"exceptionMarkTypeName":"自动", "createTime":"2026-06-01",
|
||
"elevationList":[120.0, 80.0, 100.0], "remark":"复核中",
|
||
"consortiumId":"c1", "consortiumName":"体A", "consortiumType":"溶洞群" },
|
||
{ "id":"e2", "exceptionName":"裂隙B", "exceptionTypeName":"裂隙",
|
||
"exceptionMarkTypeName":"手动", "createTime":"2026-06-02",
|
||
"elevationList":[], "remark":"" }
|
||
])");
|
||
const auto rows = dto::parseExceptions(arr);
|
||
ASSERT_EQ(rows.size(), 2u);
|
||
EXPECT_EQ(rows[0].id, "e1");
|
||
EXPECT_EQ(rows[0].name, "空洞A");
|
||
EXPECT_EQ(rows[0].typeName, "空洞");
|
||
EXPECT_EQ(rows[0].consortiumId, "c1");
|
||
EXPECT_EQ(rows[0].consortiumName, "体A");
|
||
EXPECT_EQ(rows[0].consortiumType, "溶洞群");
|
||
EXPECT_NE(rows[0].detailSummary.find("自动"), std::string::npos);
|
||
EXPECT_NE(rows[0].detailSummary.find("2026-06-01"), std::string::npos);
|
||
EXPECT_NE(rows[0].detailSummary.find("80"), std::string::npos);
|
||
EXPECT_NE(rows[0].detailSummary.find("120"), std::string::npos);
|
||
EXPECT_NE(rows[0].detailSummary.find("复核中"), std::string::npos);
|
||
EXPECT_TRUE(rows[1].consortiumId.empty());
|
||
EXPECT_NE(rows[1].detailSummary.find("手动"), std::string::npos);
|
||
}
|
||
|
||
TEST(NavDto, GroupExceptionsByConsortiumSplitsLooseAndGroups) {
|
||
std::vector<ExceptionRow> rows = {
|
||
{ "e1","空洞A","空洞","t1","c1","体A","溶洞群","" },
|
||
{ "e2","空洞B","空洞","t1","c1","","","" },
|
||
{ "e3","裂隙X","裂隙","t1","","","","" },
|
||
{ "e4","空洞C","空洞","t1","c2","体B","溶洞群","" },
|
||
};
|
||
const auto g = dto::groupExceptionsByConsortium(rows);
|
||
ASSERT_EQ(g.consortia.size(), 2u);
|
||
EXPECT_EQ(g.consortia[0].id, "c1");
|
||
EXPECT_EQ(g.consortia[0].name, "体A");
|
||
EXPECT_EQ(g.consortia[0].typeName, "溶洞群");
|
||
ASSERT_EQ(g.consortia[0].exceptions.size(), 2u);
|
||
EXPECT_EQ(g.consortia[1].id, "c2");
|
||
ASSERT_EQ(g.loose.size(), 1u);
|
||
EXPECT_EQ(g.loose[0].id, "e3");
|
||
}
|
||
|
||
TEST(NavDto, GroupExceptionsAllLooseWhenNoConsortium) {
|
||
std::vector<ExceptionRow> rows = {
|
||
{ "e1","a","t","t1","","","","" }, { "e2","b","t","t1","","","","" } };
|
||
const auto g = dto::groupExceptionsByConsortium(rows);
|
||
EXPECT_TRUE(g.consortia.empty());
|
||
EXPECT_EQ(g.loose.size(), 2u);
|
||
}
|
||
|
||
TEST(NavDto, ParseGsTypesMapsNameAndId) {
|
||
const auto arr = arrOf(R"([
|
||
{"name":"测区","gsTypeId":"gt1"},
|
||
{"name":"测点","id":"gt2"}
|
||
])");
|
||
const auto types = dto::parseGsTypes(arr);
|
||
ASSERT_EQ(types.size(), 2u);
|
||
EXPECT_EQ(types[0].name, "测区");
|
||
EXPECT_EQ(types[0].gsTypeId, "gt1");
|
||
EXPECT_EQ(types[1].gsTypeId, "gt2"); // 回退 id
|
||
}
|
||
|
||
TEST(NavDto, ParseDsImportTypesKeepsOnlyCanImport) {
|
||
const auto arr = arrOf(R"([
|
||
{"dsTypeId":"d1","nameChn":"电阻率","canImport":true},
|
||
{"dsTypeId":"d2","nameChn":"轨迹","canImport":false}
|
||
])");
|
||
const auto t = dto::parseDsImportTypes(arr);
|
||
ASSERT_EQ(t.size(), 1u);
|
||
EXPECT_EQ(t[0].dsTypeId, "d1");
|
||
EXPECT_EQ(t[0].name, "电阻率");
|
||
EXPECT_TRUE(t[0].canImport);
|
||
}
|
||
|
||
TEST(NavDto, ParseEditableFormPreservesCompAndRequired) {
|
||
const auto data = QJsonDocument::fromJson(QByteArray(R"({
|
||
"typeId":"tt1","name":"测区",
|
||
"formList":[{"groupName":"基本","groupSort":0,"values":[
|
||
{"fieldCode":"topography","fieldName":"地形","displayComponentType":8,"requiredType":2,"displaySort":1},
|
||
{"fieldCode":"device","fieldName":"设备","displayComponentType":4,"requiredType":1,"displaySort":0,
|
||
"optionsObject":[{"label":"A","value":"a"}]}
|
||
]}],
|
||
"properties":{"topography":"山地"}
|
||
})")).object();
|
||
const auto f = dto::parseEditableForm(data, 1);
|
||
EXPECT_EQ(f.confType, 1);
|
||
ASSERT_EQ(f.groups.size(), 1u);
|
||
ASSERT_EQ(f.groups[0].fields.size(), 2u);
|
||
// 已按 displaySort 排序:device(sort0) 在前。
|
||
EXPECT_EQ(f.groups[0].fields[0].code, "device");
|
||
EXPECT_EQ(f.groups[0].fields[0].comp, 4);
|
||
EXPECT_EQ(f.groups[0].fields[0].required, 1);
|
||
ASSERT_EQ(f.groups[0].fields[0].options.size(), 1u);
|
||
EXPECT_EQ(f.groups[0].fields[0].options[0].value, "a");
|
||
// topography:comp8 只读、有 properties 预填。
|
||
EXPECT_EQ(f.groups[0].fields[1].comp, 8);
|
||
EXPECT_EQ(f.groups[0].fields[1].required, 2);
|
||
EXPECT_EQ(f.groups[0].fields[1].value, "山地");
|
||
EXPECT_TRUE(f.groups[0].fields[1].fromProps);
|
||
}
|
||
|
||
TEST(NavDto, ParseEditableFormDefaultsRequiredTypeToOptional) {
|
||
// 缺省 requiredType → required==0(语义:可选可编辑,非必填亦非只读)。
|
||
const auto data = QJsonDocument::fromJson(QByteArray(R"({
|
||
"typeId":"tt1","name":"测区",
|
||
"formList":[{"groupName":"基本","groupSort":0,"values":[
|
||
{"fieldCode":"note","fieldName":"备注","displayComponentType":1,"displaySort":0}
|
||
]}],
|
||
"properties":{}
|
||
})")).object();
|
||
const auto f = dto::parseEditableForm(data, 1);
|
||
ASSERT_EQ(f.groups.size(), 1u);
|
||
ASSERT_EQ(f.groups[0].fields.size(), 1u);
|
||
EXPECT_EQ(f.groups[0].fields[0].required, 0);
|
||
}
|