Files
ViewDesignEngine/tests/regression/regression_extreme.cpp
T
茂之钳 7b76689ea1
CI / Build & Test (push) Failing after 41s
CI / Release Build (push) Failing after 30s
Build & Test / build-and-test (push) Has been cancelled
Build & Test / python-bindings (push) Has been cancelled
feat(v11): CI/CD + regression tests + fuzzing + benchmarks + code quality
v11.1 — Test Infrastructure (14 files):
- .github/workflows/ci.yml: Ubuntu 22.04 + GCC 11, auto ctest on push
- tests/regression/: degenerate geometry, extreme coords, thin wall, large models
- tests/fuzz/: SDF random CSG, random booleans, format round-trip, continuous mode
- tests/benchmark/: boolean perf, MC perf, IO perf benchmarks
- docs/benchmark-report.md: benchmark template

v11.2 — Code Quality + Docs:
- .clang-tidy: 15 check categories, 22 exclusions
- .github/workflows/static-analysis.yml: clang-tidy CI scan
- CODEOWNERS, SECURITY.md
- docs: API overview, testing guide, contributing guide
- README: module capability overview table

Pending: binary formats + curve projection (retrying)
2026-07-27 01:10:58 +08:00

226 lines
5.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// @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;
}
}