feat(cpp-object-oriented-modular-refactoring): step 6 - io-application-google-style
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
#include "fesa/io/abaqus/input_reader.hpp"
|
||||
#include "fesa/io/abaqus/input_reader.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@@ -12,122 +12,112 @@
|
||||
namespace {
|
||||
|
||||
class TemporaryInputFile {
|
||||
public:
|
||||
TemporaryInputFile(const std::string& stem, const std::string& content)
|
||||
: path_{std::filesystem::temp_directory_path() /
|
||||
("fesa-" + stem + ".inp")} {
|
||||
std::ofstream stream{path_, std::ios::binary | std::ios::trunc};
|
||||
stream.write(content.data(), static_cast<std::streamsize>(content.size()));
|
||||
if (!stream) {
|
||||
throw std::runtime_error{"Unable to create INP reader test fixture."};
|
||||
}
|
||||
public:
|
||||
TemporaryInputFile(const std::string& stem, const std::string& content)
|
||||
: path_{std::filesystem::temp_directory_path() /
|
||||
("fesa-" + stem + ".inp")} {
|
||||
std::ofstream stream{path_, std::ios::binary | std::ios::trunc};
|
||||
stream.write(content.data(), static_cast<std::streamsize>(content.size()));
|
||||
if (!stream) {
|
||||
throw std::runtime_error{"Unable to create INP reader test fixture."};
|
||||
}
|
||||
}
|
||||
|
||||
~TemporaryInputFile() {
|
||||
std::error_code error;
|
||||
std::filesystem::remove(path_, error);
|
||||
}
|
||||
~TemporaryInputFile() {
|
||||
std::error_code error;
|
||||
std::filesystem::remove(path_, error);
|
||||
}
|
||||
|
||||
const std::filesystem::path& path() const noexcept {
|
||||
return path_;
|
||||
}
|
||||
const std::filesystem::path& Path() const noexcept { return path_; }
|
||||
|
||||
private:
|
||||
std::filesystem::path path_;
|
||||
private:
|
||||
std::filesystem::path path_;
|
||||
};
|
||||
|
||||
std::string readExactBytes(const std::filesystem::path& path) {
|
||||
std::ifstream stream{path, std::ios::binary};
|
||||
if (!stream) {
|
||||
throw std::runtime_error{"Unable to read legacy INP fixture."};
|
||||
}
|
||||
return std::string{
|
||||
std::istreambuf_iterator<char>{stream},
|
||||
std::istreambuf_iterator<char>{}};
|
||||
std::string ReadExactBytes(const std::filesystem::path& path) {
|
||||
std::ifstream stream{path, std::ios::binary};
|
||||
if (!stream) {
|
||||
throw std::runtime_error{"Unable to read legacy INP fixture."};
|
||||
}
|
||||
return std::string{std::istreambuf_iterator<char>{stream},
|
||||
std::istreambuf_iterator<char>{}};
|
||||
}
|
||||
|
||||
std::filesystem::path repositoryRoot() {
|
||||
auto path = std::filesystem::path{__FILE__}.parent_path();
|
||||
for (int parent = 0; parent < 4; ++parent) {
|
||||
path = path.parent_path();
|
||||
}
|
||||
return path;
|
||||
std::filesystem::path RepositoryRoot() {
|
||||
auto path = std::filesystem::path{__FILE__}.parent_path();
|
||||
for (int parent = 0; parent < 4; ++parent) {
|
||||
path = path.parent_path();
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
TEST(InpSyntax, RejectsMalformedOrOrphanData) {
|
||||
const auto missingPath =
|
||||
std::filesystem::temp_directory_path() / "fesa-missing-input.inp";
|
||||
std::error_code removeError;
|
||||
std::filesystem::remove(missingPath, removeError);
|
||||
const auto missing_path =
|
||||
std::filesystem::temp_directory_path() / "fesa-missing-input.inp";
|
||||
std::error_code remove_error;
|
||||
std::filesystem::remove(missing_path, remove_error);
|
||||
|
||||
const auto unreadable = fesa::AbaqusInputReader{}.read(missingPath);
|
||||
ASSERT_FALSE(unreadable.HasValue());
|
||||
EXPECT_EQ(
|
||||
unreadable.GetStatus().Category(),
|
||||
fesa::FailureCategory::kInput);
|
||||
ASSERT_EQ(unreadable.GetStatus().Diagnostics().size(), 1U);
|
||||
EXPECT_EQ(unreadable.GetStatus().Diagnostics()[0].code,
|
||||
"input-file-unreadable");
|
||||
const auto unreadable = fesa::AbaqusInputReader{}.Read(missing_path);
|
||||
ASSERT_FALSE(unreadable.HasValue());
|
||||
EXPECT_EQ(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());
|
||||
EXPECT_EQ(
|
||||
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.GetStatus().Diagnostics()[0].location.line, 1U);
|
||||
const TemporaryInputFile malformed{"malformed-keyword", "*, name=value\n"};
|
||||
const auto malformed_result =
|
||||
fesa::AbaqusInputReader{}.Read(malformed.Path());
|
||||
ASSERT_FALSE(malformed_result.HasValue());
|
||||
EXPECT_EQ(malformed_result.GetStatus().Category(),
|
||||
fesa::FailureCategory::kInput);
|
||||
ASSERT_EQ(malformed_result.GetStatus().Diagnostics().size(), 1U);
|
||||
EXPECT_EQ(malformed_result.GetStatus().Diagnostics()[0].code,
|
||||
"malformed-keyword");
|
||||
EXPECT_EQ(malformed_result.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());
|
||||
EXPECT_EQ(
|
||||
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.GetStatus().Diagnostics()[0].location.line, 3U);
|
||||
const TemporaryInputFile orphan{"orphan-data",
|
||||
"** comment\n\norphan, data\n"};
|
||||
const auto orphan_result = fesa::AbaqusInputReader{}.Read(orphan.Path());
|
||||
ASSERT_FALSE(orphan_result.HasValue());
|
||||
EXPECT_EQ(orphan_result.GetStatus().Category(),
|
||||
fesa::FailureCategory::kInput);
|
||||
ASSERT_EQ(orphan_result.GetStatus().Diagnostics().size(), 1U);
|
||||
EXPECT_EQ(orphan_result.GetStatus().Diagnostics()[0].code,
|
||||
"orphan-data-line");
|
||||
EXPECT_EQ(orphan_result.GetStatus().Diagnostics()[0].location.line, 3U);
|
||||
}
|
||||
|
||||
TEST(InpSyntax, ReadsLegacyCantileverWithoutMutation) {
|
||||
const auto inputPath =
|
||||
repositoryRoot() / "reference" / "cantilever beam" /
|
||||
"cantilever beam.inp";
|
||||
const auto bytesBefore = readExactBytes(inputPath);
|
||||
const auto timestampBefore = std::filesystem::last_write_time(inputPath);
|
||||
const auto input_path = RepositoryRoot() / "reference" / "cantilever beam" /
|
||||
"cantilever beam.inp";
|
||||
const auto bytes_before = ReadExactBytes(input_path);
|
||||
const auto timestamp_before = std::filesystem::last_write_time(input_path);
|
||||
|
||||
const auto result = fesa::AbaqusInputReader{}.read(inputPath);
|
||||
const auto result = fesa::AbaqusInputReader{}.Read(input_path);
|
||||
|
||||
ASSERT_TRUE(result.HasValue());
|
||||
EXPECT_EQ(result.Value().sourceContentIdentity,
|
||||
"fnv1a64:04543464cc970405");
|
||||
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_TRUE(result.HasValue());
|
||||
EXPECT_EQ(result.Value().source_content_identity, "fnv1a64:04543464cc970405");
|
||||
EXPECT_EQ(result.Value().source_path,
|
||||
std::filesystem::absolute(input_path).lexically_normal());
|
||||
ASSERT_EQ(result.Value().blocks.size(), 30U);
|
||||
EXPECT_EQ(result.Value().blocks.front().canonical_name, "HEADING");
|
||||
EXPECT_EQ(result.Value().blocks.front().location.line, 1U);
|
||||
EXPECT_EQ(result.Value().blocks.back().canonical_name, "END STEP");
|
||||
|
||||
const auto element = std::find_if(
|
||||
result.Value().blocks.begin(),
|
||||
result.Value().blocks.end(),
|
||||
[](const fesa::KeywordBlock& block) {
|
||||
return block.canonicalName == "ELEMENT";
|
||||
});
|
||||
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());
|
||||
EXPECT_EQ(*element->parameters[0].value, "B33");
|
||||
EXPECT_EQ(element->data.size(), 10U);
|
||||
const auto element =
|
||||
std::find_if(result.Value().blocks.begin(), result.Value().blocks.end(),
|
||||
[](const fesa::KeywordBlock& block) {
|
||||
return block.canonical_name == "ELEMENT";
|
||||
});
|
||||
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());
|
||||
EXPECT_EQ(*element->parameters[0].value, "B33");
|
||||
EXPECT_EQ(element->data.size(), 10U);
|
||||
|
||||
EXPECT_EQ(readExactBytes(inputPath), bytesBefore);
|
||||
EXPECT_EQ(std::filesystem::last_write_time(inputPath), timestampBefore);
|
||||
EXPECT_EQ(ReadExactBytes(input_path), bytes_before);
|
||||
EXPECT_EQ(std::filesystem::last_write_time(input_path), timestamp_before);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#include "fesa/io/abaqus/input_reader.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <filesystem>
|
||||
@@ -8,88 +6,84 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "fesa/io/abaqus/input_reader.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class TemporaryInputFile {
|
||||
public:
|
||||
TemporaryInputFile(const std::string& stem, const std::string& content)
|
||||
: path_{std::filesystem::temp_directory_path() /
|
||||
("fesa-" + stem + ".inp")} {
|
||||
std::ofstream stream{path_, std::ios::binary | std::ios::trunc};
|
||||
stream.write(content.data(), static_cast<std::streamsize>(content.size()));
|
||||
if (!stream) {
|
||||
throw std::runtime_error{"Unable to create INP syntax test fixture."};
|
||||
}
|
||||
public:
|
||||
TemporaryInputFile(const std::string& stem, const std::string& content)
|
||||
: path_{std::filesystem::temp_directory_path() /
|
||||
("fesa-" + stem + ".inp")} {
|
||||
std::ofstream stream{path_, std::ios::binary | std::ios::trunc};
|
||||
stream.write(content.data(), static_cast<std::streamsize>(content.size()));
|
||||
if (!stream) {
|
||||
throw std::runtime_error{"Unable to create INP syntax test fixture."};
|
||||
}
|
||||
}
|
||||
|
||||
~TemporaryInputFile() {
|
||||
std::error_code error;
|
||||
std::filesystem::remove(path_, error);
|
||||
}
|
||||
~TemporaryInputFile() {
|
||||
std::error_code error;
|
||||
std::filesystem::remove(path_, error);
|
||||
}
|
||||
|
||||
const std::filesystem::path& path() const noexcept {
|
||||
return path_;
|
||||
}
|
||||
const std::filesystem::path& Path() const noexcept { return path_; }
|
||||
|
||||
private:
|
||||
std::filesystem::path path_;
|
||||
private:
|
||||
std::filesystem::path path_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
TEST(InpSyntax, CanonicalizesKeywordAndParameterNamesOnly) {
|
||||
const std::string originalLine =
|
||||
" *eLeMeNt, TyPe= b33 , generate, ELSET=Beam_Set ";
|
||||
const TemporaryInputFile input{
|
||||
"canonical-names", originalLine + "\n"};
|
||||
const std::string original_line =
|
||||
" *eLeMeNt, TyPe= b33 , generate, ELSET=Beam_Set ";
|
||||
const TemporaryInputFile input{"canonical-names", original_line + "\n"};
|
||||
|
||||
const auto result = fesa::AbaqusInputReader{}.read(input.path());
|
||||
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];
|
||||
EXPECT_EQ(block.canonicalName, "ELEMENT");
|
||||
EXPECT_EQ(block.originalLine, originalLine);
|
||||
EXPECT_EQ(block.location.line, 1U);
|
||||
ASSERT_TRUE(result.HasValue());
|
||||
ASSERT_EQ(result.Value().blocks.size(), 1U);
|
||||
const auto& block = result.Value().blocks[0];
|
||||
EXPECT_EQ(block.canonical_name, "ELEMENT");
|
||||
EXPECT_EQ(block.original_line, original_line);
|
||||
EXPECT_EQ(block.location.line, 1U);
|
||||
|
||||
ASSERT_EQ(block.parameters.size(), 3U);
|
||||
EXPECT_EQ(block.parameters[0].name, "TYPE");
|
||||
ASSERT_TRUE(block.parameters[0].value.has_value());
|
||||
EXPECT_EQ(*block.parameters[0].value, "b33");
|
||||
EXPECT_EQ(block.parameters[1].name, "GENERATE");
|
||||
EXPECT_FALSE(block.parameters[1].value.has_value());
|
||||
EXPECT_EQ(block.parameters[2].name, "ELSET");
|
||||
ASSERT_TRUE(block.parameters[2].value.has_value());
|
||||
EXPECT_EQ(*block.parameters[2].value, "Beam_Set");
|
||||
ASSERT_EQ(block.parameters.size(), 3U);
|
||||
EXPECT_EQ(block.parameters[0].name, "TYPE");
|
||||
ASSERT_TRUE(block.parameters[0].value.has_value());
|
||||
EXPECT_EQ(*block.parameters[0].value, "b33");
|
||||
EXPECT_EQ(block.parameters[1].name, "GENERATE");
|
||||
EXPECT_FALSE(block.parameters[1].value.has_value());
|
||||
EXPECT_EQ(block.parameters[2].name, "ELSET");
|
||||
ASSERT_TRUE(block.parameters[2].value.has_value());
|
||||
EXPECT_EQ(*block.parameters[2].value, "Beam_Set");
|
||||
}
|
||||
|
||||
TEST(InpSyntax, PreservesDataAndSourceLocations) {
|
||||
const std::string exactBytes =
|
||||
"** retained only in line accounting\r\n"
|
||||
"\r\n"
|
||||
"*NoDe\r\n"
|
||||
" 0007, Label_A, ,\r\n";
|
||||
const TemporaryInputFile input{"data-and-locations", exactBytes};
|
||||
const std::string exact_bytes =
|
||||
"** retained only in line accounting\r\n"
|
||||
"\r\n"
|
||||
"*NoDe\r\n"
|
||||
" 0007, Label_A, ,\r\n";
|
||||
const TemporaryInputFile input{"data-and-locations", exact_bytes};
|
||||
|
||||
const auto result = fesa::AbaqusInputReader{}.read(input.path());
|
||||
const auto result = fesa::AbaqusInputReader{}.Read(input.Path());
|
||||
|
||||
ASSERT_TRUE(result.HasValue());
|
||||
EXPECT_EQ(
|
||||
result.Value().sourcePath,
|
||||
std::filesystem::absolute(input.path()).lexically_normal());
|
||||
EXPECT_EQ(result.Value().sourceContentIdentity,
|
||||
"fnv1a64:c120b6ed2445be46");
|
||||
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.line, 3U);
|
||||
ASSERT_TRUE(result.HasValue());
|
||||
EXPECT_EQ(result.Value().source_path,
|
||||
std::filesystem::absolute(input.Path()).lexically_normal());
|
||||
EXPECT_EQ(result.Value().source_content_identity, "fnv1a64:c120b6ed2445be46");
|
||||
ASSERT_EQ(result.Value().blocks.size(), 1U);
|
||||
const auto& block = result.Value().blocks[0];
|
||||
EXPECT_EQ(block.canonical_name, "NODE");
|
||||
EXPECT_EQ(block.original_line, "*NoDe");
|
||||
EXPECT_EQ(block.location.file, result.Value().source_path);
|
||||
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.line, 4U);
|
||||
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().source_path);
|
||||
EXPECT_EQ(block.data[0].location.line, 4U);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user