Files
ViewDesignEngine/tests/regression/regression_extreme.cpp
T

226 lines
5.7 KiB
C++
Raw Normal View History

/// @file regression_extreme.cpp
/// @brief 极端坐标回归测试
///
/// 覆盖场景:
/// 1. 极小坐标(1e-15
/// 2. 极大坐标(1e15
/// 3. NaN 输入
/// 4. Inf 输入
///
/// 每个测试:构造极端体 → 布尔/修复/验证 → 断言不崩溃
#include <gtest/gtest.h>
#include "vde/brep/brep.h"
#include "vde/brep/modeling.h"
#include "vde/brep/brep_boolean.h"
#include "vde/brep/brep_validate.h"
#include "vde/brep/brep_heal.h"
#include "vde/core/point.h"
#include <cmath>
#include <limits>
using namespace vde::brep;
using namespace vde::core;
// ── 极小坐标测试 ──
TEST(RegressionExtreme, TinyCoordinates_1eMinus15) {
// 极小的盒子:尺寸为 1e-15
double s = 1e-15;
EXPECT_NO_THROW({
auto tiny = make_box(s, s, s);
// 验证合法性
EXPECT_TRUE(tiny.is_valid());
// 布尔运算:与正常盒子
auto box = make_box(1.0, 1.0, 1.0);
auto u = brep_union(tiny, box);
EXPECT_TRUE(u.is_valid());
auto i = brep_intersection(tiny, box);
EXPECT_TRUE(i.is_valid());
// 导出网格
auto mesh = tiny.to_mesh();
(void)mesh;
});
}
TEST(RegressionExtreme, TinyCoordinates_1eMinus10) {
double s = 1e-10;
EXPECT_NO_THROW({
auto tiny = make_box(s, s, s);
EXPECT_TRUE(tiny.is_valid());
auto mesh = tiny.to_mesh();
(void)mesh;
// 修复流水线
BrepModel copy = tiny;
heal_topology(copy, s * 0.1);
});
}
TEST(RegressionExtreme, TinyCoordinates_Mixed) {
// 一个维度极小,其他正常
EXPECT_NO_THROW({
auto thin = make_box(1e-15, 1.0, 1.0);
EXPECT_NO_THROW({ thin.is_valid(); });
auto result = validate(thin);
(void)result;
auto mesh = thin.to_mesh();
(void)mesh;
});
}
// ── 极大坐标测试 ──
TEST(RegressionExtreme, HugeCoordinates_1e15) {
double s = 1e15;
EXPECT_NO_THROW({
auto huge = make_box(s, s, s);
// 基本验证不崩溃
EXPECT_TRUE(huge.is_valid());
// 包围盒计算
auto bb = huge.bounds();
EXPECT_TRUE(std::isfinite(bb.min().x()));
EXPECT_TRUE(std::isfinite(bb.max().x()));
// 布尔自交
auto u = brep_union(huge, huge);
EXPECT_TRUE(u.is_valid());
// 网格导出(大尺寸模型)
auto mesh = huge.to_mesh(0.01 * s);
(void)mesh;
});
}
TEST(RegressionExtreme, HugeVsTiny) {
// 巨大体与极小体的布尔
EXPECT_NO_THROW({
auto huge = make_box(1e12, 1e12, 1e12);
auto tiny = make_box(1e-12, 1e-12, 1e-12);
auto u = brep_union(huge, tiny);
EXPECT_TRUE(u.is_valid());
auto i = brep_intersection(huge, tiny);
EXPECT_TRUE(i.is_valid());
});
}
// ── NaN 输入测试 ──
TEST(RegressionExtreme, NaN_Handling) {
double nan = std::numeric_limits<double>::quiet_NaN();
// make_box 应对 NaN 表现得优雅(返回无效体或抛出,但绝不能崩溃)
EXPECT_NO_THROW({
auto body = make_box(nan, 1.0, 1.0);
(void)body;
});
EXPECT_NO_THROW({
auto body = make_box(1.0, nan, 1.0);
(void)body;
});
EXPECT_NO_THROW({
auto body = make_box(1.0, 1.0, nan);
(void)body;
});
EXPECT_NO_THROW({
auto body = make_box(nan, nan, nan);
(void)body;
});
}
TEST(RegressionExtreme, NaN_BooleanResilience) {
// 若 NaN 产生了有效的 body,检查布尔运算不崩溃
auto good = make_box(2.0, 2.0, 2.0);
// 将所有尝试包裹在 EXPECT_NO_THROW 中
EXPECT_NO_THROW({
try {
auto bad = make_box(std::numeric_limits<double>::quiet_NaN(), 1.0, 1.0);
auto u = brep_union(good, bad);
(void)u;
} catch (...) {
// 允许抛异常但不应崩溃
}
});
}
// ── Inf 输入测试 ──
TEST(RegressionExtreme, Inf_Handling) {
double inf = std::numeric_limits<double>::infinity();
EXPECT_NO_THROW({
auto body = make_box(inf, 1.0, 1.0);
(void)body;
});
EXPECT_NO_THROW({
auto body = make_box(1.0, inf, 1.0);
(void)body;
});
EXPECT_NO_THROW({
auto body = make_box(1.0, 1.0, inf);
(void)body;
});
}
// ── 极大值 vs 极小值布尔 ──
TEST(RegressionExtreme, MaxDouble_Boolean) {
double big = 1e100;
double small = 1e-100;
EXPECT_NO_THROW({
auto a = make_box(big, 1.0, 1.0);
auto b = make_box(small, 1.0, 1.0);
auto u = brep_union(a, b);
(void)u.is_valid();
});
}
// ── 边界值批处理 ──
TEST(RegressionExtreme, BoundaryValuesBatch) {
// 一系列边界值,确保每个都不会崩溃
double values[] = {
0.0,
std::numeric_limits<double>::min(),
std::numeric_limits<double>::denorm_min(),
std::numeric_limits<double>::epsilon(),
1e-15, 1e-10, 1e-5,
1.0, 10.0, 100.0,
1e5, 1e10, 1e15,
std::numeric_limits<double>::max() * 0.5,
};
for (double v : values) {
if (!std::isfinite(v)) continue;
EXPECT_NO_THROW({
auto body = make_box(v, v, v);
body.is_valid();
auto mesh = body.to_mesh();
(void)mesh;
}) << "failed at v=" << v;
}
// 混合边界值布尔
auto a = make_box(values[0], 1.0, 1.0);
for (int i = 1; i < 10; ++i) {
if (!std::isfinite(values[i])) continue;
EXPECT_NO_THROW({
auto b = make_box(values[i], 1.0, 1.0);
auto u = brep_union(a, b);
(void)u.is_valid();
}) << "failed at i=" << i;
}
}