Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bb9c81069 | ||
|
|
cedb51b8ea | ||
|
|
9d82b94469 | ||
|
|
a9beb437b3 | ||
|
|
66d13059dd | ||
|
|
800ea40c0d | ||
|
|
20442eecd3 | ||
|
|
22d1cd7032 | ||
|
|
6a0dc18655 | ||
|
|
e006dbf1af | ||
|
|
8241a750fa | ||
|
|
41779cf7bb | ||
|
|
b01b9689c8 | ||
|
|
4426da6f5d | ||
|
|
5ead82e627 | ||
|
|
c29b0d2f13 | ||
|
|
480fd8d517 | ||
|
|
4c09fa5355 |
No files matched your search
@@ -3,7 +3,8 @@
|
||||
|
||||
[profile.ci]
|
||||
# Heavy tests (one to four minutes each on a CI runner) that pull requests skip. They run on
|
||||
# every push to main and nightly (`--ignore-default-filter`), and in `cargo xtask test`.
|
||||
# every push to main and nightly (`--ignore-default-filter`), and in `cargo xtask test`. The
|
||||
# boolean_props property tests run only nightly (ci.yml excludes them from pushes to main).
|
||||
# Keep this list in sync with docs/book/src/dev/testing.md and CONTRIBUTING.md.
|
||||
default-filter = """
|
||||
not (
|
||||
|
||||
@@ -229,7 +229,11 @@ jobs:
|
||||
run: |
|
||||
# Pull requests skip the heavy tests (default-filter in .config/nextest.toml).
|
||||
all=()
|
||||
if [ "$EVENT_NAME" != pull_request ]; then all=(--ignore-default-filter); fi
|
||||
# The boolean property tests draw new random inputs every run; they run only in the
|
||||
# nightly property-tests job, so a known kernel bug cannot turn main red at random.
|
||||
if [ "$EVENT_NAME" != pull_request ]; then
|
||||
all=(--ignore-default-filter -E 'not (package(solidcraft-kernel) & binary(boolean_props))')
|
||||
fi
|
||||
# Extract into ./target: tests that run a built binary (env!("CARGO_BIN_EXE_*")) have
|
||||
# the build job's path, which is the same checkout path here.
|
||||
cargo nextest run --archive-file tests.tar.zst --workspace-remap . --extract-to . --extract-overwrite \
|
||||
@@ -319,7 +323,8 @@ jobs:
|
||||
|
||||
property-tests:
|
||||
# The boolean property tests and the atomic command tests with many cases. Pull requests skip
|
||||
# them (.config/nextest.toml); pushes to main run them with small defaults (8 cases, seeds 0..4).
|
||||
# them (.config/nextest.toml); pushes to main run atomic_commands with small defaults (seeds
|
||||
# 0..4) and skip boolean_props, whose random inputs would fail main at random.
|
||||
name: Property tests (many cases)
|
||||
needs: build-tests
|
||||
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
|
||||
|
||||
+2
-1
@@ -181,7 +181,8 @@ Pull requests skip a few heavy tests (one to four minutes each), which run on ev
|
||||
`pattern_suppress_tests::enclosure_arc_extinction_keeps_a_real_sharp_inner_lip_after_resize_and_reopen`,
|
||||
`pattern_suppress_tests::enclosure_datums_follow_wall_height_and_board_depth_with_material_proofs`,
|
||||
`cmd::plastic::tests::enclosure_snap_fit_follows_resized_front_wall`, the `atomic_commands` contract tests
|
||||
- `solidcraft-kernel`: `tests::boolean_identity_on_tangent_primitives`, the `boolean_props` property tests
|
||||
- `solidcraft-kernel`: `tests::boolean_identity_on_tangent_primitives`, and the `boolean_props` property tests
|
||||
(these run only in the nightly "Property tests" job: their inputs are random, so main skips them too)
|
||||
- `solidcraft-ui-egui` scenarios: `acceptance_sensor_enclosure`
|
||||
|
||||
**The action matrix** tries every ordinary action on every face, edge, vertex and body of a
|
||||
|
||||
Generated
+15
-15
@@ -4051,7 +4051,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"block2 0.6.2",
|
||||
"eframe",
|
||||
@@ -4080,7 +4080,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-cli"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"image",
|
||||
"serde_json",
|
||||
@@ -4091,7 +4091,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-derive"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -4100,7 +4100,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-doc"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
@@ -4117,7 +4117,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-engine"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
@@ -4133,7 +4133,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-geom"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -4142,7 +4142,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-gpu"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"naga",
|
||||
@@ -4159,7 +4159,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-io"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"cadmpeg-core",
|
||||
"cadmpeg-ir",
|
||||
@@ -4178,7 +4178,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-kernel"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"proptest",
|
||||
@@ -4197,7 +4197,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-mcp"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"serde_json",
|
||||
"solidcraft-engine",
|
||||
@@ -4206,7 +4206,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-render"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"image",
|
||||
"moxcms",
|
||||
@@ -4219,7 +4219,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-sketch"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -4230,7 +4230,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-ui-egui"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"egui",
|
||||
"egui-wgpu",
|
||||
@@ -4251,7 +4251,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-web"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"eframe",
|
||||
"egui",
|
||||
@@ -5750,7 +5750,7 @@ checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7"
|
||||
|
||||
[[package]]
|
||||
name = "xtask"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"serde_json",
|
||||
"sha2 0.10.9",
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ members = ["crates/*", "apps/*", "xtask"]
|
||||
exclude = ["vendor"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
edition = "2024"
|
||||
license = "MIT OR Apache-2.0"
|
||||
rust-version = "1.95"
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -4,10 +4,13 @@
|
||||
//! inputs, and when a case fails it shrinks the inputs to a small case that still fails. Paste
|
||||
//! that case into a normal `#[test]` as a regression test.
|
||||
//!
|
||||
//! Case count: `PROPTEST_CASES` (default 8). Pull requests skip this file (.config/nextest.toml);
|
||||
//! pushes to main run it, and the nightly `property-tests` job uses more cases. A long local run:
|
||||
//! Case count: `PROPTEST_CASES` (default 8). Pull requests and pushes to main skip this file
|
||||
//! (.config/nextest.toml, .github/workflows/ci.yml): its random inputs differ on every run, so a
|
||||
//! known kernel bug would turn main red at random. The nightly `property-tests` job runs it with
|
||||
//! more cases. A long local run:
|
||||
//! `PROPTEST_CASES=2000 cargo test -p solidcraft-kernel --test boolean_props`.
|
||||
//! proptest saves every failing seed in `tests/boolean_props.proptest-regressions`. Commit it.
|
||||
//! proptest saves every failing seed in `tests/boolean_props.proptest-regressions`. Commit it, and
|
||||
//! copy the shrunk case into a `#[test]` below (ignored, with its issue, until the kernel is fixed).
|
||||
|
||||
use proptest::prelude::*;
|
||||
use solidcraft_geom::Vec3;
|
||||
@@ -102,7 +105,15 @@ fn cfg(default: u32) -> ProptestConfig {
|
||||
// The env var overrides the default; proptest reads PROPTEST_CASES itself only when the
|
||||
// config does not set `cases`, so read it here.
|
||||
let cases = std::env::var("PROPTEST_CASES").ok().and_then(|s| s.parse().ok()).unwrap_or(default);
|
||||
ProptestConfig { cases, max_shrink_iters: 200, ..ProptestConfig::default() }
|
||||
// Integration tests have no lib.rs or main.rs beside them, so proptest's default persistence
|
||||
// cannot place its file; name it.
|
||||
let file = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/boolean_props.proptest-regressions");
|
||||
ProptestConfig {
|
||||
cases,
|
||||
max_shrink_iters: 200,
|
||||
failure_persistence: Some(Box::new(prop::test_runner::FileFailurePersistence::Direct(file))),
|
||||
..ProptestConfig::default()
|
||||
}
|
||||
}
|
||||
|
||||
proptest! {
|
||||
@@ -218,3 +229,44 @@ proptest! {
|
||||
prop_assert!(close(run(&plate, &boss, BoolOp::Union)?, vp + vb, vp + vb), "plate + boss lost or gained volume");
|
||||
}
|
||||
}
|
||||
|
||||
// Cases the property tests found, as plain tests. Ignored until the kernel bug is fixed: run them
|
||||
// with `cargo test -p solidcraft-kernel --test boolean_props -- --ignored`.
|
||||
|
||||
fn check(r: Result<(), TestCaseError>) {
|
||||
if let Err(e) = r {
|
||||
panic!("{e}");
|
||||
}
|
||||
}
|
||||
|
||||
/// A box and a cylinder in general position: the intersect is refused as an implausible volume.
|
||||
#[test]
|
||||
#[ignore = "kernel bug, #1647"]
|
||||
fn generic_box_cylinder_intersect() {
|
||||
let a = Prim::Box { at: [11.483767761089219, 4.801612107504224, 3.6313476467611787], size: [4.789088988834864, 3.0, 10.419335961063835] };
|
||||
let b = Prim::Cyl { at: [29.2480632732879, 8.3683289461485, 6.947922225984966], axis: 2, r: 13.502884497756853, h: 19.719218725477496 };
|
||||
check(identity(&a, &b));
|
||||
}
|
||||
|
||||
/// A sphere and a box on the grid: the union has a face that does not mesh.
|
||||
#[test]
|
||||
#[ignore = "kernel bug, #1648"]
|
||||
fn grid_sphere_box_union_is_sound() {
|
||||
let a = Prim::Sph { at: [2.5, 15.0, 27.5], r: 12.5 };
|
||||
let b = Prim::Box { at: [0.0, 0.0, 17.5], size: [5.0, 7.5, 5.0] };
|
||||
check(identity(&a, &b));
|
||||
}
|
||||
|
||||
/// Two crossing cylinders: the union moved 1000 mm away loses about a tenth of its volume.
|
||||
#[test]
|
||||
#[ignore = "kernel bug, #1649"]
|
||||
fn crossing_cylinders_union_moved_far() {
|
||||
let a = Prim::Cyl { at: [17.5, 30.0, 7.5], axis: 0, r: 5.0, h: 10.0 }.body();
|
||||
let b = Prim::Cyl { at: [17.5, 30.0, 15.0], axis: 1, r: 12.5, h: 5.0 }.body();
|
||||
let t = Vec3::new(1000.0, -700.0, 300.0);
|
||||
let mv = |x: &Body| transform(x, t, Vec3::ZERO, Vec3::Z, 0.0).expect("translate");
|
||||
let s = vol(&a) + vol(&b);
|
||||
let here = run(&a, &b, BoolOp::Union).unwrap();
|
||||
let there = run(&mv(&a), &mv(&b), BoolOp::Union).unwrap();
|
||||
assert!(close(here, there, s), "union at origin {here:.4}, moved by 1000 gives {there:.4}");
|
||||
}
|
||||
@@ -81,7 +81,8 @@ Pull requests skip a few heavy tests (each takes one to four minutes); they run
|
||||
`pattern_suppress_tests::enclosure_arc_extinction_keeps_a_real_sharp_inner_lip_after_resize_and_reopen`,
|
||||
`pattern_suppress_tests::enclosure_datums_follow_wall_height_and_board_depth_with_material_proofs`,
|
||||
`cmd::plastic::tests::enclosure_snap_fit_follows_resized_front_wall`, the `atomic_commands` contract tests
|
||||
- `solidcraft-kernel`: `tests::boolean_identity_on_tangent_primitives`, the `boolean_props` property tests
|
||||
- `solidcraft-kernel`: `tests::boolean_identity_on_tangent_primitives`, and the `boolean_props` property tests
|
||||
(these run only in the nightly "Property tests" job: their inputs are random, so main skips them too)
|
||||
- `solidcraft-ui-egui` scenarios: `acceptance_sensor_enclosure`
|
||||
|
||||
The **action matrix** (`apps/solidcraft-cli/tests/action_matrix.rs`) tries every ordinary action
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"28": {"area":2394.691384,"bodies":1,"edges":15,"error":null,"faces":9,"outcome":"ok","rejected":0,"shells":2,"steps":["revolved section","join cylinder"],"unsupported":0,"volume":5902.121375},
|
||||
"29": {"area":6965.599057,"bodies":1,"edges":74,"error":null,"faces":30,"outcome":"ok","rejected":0,"shells":1,"steps":["extruded profile","shell","join cylinder"],"unsupported":0,"volume":3977.885339},
|
||||
"30": {"area":853.525389,"bodies":1,"edges":23,"error":null,"faces":10,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","chamfer"],"unsupported":0,"volume":1337.14821},
|
||||
"31": {"area":10198.42294,"bodies":3,"edges":67,"error":null,"faces":29,"outcome":"ok","rejected":1,"shells":3,"steps":["box","cut box","fillet","join box","fillet","circular pattern","cut box","circular pattern"],"unsupported":0,"volume":56408.3612},
|
||||
"31": {"area":10221.945046,"bodies":3,"edges":68,"error":null,"faces":29,"outcome":"ok","rejected":2,"shells":3,"steps":["box","cut box","fillet","join box","circular pattern","cut box","circular pattern","hole"],"unsupported":0,"volume":56397.581359},
|
||||
"32": {"area":3220.802769,"bodies":1,"edges":51,"error":null,"faces":19,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut sphere","cut box","cut box","join box"],"unsupported":0,"volume":7565.955897},
|
||||
"33": {"area":5286.736353,"bodies":2,"edges":59,"error":null,"faces":27,"outcome":"ok","rejected":0,"shells":3,"steps":["revolved section","fillet","join box","cut cylinder","chamfer","join box","chamfer","fillet"],"unsupported":2,"volume":13858.467983},
|
||||
"34": {"area":1086.305562,"bodies":1,"edges":30,"error":null,"faces":14,"outcome":"ok","rejected":0,"shells":1,"steps":["revolved section","cut sphere","hole"],"unsupported":0,"volume":2134.365275},
|
||||
@@ -84,7 +84,7 @@
|
||||
"80": {"area":8652.533342,"bodies":1,"edges":20,"error":null,"faces":9,"outcome":"ok","rejected":0,"shells":1,"steps":["box","fillet","fillet"],"unsupported":0,"volume":37387.449469},
|
||||
"81": {"area":4001.847983,"bodies":2,"edges":75,"error":null,"faces":29,"outcome":"ok","rejected":1,"shells":2,"steps":["revolved section","cut sphere","circular pattern","rectangular pattern","hole","join cylinder","join box","cut sphere"],"unsupported":2,"volume":13139.658749},
|
||||
"82": {"area":3195.487112,"bodies":1,"edges":30,"error":null,"faces":13,"outcome":"ok","rejected":0,"shells":1,"steps":["box","hole","circular pattern","cut box"],"unsupported":0,"volume":5902.162954},
|
||||
"83": {"area":8489.059183,"bodies":1,"edges":97,"error":null,"faces":35,"outcome":"ok","rejected":0,"shells":2,"steps":["box","join box","rectangular pattern","shell","fillet","cut sphere","join box"],"unsupported":1,"volume":6217.394627},
|
||||
"83": {"area":8632.834978,"bodies":1,"edges":95,"error":null,"faces":35,"outcome":"ok","rejected":0,"shells":2,"steps":["box","join box","rectangular pattern","shell","cut sphere","join box","fillet"],"unsupported":2,"volume":6339.218896},
|
||||
"84": {"area":4906.192237,"bodies":1,"edges":67,"error":null,"faces":25,"outcome":"ok","rejected":2,"shells":1,"steps":["extruded profile","fillet","hole","hole","cut cylinder","cut box","fillet"],"unsupported":0,"volume":14219.865875},
|
||||
"85": {"area":3309.210936,"bodies":1,"edges":57,"error":null,"faces":24,"outcome":"ok","rejected":1,"shells":2,"steps":["revolved section","fillet","cut sphere","circular pattern","join cylinder","hole","join box"],"unsupported":0,"volume":6904.455565},
|
||||
"86": {"area":7885.256491,"bodies":1,"edges":66,"error":"offset: a corner whose faces don't meet the same way after t","faces":28,"outcome":"failed","rejected":0,"shells":3,"steps":["extruded profile","join cylinder","join cylinder","circular pattern","rectangular pattern","shell"],"unsupported":2,"volume":21498.10695},
|
||||
@@ -125,6 +125,7 @@
|
||||
{"reason":"Seed 83 builds: a shell splits a saddle corner (convex and concave edges in turn) into two corners","seeds":[83]},
|
||||
{"reason":"seed 15 now cuts around a sealed void","seeds":[15]},
|
||||
{"reason":"#1490: when the last-resort nudge fails both ways, two more screw axes are tried; seed 63's final box join (its face 0.00005 mm off the half-ring's cut face) now builds instead of being refused with an implausible volume, and the design goes on to its fillet","seeds":[63]},
|
||||
{"reason":"a prism cut in a column round the tool (prism_local): seed 65's rectangular pattern (step 4, a second half-cylinder groove overlapping the first, in a block with a rounded vertical edge) is now built by the exact 2D route in a column clear of the round, where the B-rep tries left it with split edges. The step's part has the 10 faces, 24 edges and 16 vertices it should (28 edges and 18 vertices before), and its volume is 45145.383 mm³ against 45145.214 (exactly 45145.103, both within the mesh measure); the generator then picks other edges for its step 7 fillet, so the run ends on another design (45143.48 mm³, 15 faces)","seeds":[65]}
|
||||
{"reason":"a prism cut in a column round the tool (prism_local): seed 65's rectangular pattern (step 4, a second half-cylinder groove overlapping the first, in a block with a rounded vertical edge) is now built by the exact 2D route in a column clear of the round, where the B-rep tries left it with split edges. The step's part has the 10 faces, 24 edges and 16 vertices it should (28 edges and 18 vertices before), and its volume is 45145.383 mm³ against 45145.214 (exactly 45145.103, both within the mesh measure); the generator then picks other edges for its step 7 fillet, so the run ends on another design (45143.48 mm³, 15 faces)","seeds":[65]},
|
||||
{"reason":"Seed 31: #1581 no longer maps a pick on an earlier round's seam to some other nearby edge; the second fillet's selection includes the smooth seam at [2, 27.5, 13.5] beside the first round, which is now refused (no corner to round) instead of silently re-rounding a different edge at 1 mm, so the run goes on to a hole. Seed 83: #1316 was recorded before its branch took in #1495; with #1495's shell (an open face next to a concave edge no longer cuts the wall past it) the shelled part keeps more wall (6217 to 6339 mm3), its edges differ, and the 2.5 mm fillet of the first run is not picked; a later fillet is refused as not supported yet (an end face parallel to the edge)","seeds":[31,83]}
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user