test(s3): add negative/boundary tests for H3/H4/H5/V5/V6
H3 (GaussBonnet suite, test_phase6.cpp):
- EnforceReturnsCorrectionMagnitude_LargeCorrection: feeds tetrahedron
with all theta_v=0, asserts returned correction is exactly 4pi.
- EnforceReturnsCorrectionMagnitude_NearZeroWhenAlreadyCorrect: angles
already satisfy GB, asserts correction near zero.
- EnforceRawMapOverload_ReturnsCorrection: verifies the raw-map overload
also returns the correction magnitude.
H4 (PeriodMatrix suite, test_phase7.cpp):
- ReduceToFD_ThrowsForRealAxisBoundary: the boundary Im(tau)==0.0 (real
axis) must throw domain_error, covering the <= guard's exact boundary.
H5 (NewtonSolver suite, test_newton_solver.cpp):
- Euclidean_SliverTriangle_CharacterizedBehavior: near-degenerate sliver
triangle (aspect ratio ~10000) — solver must not crash or NaN, and
must not report LinearSolverFailed (system is still consistent).
- Euclidean_ExactDegenerateTriangle_NoCrash: collinear vertices (zero
area) — euclidean_cot_weights returns {0,0,0,false}; asserts no crash
and that the reported status is a meaningful failure mode.
V5 (Serialization suite, test_layout.cpp):
- LoadResultXml_RejectsReformattedRootElement: <ConformalResult> with
geometry= on a separate line throws runtime_error.
- LoadResultXml_RejectsDOFVectorWithTagOpenOnSeparateLine: <DOFVector>
with '>' on a separate line throws runtime_error.
- LoadResultXml_CanonicalFormatStillWorks: regression guard confirming
save_result_xml canonical output still round-trips correctly.
V6 (Serialization suite, test_layout.cpp):
- CheckDofVectorSize_ThrowsOnMismatch: size 3 vs expected 5 throws.
- CheckDofVectorSize_PassesOnMatch: exact match does not throw.
- CheckDofVectorSize_ErrorMessageNamesExpectedAndActual: exception
message contains both the actual and expected sizes.
Total CGAL tests: 313 (up from 298; 15 new tests, 0 failures).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -137,6 +137,72 @@ TEST(GaussBonnet, ManuallySetAnalyticalTheta_PassesCheck)
|
||||
EXPECT_NO_THROW(check_gauss_bonnet(m, maps));
|
||||
}
|
||||
|
||||
// ════════════════════════════════════════════════════════════════════════════
|
||||
// H3 (test-coverage audit, 2026-06-01)
|
||||
//
|
||||
// Finding H3: enforce_gauss_bonnet was silent about the magnitude of the
|
||||
// correction it applied. The fix changes both overloads to return the total
|
||||
// absolute deficit |Σ(2π−Θ_v) − 2π·χ|. A large return value signals that
|
||||
// the input target angles were far from satisfying Gauss–Bonnet, so callers
|
||||
// can warn or refuse to proceed.
|
||||
//
|
||||
// These tests:
|
||||
// (a) verify the return value is large when the input angles are badly wrong;
|
||||
// (b) verify the return value is near-zero when the input is already correct;
|
||||
// (c) check both the raw-property-map overload and the Maps overload.
|
||||
// ════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
TEST(GaussBonnet, EnforceReturnsCorrectionMagnitude_LargeCorrection)
|
||||
{
|
||||
// H3 acceptance criterion: feed intentionally bad cone angles and assert
|
||||
// the reported correction is large.
|
||||
//
|
||||
// Tetrahedron (χ=2, V=4). Set all Θ_v = 0 (badly wrong: the correct
|
||||
// Gauss–Bonnet identity needs Σ(2π−Θ_v) = 4π, but with Θ_v=0 we get
|
||||
// Σ(2π−0) = 8π, so the deficit is 8π − 4π = 4π).
|
||||
auto m = make_tetrahedron();
|
||||
auto maps = setup_euclidean_maps(m);
|
||||
for (auto v : m.vertices()) maps.theta_v[v] = 0.0;
|
||||
|
||||
double correction = enforce_gauss_bonnet(m, maps);
|
||||
|
||||
// The total correction should equal |Σ(2π−0) − 2π·χ| = |8π − 4π| = 4π.
|
||||
EXPECT_NEAR(correction, 4.0 * M_PI, 1e-10)
|
||||
<< "enforce_gauss_bonnet should report a correction of 4π for"
|
||||
" a tetrahedron with all theta_v = 0";
|
||||
// And the deficit must now be zero.
|
||||
EXPECT_NEAR(gauss_bonnet_deficit(m, maps), 0.0, 1e-10);
|
||||
}
|
||||
|
||||
TEST(GaussBonnet, EnforceReturnsCorrectionMagnitude_NearZeroWhenAlreadyCorrect)
|
||||
{
|
||||
// H3: when the angles already satisfy Gauss–Bonnet, the correction is
|
||||
// near zero.
|
||||
auto m = make_triangle();
|
||||
auto maps = setup_euclidean_maps(m);
|
||||
// Set theta_v so the sum already equals 2π·χ = 2π exactly.
|
||||
// Triangle has 3 vertices; setting each to 4π/3 gives Σ(2π−4π/3)=3·(2π/3)=2π.
|
||||
for (auto v : m.vertices()) maps.theta_v[v] = 4.0 * M_PI / 3.0;
|
||||
|
||||
double correction = enforce_gauss_bonnet(m, maps);
|
||||
|
||||
EXPECT_NEAR(correction, 0.0, 1e-10)
|
||||
<< "enforce_gauss_bonnet should report near-zero correction when"
|
||||
" angles already satisfy Gauss–Bonnet";
|
||||
}
|
||||
|
||||
TEST(GaussBonnet, EnforceRawMapOverload_ReturnsCorrection)
|
||||
{
|
||||
// H3: the raw-property-map overload also returns the correction magnitude.
|
||||
auto m = make_quad_strip();
|
||||
auto maps = setup_euclidean_maps(m);
|
||||
// Default theta_v = 2π everywhere; sum = 0, rhs = 2π, deficit = -2π.
|
||||
// |deficit| = 2π.
|
||||
double correction = enforce_gauss_bonnet(m, maps.theta_v);
|
||||
EXPECT_NEAR(correction, 2.0 * M_PI, 1e-10)
|
||||
<< "Raw-map overload of enforce_gauss_bonnet should return |deficit|";
|
||||
}
|
||||
|
||||
// ════════════════════════════════════════════════════════════════════════════
|
||||
// GaussBonnet — HyperIdeal API guard (Finding-B from external-audit-2026-05-30)
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user