feat(solver-bootstrap): step 3 — core-ids-and-diagnostics

This commit is contained in:
KOKO\Mimi
2026-07-30 13:01:15 +09:00
parent 3e44deed72
commit 34d21f43fe
10 changed files with 255 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
#include <filesystem>
#include <optional>
#include <string>
#include <gtest/gtest.h>
#include <fesa/core/diagnostic.hpp>
namespace {
TEST(Diagnostic, PreservesSourceLocation) {
const fesa::Diagnostic diagnostic{
fesa::DiagnosticStage::syntax,
fesa::Severity::error,
"ABAQUS_INVALID_NODE",
"Node data is incomplete.",
fesa::SourceLocation{
std::filesystem::path{"models/beam.inp"}, 42, 9}};
ASSERT_TRUE(diagnostic.source.has_value());
EXPECT_EQ(
diagnostic.source->file, std::filesystem::path{"models/beam.inp"});
EXPECT_EQ(diagnostic.source->line, 42U);
EXPECT_EQ(diagnostic.source->column, 9U);
}
TEST(Diagnostic, AllowsDiagnosticsWithoutSourceLocation) {
const fesa::Diagnostic diagnostic{
fesa::DiagnosticStage::solver,
fesa::Severity::warning,
"SOLVER_RESIDUAL",
"Residual is above the reporting threshold.",
std::nullopt};
EXPECT_FALSE(diagnostic.source.has_value());
}
} // namespace
+36
View File
@@ -0,0 +1,36 @@
#include <cstdint>
#include <stdexcept>
#include <type_traits>
#include <gtest/gtest.h>
#include <fesa/core/entity_id.hpp>
namespace {
struct NodeTag;
struct ElementTag;
using NodeId = fesa::EntityId<NodeTag>;
using ElementId = fesa::EntityId<ElementTag>;
static_assert(std::is_constructible_v<NodeId, std::int64_t>);
static_assert(!std::is_convertible_v<std::int64_t, NodeId>);
static_assert(!std::is_convertible_v<NodeId, ElementId>);
TEST(EntityId, PreservesValueAndSupportsTypedOrdering) {
constexpr NodeId first{7};
constexpr NodeId second{11};
static_assert(first.value() == 7);
static_assert(first < second);
EXPECT_EQ(first.value(), 7);
EXPECT_LT(first, second);
}
TEST(EntityId, RejectsNegativeValues) {
EXPECT_THROW((NodeId{-1}), std::invalid_argument);
}
} // namespace
+35
View File
@@ -0,0 +1,35 @@
#include <filesystem>
#include <vector>
#include <gtest/gtest.h>
#include <fesa/core/status.hpp>
namespace {
TEST(CoreStatus, PreservesFailureDiagnostics) {
const fesa::Status status{
false,
{fesa::Diagnostic{
fesa::DiagnosticStage::model,
fesa::Severity::error,
"MODEL_NONFINITE_VECTOR",
"A vector component is not finite.",
fesa::SourceLocation{
std::filesystem::path{"models/invalid.inp"}, 8, 3}}}};
EXPECT_FALSE(status.succeeded);
ASSERT_EQ(status.diagnostics.size(), 1U);
EXPECT_EQ(status.diagnostics.front().code, "MODEL_NONFINITE_VECTOR");
ASSERT_TRUE(status.diagnostics.front().source.has_value());
EXPECT_EQ(status.diagnostics.front().source->line, 8U);
}
TEST(CoreStatus, RepresentsSuccessWithoutDiagnostics) {
const fesa::Status status{true, {}};
EXPECT_TRUE(status.succeeded);
EXPECT_TRUE(status.diagnostics.empty());
}
} // namespace
+20
View File
@@ -0,0 +1,20 @@
#include <limits>
#include <gtest/gtest.h>
#include <fesa/core/vec3.hpp>
namespace {
TEST(CoreVec3, ReportsOnlyFiniteVectorsAsFinite) {
EXPECT_TRUE(fesa::is_finite(fesa::Vec3{1.0, -2.0, 0.0}));
const double infinity = std::numeric_limits<double>::infinity();
const double nan = std::numeric_limits<double>::quiet_NaN();
EXPECT_FALSE(fesa::is_finite(fesa::Vec3{infinity, 0.0, 0.0}));
EXPECT_FALSE(fesa::is_finite(fesa::Vec3{0.0, -infinity, 0.0}));
EXPECT_FALSE(fesa::is_finite(fesa::Vec3{0.0, 0.0, nan}));
}
} // namespace