feat(cpp-object-oriented-modular-refactoring): step 3 - foundation-google-style

This commit is contained in:
KOKO\Mimi
2026-08-16 04:26:14 +09:00
parent 2628ed3488
commit 042edadffb
93 changed files with 3144 additions and 3175 deletions
+161 -161
View File
@@ -45,10 +45,10 @@ fesa::Result<fesa::Domain> mapText(
const std::string& content) {
const TemporaryInputFile input{stem, content};
auto parsed = fesa::AbaqusInputReader{}.read(input.path());
if (!parsed.hasValue()) {
return fesa::Result<fesa::Domain>::failure(parsed.status());
if (!parsed.HasValue()) {
return fesa::Result<fesa::Domain>::Failure(parsed.GetStatus());
}
return fesa::AbaqusDomainMapper{}.map(parsed.value());
return fesa::AbaqusDomainMapper{}.map(parsed.Value());
}
std::string readExactBytes(const std::filesystem::path& path) {
@@ -73,12 +73,12 @@ const fesa::Diagnostic* findDiagnostic(
const fesa::Status& status,
const std::string& code) {
const auto found = std::find_if(
status.diagnostics().begin(),
status.diagnostics().end(),
status.Diagnostics().begin(),
status.Diagnostics().end(),
[&code](const fesa::Diagnostic& diagnostic) {
return diagnostic.code == code;
});
return found == status.diagnostics().end() ? nullptr : &*found;
return found == status.Diagnostics().end() ? nullptr : &*found;
}
std::string replaceOnce(
@@ -246,18 +246,18 @@ RootAssembly, 6, -12.5
TEST(InpDomainMapping, MapsEverySupportedKeywordAndLegacyDeck) {
auto result = mapText("supported-inventory", supportedInventoryDeck(true));
ASSERT_TRUE(result.hasValue());
const fesa::Domain& domain = result.value();
ASSERT_TRUE(result.HasValue());
const fesa::Domain& domain = result.Value();
ASSERT_EQ(domain.nodes().size(), 2U);
EXPECT_EQ(domain.nodes()[0].sourceId.instanceName, "Beam-1");
EXPECT_EQ(domain.nodes()[0].sourceId.sourceLabel, 1);
EXPECT_EQ(domain.nodes()[0].sourceId.sourceLabelText, "0001");
EXPECT_EQ(domain.nodes()[1].sourceId.sourceLabelText, "0002");
EXPECT_EQ(domain.nodes()[0].sourceId.instance_name, "Beam-1");
EXPECT_EQ(domain.nodes()[0].sourceId.source_label, 1);
EXPECT_EQ(domain.nodes()[0].sourceId.source_label_text, "0001");
EXPECT_EQ(domain.nodes()[1].sourceId.source_label_text, "0002");
EXPECT_DOUBLE_EQ(domain.nodes()[1].coordinates[0], 2.0);
ASSERT_EQ(domain.elements().size(), 1U);
EXPECT_EQ(domain.elements()[0].sourceId.sourceLabelText, "0007");
EXPECT_EQ(domain.elements()[0].sourceId.source_label_text, "0007");
EXPECT_EQ(domain.elements()[0].nodeIndices[0], 0U);
EXPECT_EQ(domain.elements()[0].nodeIndices[1], 1U);
@@ -304,15 +304,15 @@ TEST(InpDomainMapping, MapsEverySupportedKeywordAndLegacyDeck) {
const auto bytesBefore = readExactBytes(legacyPath);
const auto timestampBefore = std::filesystem::last_write_time(legacyPath);
auto parsedLegacy = fesa::AbaqusInputReader{}.read(legacyPath);
ASSERT_TRUE(parsedLegacy.hasValue());
auto legacy = fesa::AbaqusDomainMapper{}.map(parsedLegacy.value());
ASSERT_TRUE(legacy.hasValue());
EXPECT_EQ(legacy.value().nodes().size(), 11U);
EXPECT_EQ(legacy.value().elements().size(), 10U);
EXPECT_EQ(legacy.value().materials().size(), 1U);
EXPECT_EQ(legacy.value().sections().size(), 1U);
EXPECT_EQ(legacy.value().steps().size(), 1U);
EXPECT_EQ(legacy.value().warnings().size(), 7U);
ASSERT_TRUE(parsedLegacy.HasValue());
auto legacy = fesa::AbaqusDomainMapper{}.map(parsedLegacy.Value());
ASSERT_TRUE(legacy.HasValue());
EXPECT_EQ(legacy.Value().nodes().size(), 11U);
EXPECT_EQ(legacy.Value().elements().size(), 10U);
EXPECT_EQ(legacy.Value().materials().size(), 1U);
EXPECT_EQ(legacy.Value().sections().size(), 1U);
EXPECT_EQ(legacy.Value().steps().size(), 1U);
EXPECT_EQ(legacy.Value().warnings().size(), 7U);
EXPECT_EQ(readExactBytes(legacyPath), bytesBefore);
EXPECT_EQ(std::filesystem::last_write_time(legacyPath), timestampBefore);
}
@@ -356,24 +356,24 @@ OnlySecond, 2, 5.
)inp";
auto result = mapText("multiple-instances", deck);
ASSERT_TRUE(result.hasValue());
const fesa::Domain& domain = result.value();
ASSERT_TRUE(result.HasValue());
const fesa::Domain& domain = result.Value();
ASSERT_EQ(domain.nodes().size(), 4U);
EXPECT_EQ(domain.nodes()[0].sourceId.instanceName, "First");
EXPECT_EQ(domain.nodes()[0].sourceId.sourceLabel, 10);
EXPECT_EQ(domain.nodes()[1].sourceId.instanceName, "First");
EXPECT_EQ(domain.nodes()[1].sourceId.sourceLabel, 20);
EXPECT_EQ(domain.nodes()[2].sourceId.instanceName, "Second");
EXPECT_EQ(domain.nodes()[2].sourceId.sourceLabel, 10);
EXPECT_EQ(domain.nodes()[3].sourceId.instanceName, "Second");
EXPECT_EQ(domain.nodes()[3].sourceId.sourceLabel, 20);
EXPECT_EQ(domain.nodes()[0].sourceId.instance_name, "First");
EXPECT_EQ(domain.nodes()[0].sourceId.source_label, 10);
EXPECT_EQ(domain.nodes()[1].sourceId.instance_name, "First");
EXPECT_EQ(domain.nodes()[1].sourceId.source_label, 20);
EXPECT_EQ(domain.nodes()[2].sourceId.instance_name, "Second");
EXPECT_EQ(domain.nodes()[2].sourceId.source_label, 10);
EXPECT_EQ(domain.nodes()[3].sourceId.instance_name, "Second");
EXPECT_EQ(domain.nodes()[3].sourceId.source_label, 20);
ASSERT_EQ(domain.elements().size(), 2U);
EXPECT_EQ(domain.elements()[0].sourceId.instanceName, "First");
EXPECT_EQ(domain.elements()[0].sourceId.instance_name, "First");
EXPECT_EQ(domain.elements()[0].nodeIndices,
(std::array<fesa::EntityIndex, 2>{0U, 1U}));
EXPECT_EQ(domain.elements()[1].sourceId.instanceName, "Second");
EXPECT_EQ(domain.elements()[1].sourceId.instance_name, "Second");
EXPECT_EQ(domain.elements()[1].nodeIndices,
(std::array<fesa::EntityIndex, 2>{2U, 3U}));
@@ -412,9 +412,9 @@ OnlySecond, 2, 5.
replaceOnce(minimalDeck(), "Root, 1, 6", "1, 1, 6"),
"Tip, 2, -1.",
"2, 2, -1."));
ASSERT_TRUE(direct.hasValue());
EXPECT_EQ(direct.value().steps()[0].boundaries[0].target, "1");
EXPECT_EQ(direct.value().steps()[0].loads[0].target, "2");
ASSERT_TRUE(direct.HasValue());
EXPECT_EQ(direct.Value().steps()[0].boundaries[0].target, "1");
EXPECT_EQ(direct.Value().steps()[0].loads[0].target, "2");
auto aboveThresholds = mapText(
"above-geometry-thresholds",
@@ -422,7 +422,7 @@ OnlySecond, 2, 5.
replaceOnce(minimalDeck(), "2, 1., 0., 0.", "2, 2e-12, 0., 0."),
"0., 1., 0.",
"1., 2e-12, 0."));
ASSERT_TRUE(aboveThresholds.hasValue());
ASSERT_TRUE(aboveThresholds.HasValue());
auto largeFinite = mapText(
"large-finite-geometry",
@@ -433,7 +433,7 @@ OnlySecond, 2, 5.
"2, 1e308, 1e297, 0."),
"0., 1., 0.",
"1e308, 0., 0."));
ASSERT_TRUE(largeFinite.hasValue());
ASSERT_TRUE(largeFinite.HasValue());
}
TEST(InpDomainMapping, KeepsNodeAndElementSetNamesInSeparateNamespaces) {
@@ -444,8 +444,8 @@ TEST(InpDomainMapping, KeepsNodeAndElementSetNamesInSeparateNamespaces) {
"*Elset, elset=ShellS4\n10",
"*Nset, nset=ShellS4\n1, 2, 3, 4\n*Elset, elset=ShellS4\n10"));
ASSERT_TRUE(sharedName.hasValue());
const auto& domain = sharedName.value();
ASSERT_TRUE(sharedName.HasValue());
const auto& domain = sharedName.Value();
EXPECT_TRUE(std::any_of(
domain.nodeSets().begin(), domain.nodeSets().end(),
[](const fesa::NodeSet& set) { return set.name == "ShellS4"; }));
@@ -460,8 +460,8 @@ TEST(InpDomainMapping, KeepsNodeAndElementSetNamesInSeparateNamespaces) {
"*Elset, elset=ShellS4\n10",
"*Nset, nset=Shared\n1\n*Nset, nset=Shared\n2\n"
"*Elset, elset=ShellS4\n10"));
ASSERT_FALSE(duplicateNodeSet.hasValue());
EXPECT_NE(findDiagnostic(duplicateNodeSet.status(), "duplicate-entity"), nullptr);
ASSERT_FALSE(duplicateNodeSet.HasValue());
EXPECT_NE(findDiagnostic(duplicateNodeSet.GetStatus(), "duplicate-entity"), nullptr);
auto duplicateElementSet = mapText(
"duplicate-part-element-set",
@@ -470,8 +470,8 @@ TEST(InpDomainMapping, KeepsNodeAndElementSetNamesInSeparateNamespaces) {
"*Elset, elset=ShellS4\n10",
"*Elset, elset=Repeated\n10\n*Elset, elset=Repeated\n20\n"
"*Elset, elset=ShellS4\n10"));
ASSERT_FALSE(duplicateElementSet.hasValue());
EXPECT_NE(findDiagnostic(duplicateElementSet.status(), "duplicate-entity"), nullptr);
ASSERT_FALSE(duplicateElementSet.HasValue());
EXPECT_NE(findDiagnostic(duplicateElementSet.GetStatus(), "duplicate-entity"), nullptr);
auto assemblySharedName = mapText(
"separate-assembly-set-namespaces",
@@ -483,8 +483,8 @@ TEST(InpDomainMapping, KeepsNodeAndElementSetNamesInSeparateNamespaces) {
"*Nset, nset=Root, instance=Beam-1\n1",
"*Nset, nset=Root, instance=Beam-1\n1\n"
"*Elset, elset=Root, instance=Beam-1\n1"));
ASSERT_TRUE(assemblySharedName.hasValue());
const auto& assemblyDomain = assemblySharedName.value();
ASSERT_TRUE(assemblySharedName.HasValue());
const auto& assemblyDomain = assemblySharedName.Value();
const auto rootNodeSetCount = std::count_if(
assemblyDomain.nodeSets().begin(), assemblyDomain.nodeSets().end(),
[](const fesa::NodeSet& set) { return set.name == "Root"; });
@@ -502,48 +502,48 @@ TEST(InpDomainMapping, KeepsNodeAndElementSetNamesInSeparateNamespaces) {
TEST(InpDomainMapping, NoOpAllowlistWarnsWithoutSemanticEffect) {
auto plain = mapText("without-no-ops", supportedInventoryDeck(false));
auto withNoOps = mapText("with-no-ops", supportedInventoryDeck(true));
ASSERT_TRUE(plain.hasValue());
ASSERT_TRUE(withNoOps.hasValue());
ASSERT_TRUE(plain.HasValue());
ASSERT_TRUE(withNoOps.HasValue());
EXPECT_TRUE(plain.value().warnings().empty());
ASSERT_EQ(withNoOps.value().warnings().size(), 8U);
EXPECT_EQ(withNoOps.value().warnings()[0].code, "ignored-input-keyword");
EXPECT_EQ(withNoOps.value().warnings()[0].keyword, "PREPRINT");
EXPECT_EQ(withNoOps.value().warnings()[1].keyword,
EXPECT_TRUE(plain.Value().warnings().empty());
ASSERT_EQ(withNoOps.Value().warnings().size(), 8U);
EXPECT_EQ(withNoOps.Value().warnings()[0].code, "ignored-input-keyword");
EXPECT_EQ(withNoOps.Value().warnings()[0].keyword, "PREPRINT");
EXPECT_EQ(withNoOps.Value().warnings()[1].keyword,
"TRANSVERSE SHEAR STIFFNESS");
EXPECT_EQ(withNoOps.value().warnings()[2].keyword, "RESTART");
EXPECT_EQ(withNoOps.value().warnings()[3].keyword, "OUTPUT");
EXPECT_EQ(withNoOps.value().warnings()[4].keyword, "NODE OUTPUT");
EXPECT_EQ(withNoOps.value().warnings()[5].keyword, "ELEMENT OUTPUT");
EXPECT_EQ(withNoOps.value().warnings()[6].keyword, "CONTACT OUTPUT");
EXPECT_EQ(withNoOps.value().warnings()[7].keyword, "OUTPUT");
for (const auto& warning : withNoOps.value().warnings()) {
EXPECT_EQ(warning.severity, fesa::Severity::warning);
EXPECT_EQ(withNoOps.Value().warnings()[2].keyword, "RESTART");
EXPECT_EQ(withNoOps.Value().warnings()[3].keyword, "OUTPUT");
EXPECT_EQ(withNoOps.Value().warnings()[4].keyword, "NODE OUTPUT");
EXPECT_EQ(withNoOps.Value().warnings()[5].keyword, "ELEMENT OUTPUT");
EXPECT_EQ(withNoOps.Value().warnings()[6].keyword, "CONTACT OUTPUT");
EXPECT_EQ(withNoOps.Value().warnings()[7].keyword, "OUTPUT");
for (const auto& warning : withNoOps.Value().warnings()) {
EXPECT_EQ(warning.severity, fesa::Severity::kWarning);
}
EXPECT_EQ(withNoOps.value().nodes().size(), plain.value().nodes().size());
EXPECT_EQ(withNoOps.value().elements().size(), plain.value().elements().size());
EXPECT_EQ(withNoOps.value().materials().size(), plain.value().materials().size());
EXPECT_EQ(withNoOps.value().sections().size(), plain.value().sections().size());
EXPECT_EQ(withNoOps.value().nodeSets().size(), plain.value().nodeSets().size());
EXPECT_EQ(withNoOps.value().elementSets().size(), plain.value().elementSets().size());
EXPECT_EQ(withNoOps.value().steps().size(), plain.value().steps().size());
EXPECT_EQ(withNoOps.value().steps()[0].boundaries.size(),
plain.value().steps()[0].boundaries.size());
EXPECT_EQ(withNoOps.value().steps()[0].loads.size(),
plain.value().steps()[0].loads.size());
EXPECT_EQ(withNoOps.Value().nodes().size(), plain.Value().nodes().size());
EXPECT_EQ(withNoOps.Value().elements().size(), plain.Value().elements().size());
EXPECT_EQ(withNoOps.Value().materials().size(), plain.Value().materials().size());
EXPECT_EQ(withNoOps.Value().sections().size(), plain.Value().sections().size());
EXPECT_EQ(withNoOps.Value().nodeSets().size(), plain.Value().nodeSets().size());
EXPECT_EQ(withNoOps.Value().elementSets().size(), plain.Value().elementSets().size());
EXPECT_EQ(withNoOps.Value().steps().size(), plain.Value().steps().size());
EXPECT_EQ(withNoOps.Value().steps()[0].boundaries.size(),
plain.Value().steps()[0].boundaries.size());
EXPECT_EQ(withNoOps.Value().steps()[0].loads.size(),
plain.Value().steps()[0].loads.size());
}
// MITC4-MAP-001
TEST(InpDomainMapping, MapsS4AndS4rThroughOneMitc4Identity) {
auto result = mapText("mitc4-map-001", shellDeck());
ASSERT_TRUE(result.hasValue());
const fesa::Domain& domain = result.value();
ASSERT_TRUE(result.HasValue());
const fesa::Domain& domain = result.Value();
EXPECT_TRUE(domain.elements().empty());
ASSERT_EQ(domain.shellElements().size(), 4U);
EXPECT_EQ(domain.shellElements()[0].sourceId.instanceName, "First");
EXPECT_EQ(domain.shellElements()[0].sourceId.sourceLabelText, "0010");
EXPECT_EQ(domain.shellElements()[0].sourceId.instance_name, "First");
EXPECT_EQ(domain.shellElements()[0].sourceId.source_label_text, "0010");
EXPECT_EQ(
domain.shellElements()[0].sourceType,
fesa::ShellSourceElementType::s4);
@@ -553,7 +553,7 @@ TEST(InpDomainMapping, MapsS4AndS4rThroughOneMitc4Identity) {
EXPECT_EQ(domain.shellElements()[0].sectionIndex, 0U);
EXPECT_EQ(domain.shellElements()[0].materialIndex, 0U);
EXPECT_EQ(domain.shellElements()[1].sourceId.instanceName, "First");
EXPECT_EQ(domain.shellElements()[1].sourceId.instance_name, "First");
EXPECT_EQ(
domain.shellElements()[1].sourceType,
fesa::ShellSourceElementType::s4r);
@@ -563,11 +563,11 @@ TEST(InpDomainMapping, MapsS4AndS4rThroughOneMitc4Identity) {
EXPECT_EQ(domain.shellElements()[1].sectionIndex, 1U);
EXPECT_EQ(domain.shellElements()[1].materialIndex, 1U);
EXPECT_EQ(domain.shellElements()[2].sourceId.instanceName, "Second");
EXPECT_EQ(domain.shellElements()[2].sourceId.instance_name, "Second");
EXPECT_EQ(
domain.shellElements()[2].nodeIndices,
(std::array<fesa::EntityIndex, 4>{6U, 7U, 8U, 9U}));
EXPECT_EQ(domain.shellElements()[3].sourceId.instanceName, "Second");
EXPECT_EQ(domain.shellElements()[3].sourceId.instance_name, "Second");
EXPECT_EQ(
fesa::kMitc4InternalFormulation,
std::string_view{"FESA-MITC4"});
@@ -612,34 +612,34 @@ TEST(InpDomainMapping, RejectsInvalidShellAssignmentsAndProperties) {
const std::vector<InvalidCase> cases{
{"unresolved-material",
replaceOnce(base, "material=Steel", "material=Missing"),
"unresolved-shell-section", fesa::FailureCategory::input},
"unresolved-shell-section", fesa::FailureCategory::kInput},
{"unresolved-elset",
replaceOnce(base, "elset=ShellS4, material=Steel",
"elset=Missing, material=Steel"),
"unresolved-shell-section", fesa::FailureCategory::input},
"unresolved-shell-section", fesa::FailureCategory::kInput},
{"missing-assignment",
replaceOnce(
base,
"*Shell Section, elset=ShellS4R, material=Aluminum\n0.2\n",
""),
"invalid-shell-section-assignment", fesa::FailureCategory::input},
"invalid-shell-section-assignment", fesa::FailureCategory::kInput},
{"conflicting-assignment",
replaceOnce(base, "elset=ShellS4R, material=Aluminum",
"elset=ShellS4, material=Aluminum"),
"invalid-shell-section-assignment", fesa::FailureCategory::input},
"invalid-shell-section-assignment", fesa::FailureCategory::kInput},
{"invalid-thickness",
replaceOnce(base, "0.2\n*End Part", "0.\n*End Part"),
"invalid-shell-thickness", fesa::FailureCategory::model},
"invalid-shell-thickness", fesa::FailureCategory::kModel},
{"invalid-material",
replaceOnce(base, "70000., 0.25", "70000., 0.5"),
"invalid-shell-material", fesa::FailureCategory::model}};
"invalid-shell-material", fesa::FailureCategory::kModel}};
for (const auto& testCase : cases) {
SCOPED_TRACE(testCase.name);
auto result = mapText("mitc4-map-002-" + testCase.name, testCase.deck);
ASSERT_FALSE(result.hasValue());
EXPECT_EQ(result.status().failureCategory(), testCase.category);
ASSERT_NE(findDiagnostic(result.status(), testCase.expectedCode), nullptr);
ASSERT_FALSE(result.HasValue());
EXPECT_EQ(result.GetStatus().Category(), testCase.category);
ASSERT_NE(findDiagnostic(result.GetStatus(), testCase.expectedCode), nullptr);
}
}
@@ -674,11 +674,11 @@ TEST(InpDomainMapping, RejectsInvalidShellConnectivityOptionsAndMixedModels) {
for (const auto& testCase : cases) {
SCOPED_TRACE(testCase.name);
auto result = mapText("mitc4-map-003-" + testCase.name, testCase.deck);
ASSERT_FALSE(result.hasValue());
ASSERT_FALSE(result.HasValue());
EXPECT_EQ(
result.status().failureCategory(),
fesa::FailureCategory::input);
ASSERT_NE(findDiagnostic(result.status(), testCase.expectedCode), nullptr);
result.GetStatus().Category(),
fesa::FailureCategory::kInput);
ASSERT_NE(findDiagnostic(result.GetStatus(), testCase.expectedCode), nullptr);
}
}
@@ -689,11 +689,11 @@ TEST(InpDomainMapping, PreservesProcedureLoadAndOutputRequestBoundariesForShells
"*End Step\n",
"*Output, field\n*Node Output\nU, RF\n*Element Output\nS\n*End Step\n");
auto valid = mapText("mitc4-map-004-no-ops", withNoOps);
ASSERT_TRUE(valid.hasValue());
ASSERT_EQ(valid.value().warnings().size(), 3U);
EXPECT_EQ(valid.value().warnings()[0].keyword, "OUTPUT");
EXPECT_EQ(valid.value().warnings()[1].keyword, "NODE OUTPUT");
EXPECT_EQ(valid.value().warnings()[2].keyword, "ELEMENT OUTPUT");
ASSERT_TRUE(valid.HasValue());
ASSERT_EQ(valid.Value().warnings().size(), 3U);
EXPECT_EQ(valid.Value().warnings()[0].keyword, "OUTPUT");
EXPECT_EQ(valid.Value().warnings()[1].keyword, "NODE OUTPUT");
EXPECT_EQ(valid.Value().warnings()[2].keyword, "ELEMENT OUTPUT");
struct InvalidCase {
std::string name;
@@ -720,11 +720,11 @@ TEST(InpDomainMapping, PreservesProcedureLoadAndOutputRequestBoundariesForShells
for (const auto& testCase : cases) {
SCOPED_TRACE(testCase.name);
auto result = mapText("mitc4-map-004-" + testCase.name, testCase.deck);
ASSERT_FALSE(result.hasValue());
ASSERT_FALSE(result.HasValue());
EXPECT_EQ(
result.status().failureCategory(),
fesa::FailureCategory::input);
ASSERT_NE(findDiagnostic(result.status(), testCase.expectedCode), nullptr);
result.GetStatus().Category(),
fesa::FailureCategory::kInput);
ASSERT_NE(findDiagnostic(result.GetStatus(), testCase.expectedCode), nullptr);
}
}
@@ -739,116 +739,116 @@ TEST(InpDomainMapping, RejectsUnsupportedAndInvalidPortfolio) {
const std::string base = minimalDeck();
const std::vector<InvalidCase> cases{
{"b31", replaceOnce(base, "type=B33", "type=B31"),
"unsupported-element-formulation", fesa::FailureCategory::input},
"unsupported-element-formulation", fesa::FailureCategory::kInput},
{"transform", replaceOnce(base, "*End Instance\n", "1., 0., 0.\n*End Instance\n"),
"unsupported-instance-transform", fesa::FailureCategory::input},
"unsupported-instance-transform", fesa::FailureCategory::kInput},
{"nested-assembly", replaceOnce(base, "*End Assembly\n", "*Assembly, name=Nested\n*End Assembly\n*End Assembly\n"),
"unsupported-nested-assembly", fesa::FailureCategory::input},
"unsupported-nested-assembly", fesa::FailureCategory::kInput},
{"multiple-step", base + "*Step\n*Static\n1., 1., 1., 1.\n*End Step\n",
"unsupported-multiple-step", fesa::FailureCategory::input},
"unsupported-multiple-step", fesa::FailureCategory::kInput},
{"late-part", replaceOnce(base, "*End Assembly\n*Material", "*End Assembly\n*Part, name=Late\n*End Part\n*Material"),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"material-before-assembly", replaceOnce(base, "*Assembly, name=Assembly", "*Material, name=Early\n*Elastic\n50., 0.2\n*Assembly, name=Assembly"),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"material-after-model-boundary", replaceOnce(base,
"*Material, name=Steel\n*Elastic\n100., 0.25\n*Boundary\nRoot, 1, 6",
"*Boundary\nRoot, 1, 6\n*Material, name=Steel\n*Elastic\n100., 0.25"),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"keyword-after-step", base + "*Preprint, echo=NO\n",
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"assembly-instance-after-set", replaceOnce(base,
"*Instance, name=Beam-1, part=BeamPart\n*End Instance\n*Nset, nset=Root, instance=Beam-1\n1",
"*Nset, nset=Root, instance=Beam-1\n1\n*Instance, name=Beam-1, part=BeamPart\n*End Instance"),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"element-before-node", replaceOnce(base,
"*Node\n1, 0., 0., 0.\n2, 1., 0., 0.\n*Element, type=B33\n1, 1, 2",
"*Element, type=B33\n1, 1, 2\n*Node\n1, 0., 0., 0.\n2, 1., 0., 0."),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"shear-before-section-context", replaceOnce(base,
"*Beam General Section",
"*Transverse Shear Stiffness\n1., 2., 3.\n*Beam General Section"),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"incomplete-part", replaceOnce(base,
base.substr(base.find("*Part"), base.find("*End Part") + std::string{"*End Part\n"}.size() - base.find("*Part")),
"*Part, name=BeamPart\n*End Part\n"),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"empty-assembly", replaceOnce(base,
base.substr(base.find("*Assembly"), base.find("*End Assembly") + std::string{"*End Assembly\n"}.size() - base.find("*Assembly")),
"*Assembly, name=Assembly\n*End Assembly\n"),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"cload-before-static", replaceOnce(base,
"*Static\n0.1, 1., 0.01, 1.\n*Cload\nTip, 2, -1.",
"*Cload\nTip, 2, -1.\n*Static\n0.1, 1., 0.01, 1."),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"static-after-boundary", replaceOnce(
replaceOnce(base, "*Boundary\nRoot, 1, 6\n*Step", "*Step"),
"*Static\n0.1, 1., 0.01, 1.",
"*Boundary\nRoot, 1, 6\n*Static\n0.1, 1., 0.01, 1."),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"boundary-after-cload", replaceOnce(
replaceOnce(base, "*Boundary\nRoot, 1, 6\n*Step", "*Step"),
"Tip, 2, -1.\n*End Step",
"Tip, 2, -1.\n*Boundary\nRoot, 1, 6\n*End Step"),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"cload-after-no-op", replaceOnce(base, "*Cload", "*Restart, write, frequency=0\n*Cload"),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"step-without-static", replaceOnce(base,
"*Static\n0.1, 1., 0.01, 1.\n*Cload\nTip, 2, -1.\n*End Step",
"*End Step"),
"invalid-keyword-location", fesa::FailureCategory::input},
"invalid-keyword-location", fesa::FailureCategory::kInput},
{"dependent-instance", replaceOnce(base, "part=BeamPart", "part=BeamPart, dependent=YES"),
"unsupported-instance-mesh-semantics", fesa::FailureCategory::input},
"unsupported-instance-mesh-semantics", fesa::FailureCategory::kInput},
{"coupled-section", replaceOnce(base, "1., 1., 0., 1., 1.", "1., 1., 0.5, 1., 1."),
"unsupported-coupled-section", fesa::FailureCategory::model},
"unsupported-coupled-section", fesa::FailureCategory::kModel},
{"zero-length", replaceOnce(base, "2, 1., 0., 0.", "2, 0., 0., 0."),
"invalid-beam-length", fesa::FailureCategory::model},
"invalid-beam-length", fesa::FailureCategory::kModel},
{"parallel-guide", replaceOnce(base, "0., 1., 0.", "1., 0., 0."),
"invalid-beam-guide-vector", fesa::FailureCategory::model},
"invalid-beam-guide-vector", fesa::FailureCategory::kModel},
{"nonpositive-area", replaceOnce(base, "1., 1., 0., 1., 1.", "0., 1., 0., 1., 1."),
"invalid-beam-property", fesa::FailureCategory::model},
"invalid-beam-property", fesa::FailureCategory::kModel},
{"nonpositive-derived-shear", replaceOnce(base, "100., 0.25", "100., -1.25"),
"invalid-beam-property", fesa::FailureCategory::model},
"invalid-beam-property", fesa::FailureCategory::kModel},
{"nonfinite-elastic", replaceOnce(base, "100., 0.25", "inf, 0.25"),
"invalid-beam-property", fesa::FailureCategory::model},
"invalid-beam-property", fesa::FailureCategory::kModel},
{"nonfinite-section-property", replaceOnce(base, "1., 1., 0., 1., 1.", "nan, 1., 0., 1., 1."),
"invalid-beam-property", fesa::FailureCategory::model},
"invalid-beam-property", fesa::FailureCategory::kModel},
{"nonfinite-guide", replaceOnce(base, "0., 1., 0.", "0., inf, 0."),
"invalid-beam-guide-vector", fesa::FailureCategory::model},
"invalid-beam-guide-vector", fesa::FailureCategory::kModel},
{"length-at-threshold", replaceOnce(base, "2, 1., 0., 0.", "2, 1e-12, 0., 0."),
"invalid-beam-length", fesa::FailureCategory::model},
"invalid-beam-length", fesa::FailureCategory::kModel},
{"guide-at-threshold", replaceOnce(base, "0., 1., 0.", "1., 1e-12, 0."),
"invalid-beam-guide-vector", fesa::FailureCategory::model},
"invalid-beam-guide-vector", fesa::FailureCategory::kModel},
{"duplicate-elastic", replaceOnce(base, "100., 0.25\n*Boundary", "100., 0.25\n*Elastic\n100., 0.25\n*Boundary"),
"duplicate-entity", fesa::FailureCategory::input},
"duplicate-entity", fesa::FailureCategory::kInput},
{"duplicate-node-label", replaceOnce(base, "2, 1., 0., 0.", "1, 1., 0., 0."),
"duplicate-entity", fesa::FailureCategory::input},
"duplicate-entity", fesa::FailureCategory::kInput},
{"dangling-connectivity", replaceOnce(base, "1, 1, 2", "1, 1, 9"),
"unresolved-reference", fesa::FailureCategory::input},
"unresolved-reference", fesa::FailureCategory::kInput},
{"invalid-dof", replaceOnce(base, "Root, 1, 6", "Root, 1, 7"),
"invalid-dof", fesa::FailureCategory::input},
"invalid-dof", fesa::FailureCategory::kInput},
{"nonfinite-coordinate", replaceOnce(base, "1., 0., 0.", "nan, 0., 0."),
"invalid-numeric-value", fesa::FailureCategory::input},
"invalid-numeric-value", fesa::FailureCategory::kInput},
{"malformed-node-arity", replaceOnce(base, "1, 0., 0., 0.", "1, 0., 0."),
"invalid-data-arity", fesa::FailureCategory::input},
"invalid-data-arity", fesa::FailureCategory::kInput},
{"nlgeom", replaceOnce(base, "nlgeom=NO", "nlgeom=YES"),
"unsupported-nonlinear-geometry", fesa::FailureCategory::model},
"unsupported-nonlinear-geometry", fesa::FailureCategory::kModel},
{"unknown-keyword", replaceOnce(base, "*Assembly, name=Assembly", "*Density\n1.\n*Assembly, name=Assembly"),
"unsupported-keyword", fesa::FailureCategory::input},
"unsupported-keyword", fesa::FailureCategory::kInput},
{"invalid-static-arity", replaceOnce(base, "0.1, 1., 0.01, 1.", "0.1, 1., 0.01"),
"invalid-static-data", fesa::FailureCategory::input},
"invalid-static-data", fesa::FailureCategory::kInput},
{"invalid-static-range", replaceOnce(base, "0.1, 1., 0.01, 1.", "0.1, 1., 2., 1."),
"invalid-static-data", fesa::FailureCategory::input},
"invalid-static-data", fesa::FailureCategory::kInput},
{"invalid-generate", replaceOnce(base, "*Elset, elset=BeamSet\n1", "*Elset, elset=BeamSet, generate\n1, 1, 0"),
"invalid-set-range", fesa::FailureCategory::input},
"invalid-set-range", fesa::FailureCategory::kInput},
{"nonlanding-generate", replaceOnce(base, "*Elset, elset=BeamSet\n1", "*Elset, elset=BeamSet, generate\n1, 2, 2"),
"invalid-set-range", fesa::FailureCategory::input},
"invalid-set-range", fesa::FailureCategory::kInput},
{"ambiguous-direct-label", replaceOnce(
replaceOnce(base,
"*End Instance\n*Nset, nset=Root",
"*End Instance\n*Instance, name=Beam-2, part=BeamPart\n*End Instance\n*Nset, nset=Root"),
"Root, 1, 6",
"1, 1, 6"),
"unresolved-reference", fesa::FailureCategory::input},
"unresolved-reference", fesa::FailureCategory::kInput},
{"ambiguous-part-set", replaceOnce(
replaceOnce(
replaceOnce(base,
@@ -858,24 +858,24 @@ TEST(InpDomainMapping, RejectsUnsupportedAndInvalidPortfolio) {
"*End Instance\n*Instance, name=Beam-2, part=BeamPart\n*End Instance\n*Nset, nset=Root"),
"Root, 1, 6",
"Local, 1, 6"),
"unresolved-reference", fesa::FailureCategory::input},
"unresolved-reference", fesa::FailureCategory::kInput},
{"direct-set-conflict", replaceOnce(base,
"*Step, name=Load",
"*Boundary\n1, 1, 1, 2.\n*Step, name=Load"),
"conflicting-boundary-condition", fesa::FailureCategory::input},
"conflicting-boundary-condition", fesa::FailureCategory::kInput},
{"dangling-boundary-target", replaceOnce(base, "Root, 1, 6", "Missing, 1, 6"),
"unresolved-reference", fesa::FailureCategory::input},
"unresolved-reference", fesa::FailureCategory::kInput},
{"conflicting-boundary", replaceOnce(base, "*Step, name=Load", "*Boundary\nRoot, 1, 1, 2.\n*Step, name=Load"),
"conflicting-boundary-condition", fesa::FailureCategory::input}};
"conflicting-boundary-condition", fesa::FailureCategory::kInput}};
for (const auto& testCase : cases) {
SCOPED_TRACE(testCase.name);
auto result = mapText("invalid-" + testCase.name, testCase.deck);
ASSERT_FALSE(result.hasValue());
EXPECT_EQ(result.status().failureCategory(), testCase.category);
const auto* diagnostic = findDiagnostic(result.status(), testCase.expectedCode);
ASSERT_FALSE(result.HasValue());
EXPECT_EQ(result.GetStatus().Category(), testCase.category);
const auto* diagnostic = findDiagnostic(result.GetStatus(), testCase.expectedCode);
ASSERT_NE(diagnostic, nullptr);
EXPECT_EQ(diagnostic->severity, fesa::Severity::error);
EXPECT_EQ(diagnostic->severity, fesa::Severity::kError);
EXPECT_FALSE(diagnostic->location.file.empty());
EXPECT_GT(diagnostic->location.line, 0U);
}
@@ -899,16 +899,16 @@ TEST(InpDomainMapping, RejectsUnsupportedAndInvalidPortfolio) {
for (const auto& testCase : sameTokenCases) {
SCOPED_TRACE("same-token-" + testCase.name);
auto result = mapText("same-token-" + testCase.name, testCase.deck);
ASSERT_FALSE(result.hasValue());
ASSERT_FALSE(result.HasValue());
EXPECT_EQ(
result.status().failureCategory(),
fesa::FailureCategory::input);
result.GetStatus().Category(),
fesa::FailureCategory::kInput);
const auto* diagnostic =
findDiagnostic(result.status(), "unresolved-reference");
findDiagnostic(result.GetStatus(), "unresolved-reference");
ASSERT_NE(diagnostic, nullptr);
EXPECT_EQ(diagnostic->severity, fesa::Severity::error);
EXPECT_EQ(diagnostic->severity, fesa::Severity::kError);
EXPECT_EQ(diagnostic->keyword, testCase.expectedKeyword);
EXPECT_EQ(diagnostic->entityIdentity, "1");
EXPECT_EQ(diagnostic->entity_identity, "1");
EXPECT_EQ(diagnostic->location.line, testCase.expectedLine);
EXPECT_EQ(
diagnostic->location.file.filename().string(),
@@ -923,9 +923,9 @@ TEST(InpDomainMapping, RejectsDloadWithoutDistributedLoadObject) {
"*Dload\nBeamSet, PY, -1.\n");
auto result = mapText("dload", deck);
ASSERT_FALSE(result.hasValue());
EXPECT_EQ(result.status().failureCategory(), fesa::FailureCategory::input);
const auto* diagnostic = findDiagnostic(result.status(), "unsupported-keyword");
ASSERT_FALSE(result.HasValue());
EXPECT_EQ(result.GetStatus().Category(), fesa::FailureCategory::kInput);
const auto* diagnostic = findDiagnostic(result.GetStatus(), "unsupported-keyword");
ASSERT_NE(diagnostic, nullptr);
EXPECT_EQ(diagnostic->keyword, "DLOAD");
}
+27 -27
View File
@@ -63,37 +63,37 @@ TEST(InpSyntax, RejectsMalformedOrOrphanData) {
std::filesystem::remove(missingPath, removeError);
const auto unreadable = fesa::AbaqusInputReader{}.read(missingPath);
ASSERT_FALSE(unreadable.hasValue());
ASSERT_FALSE(unreadable.HasValue());
EXPECT_EQ(
unreadable.status().failureCategory(),
fesa::FailureCategory::input);
ASSERT_EQ(unreadable.status().diagnostics().size(), 1U);
EXPECT_EQ(unreadable.status().diagnostics()[0].code,
unreadable.GetStatus().Category(),
fesa::FailureCategory::kInput);
ASSERT_EQ(unreadable.GetStatus().Diagnostics().size(), 1U);
EXPECT_EQ(unreadable.GetStatus().Diagnostics()[0].code,
"input-file-unreadable");
const TemporaryInputFile malformed{"malformed-keyword", "*, name=value\n"};
const auto malformedResult =
fesa::AbaqusInputReader{}.read(malformed.path());
ASSERT_FALSE(malformedResult.hasValue());
ASSERT_FALSE(malformedResult.HasValue());
EXPECT_EQ(
malformedResult.status().failureCategory(),
fesa::FailureCategory::input);
ASSERT_EQ(malformedResult.status().diagnostics().size(), 1U);
EXPECT_EQ(malformedResult.status().diagnostics()[0].code,
malformedResult.GetStatus().Category(),
fesa::FailureCategory::kInput);
ASSERT_EQ(malformedResult.GetStatus().Diagnostics().size(), 1U);
EXPECT_EQ(malformedResult.GetStatus().Diagnostics()[0].code,
"malformed-keyword");
EXPECT_EQ(malformedResult.status().diagnostics()[0].location.line, 1U);
EXPECT_EQ(malformedResult.GetStatus().Diagnostics()[0].location.line, 1U);
const TemporaryInputFile orphan{
"orphan-data", "** comment\n\norphan, data\n"};
const auto orphanResult = fesa::AbaqusInputReader{}.read(orphan.path());
ASSERT_FALSE(orphanResult.hasValue());
ASSERT_FALSE(orphanResult.HasValue());
EXPECT_EQ(
orphanResult.status().failureCategory(),
fesa::FailureCategory::input);
ASSERT_EQ(orphanResult.status().diagnostics().size(), 1U);
EXPECT_EQ(orphanResult.status().diagnostics()[0].code,
orphanResult.GetStatus().Category(),
fesa::FailureCategory::kInput);
ASSERT_EQ(orphanResult.GetStatus().Diagnostics().size(), 1U);
EXPECT_EQ(orphanResult.GetStatus().Diagnostics()[0].code,
"orphan-data-line");
EXPECT_EQ(orphanResult.status().diagnostics()[0].location.line, 3U);
EXPECT_EQ(orphanResult.GetStatus().Diagnostics()[0].location.line, 3U);
}
TEST(InpSyntax, ReadsLegacyCantileverWithoutMutation) {
@@ -105,23 +105,23 @@ TEST(InpSyntax, ReadsLegacyCantileverWithoutMutation) {
const auto result = fesa::AbaqusInputReader{}.read(inputPath);
ASSERT_TRUE(result.hasValue());
EXPECT_EQ(result.value().sourceContentIdentity,
ASSERT_TRUE(result.HasValue());
EXPECT_EQ(result.Value().sourceContentIdentity,
"fnv1a64:04543464cc970405");
EXPECT_EQ(result.value().sourcePath,
EXPECT_EQ(result.Value().sourcePath,
std::filesystem::absolute(inputPath).lexically_normal());
ASSERT_EQ(result.value().blocks.size(), 30U);
EXPECT_EQ(result.value().blocks.front().canonicalName, "HEADING");
EXPECT_EQ(result.value().blocks.front().location.line, 1U);
EXPECT_EQ(result.value().blocks.back().canonicalName, "END STEP");
ASSERT_EQ(result.Value().blocks.size(), 30U);
EXPECT_EQ(result.Value().blocks.front().canonicalName, "HEADING");
EXPECT_EQ(result.Value().blocks.front().location.line, 1U);
EXPECT_EQ(result.Value().blocks.back().canonicalName, "END STEP");
const auto element = std::find_if(
result.value().blocks.begin(),
result.value().blocks.end(),
result.Value().blocks.begin(),
result.Value().blocks.end(),
[](const fesa::KeywordBlock& block) {
return block.canonicalName == "ELEMENT";
});
ASSERT_NE(element, result.value().blocks.end());
ASSERT_NE(element, result.Value().blocks.end());
ASSERT_EQ(element->parameters.size(), 1U);
EXPECT_EQ(element->parameters[0].name, "TYPE");
ASSERT_TRUE(element->parameters[0].value.has_value());
+10 -10
View File
@@ -45,9 +45,9 @@ TEST(InpSyntax, CanonicalizesKeywordAndParameterNamesOnly) {
const auto result = fesa::AbaqusInputReader{}.read(input.path());
ASSERT_TRUE(result.hasValue());
ASSERT_EQ(result.value().blocks.size(), 1U);
const auto& block = result.value().blocks[0];
ASSERT_TRUE(result.HasValue());
ASSERT_EQ(result.Value().blocks.size(), 1U);
const auto& block = result.Value().blocks[0];
EXPECT_EQ(block.canonicalName, "ELEMENT");
EXPECT_EQ(block.originalLine, originalLine);
EXPECT_EQ(block.location.line, 1U);
@@ -73,23 +73,23 @@ TEST(InpSyntax, PreservesDataAndSourceLocations) {
const auto result = fesa::AbaqusInputReader{}.read(input.path());
ASSERT_TRUE(result.hasValue());
ASSERT_TRUE(result.HasValue());
EXPECT_EQ(
result.value().sourcePath,
result.Value().sourcePath,
std::filesystem::absolute(input.path()).lexically_normal());
EXPECT_EQ(result.value().sourceContentIdentity,
EXPECT_EQ(result.Value().sourceContentIdentity,
"fnv1a64:c120b6ed2445be46");
ASSERT_EQ(result.value().blocks.size(), 1U);
const auto& block = result.value().blocks[0];
ASSERT_EQ(result.Value().blocks.size(), 1U);
const auto& block = result.Value().blocks[0];
EXPECT_EQ(block.canonicalName, "NODE");
EXPECT_EQ(block.originalLine, "*NoDe");
EXPECT_EQ(block.location.file, result.value().sourcePath);
EXPECT_EQ(block.location.file, result.Value().sourcePath);
EXPECT_EQ(block.location.line, 3U);
ASSERT_EQ(block.data.size(), 1U);
EXPECT_EQ(
block.data[0].fields,
(std::vector<std::string>{"0007", "Label_A", "", ""}));
EXPECT_EQ(block.data[0].location.file, result.value().sourcePath);
EXPECT_EQ(block.data[0].location.file, result.Value().sourcePath);
EXPECT_EQ(block.data[0].location.line, 4U);
}