feat(cpp-object-oriented-modular-refactoring): step 6 - io-application-google-style
This commit is contained in:
@@ -1,7 +1,3 @@
|
||||
#include "mitc4_reference_comparison.hpp"
|
||||
|
||||
#include "fesa/app/fesa_application.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -14,6 +10,9 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "fesa/app/fesa_application.h"
|
||||
#include "mitc4_reference_comparison.h"
|
||||
|
||||
#ifndef FESA_TEST_SOURCE_DIR
|
||||
#error FESA_TEST_SOURCE_DIR must identify the repository root.
|
||||
#endif
|
||||
@@ -30,150 +29,139 @@ constexpr const char* kIntegrationRule =
|
||||
constexpr std::size_t kNodeCount = 49U;
|
||||
constexpr std::size_t kComponentCount = 6U;
|
||||
|
||||
std::string readBytes(const std::filesystem::path& path) {
|
||||
std::ifstream stream{path, std::ios::binary};
|
||||
if (!stream) {
|
||||
throw std::runtime_error{"Unable to read declared reference artifact."};
|
||||
}
|
||||
return {std::istreambuf_iterator<char>{stream},
|
||||
std::istreambuf_iterator<char>{}};
|
||||
std::string ReadBytes(const std::filesystem::path& path) {
|
||||
std::ifstream stream{path, std::ios::binary};
|
||||
if (!stream) {
|
||||
throw std::runtime_error{"Unable to read declared reference artifact."};
|
||||
}
|
||||
return {std::istreambuf_iterator<char>{stream},
|
||||
std::istreambuf_iterator<char>{}};
|
||||
}
|
||||
|
||||
struct ArtifactSnapshot {
|
||||
std::string bytes;
|
||||
std::filesystem::file_time_type lastWriteTime;
|
||||
std::string bytes;
|
||||
std::filesystem::file_time_type last_write_time;
|
||||
};
|
||||
|
||||
ArtifactSnapshot snapshot(const std::filesystem::path& path) {
|
||||
return {readBytes(path), std::filesystem::last_write_time(path)};
|
||||
ArtifactSnapshot Snapshot(const std::filesystem::path& path) {
|
||||
return {ReadBytes(path), std::filesystem::last_write_time(path)};
|
||||
}
|
||||
|
||||
void expectUnchanged(
|
||||
const std::filesystem::path& path, const ArtifactSnapshot& before) {
|
||||
EXPECT_EQ(readBytes(path), before.bytes) << path.string();
|
||||
EXPECT_EQ(std::filesystem::last_write_time(path), before.lastWriteTime)
|
||||
<< path.string();
|
||||
void ExpectUnchanged(const std::filesystem::path& path,
|
||||
const ArtifactSnapshot& before) {
|
||||
EXPECT_EQ(ReadBytes(path), before.bytes) << path.string();
|
||||
EXPECT_EQ(std::filesystem::last_write_time(path), before.last_write_time)
|
||||
<< path.string();
|
||||
}
|
||||
|
||||
struct CaseEvidence {
|
||||
fesa::test::Mitc4ComparisonReport report;
|
||||
std::filesystem::path comparisonJson;
|
||||
fesa::test::Mitc4ComparisonReport report;
|
||||
std::filesystem::path comparison_json;
|
||||
};
|
||||
|
||||
CaseEvidence runCase(
|
||||
const std::string& caseId,
|
||||
const std::string& sourceElementType,
|
||||
const std::filesystem::path& referenceDirectory,
|
||||
const std::filesystem::path& input,
|
||||
const std::filesystem::path& csv,
|
||||
const std::string& outputName) {
|
||||
const auto inputBefore = snapshot(input);
|
||||
const auto csvBefore = snapshot(csv);
|
||||
const std::filesystem::path outputDirectory =
|
||||
std::filesystem::path{FESA_TEST_BINARY_DIR} / "reference" / outputName;
|
||||
std::error_code error;
|
||||
std::filesystem::remove_all(outputDirectory, error);
|
||||
error.clear();
|
||||
if (!std::filesystem::create_directories(outputDirectory, error) || error) {
|
||||
throw std::runtime_error{"Unable to create MITC4 evidence directory."};
|
||||
}
|
||||
const auto results = outputDirectory / "results.h5";
|
||||
const auto comparison = outputDirectory / "comparison.json";
|
||||
CaseEvidence RunCase(const std::string& case_id,
|
||||
const std::string& source_element_type,
|
||||
const std::filesystem::path& reference_directory,
|
||||
const std::filesystem::path& input,
|
||||
const std::filesystem::path& csv,
|
||||
const std::string& output_name) {
|
||||
const auto input_before = Snapshot(input);
|
||||
const auto csv_before = Snapshot(csv);
|
||||
const std::filesystem::path output_directory =
|
||||
std::filesystem::path{FESA_TEST_BINARY_DIR} / "reference" / output_name;
|
||||
std::error_code error;
|
||||
std::filesystem::remove_all(output_directory, error);
|
||||
error.clear();
|
||||
if (!std::filesystem::create_directories(output_directory, error) || error) {
|
||||
throw std::runtime_error{"Unable to create MITC4 evidence directory."};
|
||||
}
|
||||
const auto results = output_directory / "results.h5";
|
||||
const auto comparison = output_directory / "comparison.json";
|
||||
|
||||
fesa::FesaApplication application;
|
||||
EXPECT_EQ(
|
||||
application.run({input.string(), "--output", results.string()}), 0);
|
||||
EXPECT_TRUE(std::filesystem::is_regular_file(results));
|
||||
auto comparisonResult = fesa::test::Mitc4ReferenceComparison::compare(
|
||||
{caseId, sourceElementType, input, csv, results});
|
||||
if (!comparisonResult.HasValue()) {
|
||||
std::string diagnostics;
|
||||
for (const auto& diagnostic :
|
||||
comparisonResult.GetStatus().Diagnostics()) {
|
||||
diagnostics += "\n" + diagnostic.code + ": " + diagnostic.message;
|
||||
}
|
||||
ADD_FAILURE() << "MITC4 comparison precheck failed for " << caseId
|
||||
<< diagnostics;
|
||||
return {{}, comparison};
|
||||
fesa::FesaApplication application;
|
||||
EXPECT_EQ(application.Run({input.string(), "--output", results.string()}), 0);
|
||||
EXPECT_TRUE(std::filesystem::is_regular_file(results));
|
||||
auto comparison_result = fesa::test::Mitc4ReferenceComparison::Compare(
|
||||
{case_id, source_element_type, input, csv, results});
|
||||
if (!comparison_result.HasValue()) {
|
||||
std::string diagnostics;
|
||||
for (const auto& diagnostic : comparison_result.GetStatus().Diagnostics()) {
|
||||
diagnostics += "\n" + diagnostic.code + ": " + diagnostic.message;
|
||||
}
|
||||
EXPECT_TRUE(
|
||||
fesa::test::Mitc4ReferenceComparison::writeDeterministicJson(
|
||||
comparisonResult.Value(), comparison)
|
||||
.IsOk());
|
||||
EXPECT_TRUE(std::filesystem::is_regular_file(comparison));
|
||||
ADD_FAILURE() << "MITC4 comparison precheck failed for " << case_id
|
||||
<< diagnostics;
|
||||
return {{}, comparison};
|
||||
}
|
||||
EXPECT_TRUE(fesa::test::Mitc4ReferenceComparison::WriteDeterministicJson(
|
||||
comparison_result.Value(), comparison)
|
||||
.IsOk());
|
||||
EXPECT_TRUE(std::filesystem::is_regular_file(comparison));
|
||||
|
||||
std::vector<std::string> generated;
|
||||
for (const auto& entry :
|
||||
std::filesystem::directory_iterator{outputDirectory}) {
|
||||
generated.push_back(entry.path().filename().string());
|
||||
}
|
||||
std::sort(generated.begin(), generated.end());
|
||||
EXPECT_EQ(
|
||||
generated,
|
||||
(std::vector<std::string>{"comparison.json", "results.h5"}));
|
||||
EXPECT_TRUE(std::filesystem::is_directory(referenceDirectory));
|
||||
expectUnchanged(input, inputBefore);
|
||||
expectUnchanged(csv, csvBefore);
|
||||
return {std::move(comparisonResult.Value()), comparison};
|
||||
std::vector<std::string> generated;
|
||||
for (const auto& entry :
|
||||
std::filesystem::directory_iterator{output_directory}) {
|
||||
generated.push_back(entry.path().filename().string());
|
||||
}
|
||||
std::sort(generated.begin(), generated.end());
|
||||
EXPECT_EQ(generated,
|
||||
(std::vector<std::string>{"comparison.json", "results.h5"}));
|
||||
EXPECT_TRUE(std::filesystem::is_directory(reference_directory));
|
||||
ExpectUnchanged(input, input_before);
|
||||
ExpectUnchanged(csv, csv_before);
|
||||
return {std::move(comparison_result.Value()), comparison};
|
||||
}
|
||||
|
||||
void expectCommonMetadata(
|
||||
const fesa::test::Mitc4ComparisonReport& report,
|
||||
const std::string& caseId,
|
||||
const std::string& sourceElementType) {
|
||||
EXPECT_EQ(report.caseId, caseId);
|
||||
EXPECT_EQ(report.sourceElementType, sourceElementType);
|
||||
EXPECT_EQ(report.internalFormulation, kInternalFormulation);
|
||||
EXPECT_EQ(report.integrationRule, kIntegrationRule);
|
||||
void ExpectCommonMetadata(const fesa::test::Mitc4ComparisonReport& report,
|
||||
const std::string& case_id,
|
||||
const std::string& source_element_type) {
|
||||
EXPECT_EQ(report.case_id, case_id);
|
||||
EXPECT_EQ(report.source_element_type, source_element_type);
|
||||
EXPECT_EQ(report.internal_formulation, kInternalFormulation);
|
||||
EXPECT_EQ(report.integration_rule, kIntegrationRule);
|
||||
}
|
||||
|
||||
void expectComparisonCoverage(
|
||||
const fesa::test::Mitc4ComparisonReport& report) {
|
||||
ASSERT_EQ(report.rows.size(), kNodeCount * kComponentCount);
|
||||
ASSERT_EQ(report.metrics.size(), kComponentCount);
|
||||
ASSERT_EQ(report.vectorMetrics.size(), kNodeCount);
|
||||
EXPECT_TRUE(report.passed);
|
||||
const std::size_t blockingRows = static_cast<std::size_t>(std::count_if(
|
||||
report.rows.begin(), report.rows.end(),
|
||||
[](const fesa::test::Mitc4RowDecision& row) {
|
||||
return row.blocking;
|
||||
}));
|
||||
const std::size_t rotationRows = report.rows.size() - blockingRows;
|
||||
EXPECT_EQ(blockingRows, kNodeCount * 3U);
|
||||
EXPECT_EQ(rotationRows, kNodeCount * 3U);
|
||||
EXPECT_TRUE(std::all_of(
|
||||
report.rows.begin(), report.rows.end(),
|
||||
[](const fesa::test::Mitc4RowDecision& row) {
|
||||
return !row.blocking || row.withinTolerance;
|
||||
}));
|
||||
EXPECT_EQ(
|
||||
report.warnings.size(),
|
||||
static_cast<std::size_t>(std::count_if(
|
||||
report.rows.begin(), report.rows.end(),
|
||||
[](const fesa::test::Mitc4RowDecision& row) {
|
||||
return !row.blocking && !row.withinTolerance;
|
||||
})));
|
||||
void ExpectComparisonCoverage(const fesa::test::Mitc4ComparisonReport& report) {
|
||||
ASSERT_EQ(report.rows.size(), kNodeCount * kComponentCount);
|
||||
ASSERT_EQ(report.metrics.size(), kComponentCount);
|
||||
ASSERT_EQ(report.vector_metrics.size(), kNodeCount);
|
||||
EXPECT_TRUE(report.passed);
|
||||
const std::size_t blocking_rows = static_cast<std::size_t>(std::count_if(
|
||||
report.rows.begin(), report.rows.end(),
|
||||
[](const fesa::test::Mitc4RowDecision& row) { return row.blocking; }));
|
||||
const std::size_t rotation_rows = report.rows.size() - blocking_rows;
|
||||
EXPECT_EQ(blocking_rows, kNodeCount * 3U);
|
||||
EXPECT_EQ(rotation_rows, kNodeCount * 3U);
|
||||
EXPECT_TRUE(std::all_of(report.rows.begin(), report.rows.end(),
|
||||
[](const fesa::test::Mitc4RowDecision& row) {
|
||||
return !row.blocking || row.within_tolerance;
|
||||
}));
|
||||
EXPECT_EQ(report.warnings.size(),
|
||||
static_cast<std::size_t>(
|
||||
std::count_if(report.rows.begin(), report.rows.end(),
|
||||
[](const fesa::test::Mitc4RowDecision& row) {
|
||||
return !row.blocking && !row.within_tolerance;
|
||||
})));
|
||||
}
|
||||
|
||||
// MITC4-E2E-S4-001
|
||||
TEST(Mitc4S4Reference, PreservesS4AndWritesCommonMitc4Metadata) {
|
||||
const std::filesystem::path root{FESA_TEST_SOURCE_DIR};
|
||||
const auto directory = root / "reference" / "shell";
|
||||
const auto evidence = runCase(
|
||||
"shell-s4", "S4", directory, directory / "shell.inp",
|
||||
directory / "shell displacements.csv", "mitc4-shell-s4-metadata");
|
||||
expectCommonMetadata(evidence.report, "shell-s4", "S4");
|
||||
const std::filesystem::path root{FESA_TEST_SOURCE_DIR};
|
||||
const auto directory = root / "reference" / "shell";
|
||||
const auto evidence =
|
||||
RunCase("shell-s4", "S4", directory, directory / "shell.inp",
|
||||
directory / "shell displacements.csv", "mitc4-shell-s4-metadata");
|
||||
ExpectCommonMetadata(evidence.report, "shell-s4", "S4");
|
||||
}
|
||||
|
||||
// MITC4-E2E-S4-002
|
||||
TEST(Mitc4S4Reference, PassesBlockingUAndReportsEveryUrRow) {
|
||||
const std::filesystem::path root{FESA_TEST_SOURCE_DIR};
|
||||
const auto directory = root / "reference" / "shell";
|
||||
const auto evidence = runCase(
|
||||
"shell-s4", "S4", directory, directory / "shell.inp",
|
||||
directory / "shell displacements.csv", "mitc4-shell-s4-comparison");
|
||||
expectCommonMetadata(evidence.report, "shell-s4", "S4");
|
||||
expectComparisonCoverage(evidence.report);
|
||||
const std::filesystem::path root{FESA_TEST_SOURCE_DIR};
|
||||
const auto directory = root / "reference" / "shell";
|
||||
const auto evidence = RunCase(
|
||||
"shell-s4", "S4", directory, directory / "shell.inp",
|
||||
directory / "shell displacements.csv", "mitc4-shell-s4-comparison");
|
||||
ExpectCommonMetadata(evidence.report, "shell-s4", "S4");
|
||||
ExpectComparisonCoverage(evidence.report);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user