From f5257041923c26f18a3bc43e207b985f3d6cd5f0 Mon Sep 17 00:00:00 2001 From: Jonas Wrede Date: Mon, 12 Oct 2026 17:18:24 +0200 Subject: [PATCH] test: failing regression test for #268: Panic from truck-topology lib.rs:186 when joining struts that end on a bore wall (#283) * test: reproduce #268 (Panic from truck-topology lib.rs:186 when joining struts that end on a bore wall) * Sew refuses edges whose ends weld to one vertex (#268) The sewer welds vertices on a 1e-6 grid but only rejected edges shorter than 1e-9, so a sliver edge between the two welded its ends into one vertex and truck-topology panicked ("Two same vertices cannot construct an edge") inside the guard. Such an edge is now a degenerate-edge error before any truck call, and the boolean takes its usual fallback. Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: bherbruck Co-authored-by: Claude Opus 5.5 --- crates/engine/src/boolean_regression_tests.rs | 24 +++++++++++++++++++ crates/kernel/src/sew.rs | 3 ++- .../regressions/join_struts_on_bore_wall.json | 10 ++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 examples/regressions/join_struts_on_bore_wall.json diff --git a/crates/engine/src/boolean_regression_tests.rs b/crates/engine/src/boolean_regression_tests.rs index ccbb9a4b..20bcea16 100644 --- a/crates/engine/src/boolean_regression_tests.rs +++ b/crates/engine/src/boolean_regression_tests.rs @@ -64,3 +64,27 @@ fn oblique_cut_through_a_small_arc_matches_a_split() { assert!((got - above).abs() < 1e-6 * above, "{got} vs {above}"); } } + +/// Joining struts that end on a bore wall reached a truck-topology panic (#268). The guard caught it, +/// but no kernel call should panic at all (wasm aborts on a panic). +#[test] +fn struts_ending_on_a_bore_wall_join_without_a_panic() { + use std::sync::Arc; + use std::sync::atomic::{AtomicUsize, Ordering}; + let me = std::thread::current().id(); + let count = Arc::new(AtomicUsize::new(0)); + let c2 = count.clone(); + let prev = std::panic::take_hook(); + std::panic::set_hook(Box::new(move |_| { + if std::thread::current().id() == me { + c2.fetch_add(1, Ordering::SeqCst); + } + })); + let mut s = Session::default(); + let script: Value = serde_json::from_str(include_str!("../../../examples/regressions/join_struts_on_bore_wall.json")).unwrap(); + let result = s.run_script(&script); + std::panic::set_hook(prev); + assert_eq!(count.load(Ordering::SeqCst), 0, "kernel panics during the join"); + result.unwrap(); + assert_eq!(s.model.state().bodies.len(), 1); +} diff --git a/crates/kernel/src/sew.rs b/crates/kernel/src/sew.rs index 0d00d8c2..7c2b6692 100644 --- a/crates/kernel/src/sew.rs +++ b/crates/kernel/src/sew.rs @@ -363,7 +363,8 @@ fn sew_impl(faces: &[FaceSpec], touching: bool, sources: Option<&[Option