Tests and the rig for a default build without the C++ kernel

- step_in's a_solid_smlib_refuses_with_its_faces_is_refused_not_meshed assumed
  a build without SMLib has no kernel; on solidcore the cube imports, so it
  now runs only under SOLIDCRAFT_KERNEL=smlib and says it skipped otherwise.
- rounds_on_the_871_part and mitred_rounds_follow_a_moved_top compare with
  the C++ kernel (listed in tests/KNOWN_FAILING_TESTS) when it is built; their
  solidcore half runs as *_on_solidcore on a build without it, so each list
  entry is graded only where its comparison runs.
- kernel-cases without --cli builds the CLI once (with --features smlib when
  a run asks for the C++ kernel) before the cases, so the first cases don't
  spend their timeout compiling it.
- rustfmt for diagnostics.kernel's message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SdcgEtwSrdwZxqTQp5MfnU
This commit is contained in:
brett19
2026-11-02 12:30:22 -07:00
parent 29a148abd4
commit e30cfd2acf
5 changed files with 48 additions and 6 deletions
+4 -1
View File
@@ -78,7 +78,10 @@ pub(crate) fn kernel_asked(choice: &Value, built: bool) -> Result<solidcraft_ker
use solidcraft_kernel::kernel_route::Backend;
let asked = choice.as_str().and_then(Backend::from_id).ok_or_else(|| bad("diagnostics.kernel", "`choice` is solidcore or smlib"))?;
if asked == Backend::Smlib && !built {
return Err(EngineError::Disabled("diagnostics.kernel".into(), "this build doesn't include the C++ SMLib kernel; build with --features smlib".into()));
return Err(EngineError::Disabled(
"diagnostics.kernel".into(),
"this build doesn't include the C++ SMLib kernel; build with --features smlib".into(),
));
}
Ok(asked)
}
+9 -3
View File
@@ -540,12 +540,18 @@ fn offset_surface_cube_import_is_closed_and_editable() {
assert!(rel(measure(&result).unwrap().volume, 1000.0 - 40.0 * std::f64::consts::PI) < 1e-3);
}
/// A solid whose B-rep SMLib refuses, its faces too (here every SMLib call: the build has no
/// SMLib), is refused with the kernel's reason, naming the solid. It once came in as a mesh of
/// its faces, which the planner could still triangulate.
/// A solid whose B-rep SMLib refuses, its faces too (here every SMLib call: the C++ kernel is asked
/// for, SOLIDCRAFT_KERNEL=smlib, on a build without it), is refused with the kernel's reason, naming
/// the solid. It once came in as a mesh of its faces, which the planner could still triangulate.
/// On solidcore, the default, the cube imports, so there is nothing to refuse.
#[cfg(not(feature = "smlib"))]
#[test]
fn a_solid_smlib_refuses_with_its_faces_is_refused_not_meshed() {
use crate::kernel_route::{Backend, choice};
if choice() != Backend::Smlib {
eprintln!("skipped: needs SOLIDCRAFT_KERNEL=smlib on a build without the C++ kernel");
return;
}
let text = format!("{HEAD}{}#60=SHAPE_REPRESENTATION('',(#101),$);\n{TAIL}", cube_entities());
let why = step_import(&text).map(|imp| imp.warnings).unwrap_err().to_string();
assert!(why.contains("solid 'Cube': not imported: ") && why.contains("SMLib"), "{why}");
+13 -1
View File
@@ -929,10 +929,22 @@ fn edges_871() -> Vec<[f64; 3]> {
/// #871's rounds at r 0.5 fit (the wall between the window and the block's side is 1.26 thick):
/// 38 faces, and the closed form `issue_871_tests::rounds_that_fit_are_closed` derives. At r 1 they
/// overlap, which is refused. With SMLib built, the C++ kernel gives the same.
#[cfg(feature = "native")]
#[test]
fn rounds_on_the_871_part() {
#[cfg(feature = "native")]
let _cpp = crate::route::on_cpp();
rounds_on_the_871_part_check();
}
/// The same on a build without the C++ kernel: solidcore's half alone. A test of its own, so that
/// tests/KNOWN_FAILING_TESTS's entry for the C++ comparison (rounds_on_the_871_part) is graded only where it runs.
#[cfg(not(feature = "native"))]
#[test]
fn rounds_on_the_871_part_on_solidcore() {
rounds_on_the_871_part_check();
}
fn rounds_on_the_871_part_check() {
let p = part_871();
let e = edges_871();
let sizes = |r: f64| vec![r; e.len()];
+13 -1
View File
@@ -840,10 +840,22 @@ fn offset_faces_close_a_step_wall() {
/// solidcore refuses to put the rounds back (solidcore#2020, open): SolidCraft says it does not
/// make that move, where the C++ kernel gives the analytic value, also checked here. With SMLib
/// built, the C++ kernel gives the same at every other move.
#[cfg(feature = "native")]
#[test]
fn mitred_rounds_follow_a_moved_top() {
#[cfg(feature = "native")]
let _cpp = crate::route::on_cpp();
mitred_rounds_follow_a_moved_top_check();
}
/// The same on a build without the C++ kernel: solidcore's half alone. A test of its own, so that
/// tests/KNOWN_FAILING_TESTS's entry for the C++ comparison (mitred_rounds_follow_a_moved_top) is graded only where it runs.
#[cfg(not(feature = "native"))]
#[test]
fn mitred_rounds_follow_a_moved_top_on_solidcore() {
mitred_rounds_follow_a_moved_top_check();
}
fn mitred_rounds_follow_a_moved_top_check() {
use super::blend::{Corners, blend};
use crate::Blend;
let edges = [[20.0, 0.0, 10.0], [20.0, 30.0, 10.0], [0.0, 15.0, 10.0], [40.0, 15.0, 10.0]];
+9
View File
@@ -229,6 +229,15 @@ pub(crate) fn run_all(o: &Options, list: &[PathBuf]) -> Vec<Value> {
/// Every case on each backend, one job pool for all the runs; the results per backend, in order.
fn run_on(o: &Options, list: &[PathBuf], kernels: &[&str]) -> Vec<Vec<Value>> {
// Without --cli each case is `cargo run`: build the CLI once first, so the first cases don't
// spend their timeout compiling it (the C++ kernel's build most of all).
if o.cli.is_none() {
let mut c = cargo();
c.args(["build", "-q", "--release", "-p", "solidcraft-cli"]).args(cli_features(kernels));
if let Err(e) = c.status().map_err(|e| e.to_string()).and_then(|s| if s.success() { Ok(()) } else { Err(s.to_string()) }) {
eprintln!("kernel-cases: building solidcraft-cli failed ({e}); each case will say why");
}
}
let jobs = list.len() * kernels.len();
let next = Arc::new(Mutex::new(0usize));
let results = Arc::new(Mutex::new(vec![Value::Null; jobs]));