diff --git a/tests/kernel-cases/README.md b/tests/kernel-cases/README.md index 709ec90c06..aeb5502466 100644 --- a/tests/kernel-cases/README.md +++ b/tests/kernel-cases/README.md @@ -37,6 +37,8 @@ One directory per area, one per case: `tests/kernel-cases///`. | `crashes` (crashes and hangs inside kernel operations) | booleans/shell/import/crash rig | | `fillets`, `sweeps`, `threads`, `sheet-metal`, `tessellation` | history rig | | `continuity` (designed seams of known order, G0 to G4, that prove the continuity measurement itself) | history rig | +| `solids` (cones, scale, align, bounding solids) | tool coverage | +| `frames` (frame members, inserted profiles) | tool coverage | Each area also has its gate files: `KNOWN_FAILING` and `PATHS` (see [the gate](#the-kernel-rig-gate)). diff --git a/tests/kernel-cases/frames/KNOWN_FAILING b/tests/kernel-cases/frames/KNOWN_FAILING new file mode 100644 index 0000000000..f1ab5c3aab --- /dev/null +++ b/tests/kernel-cases/frames/KNOWN_FAILING @@ -0,0 +1,4 @@ +# The frames cases that fail today, one a line: ` `. Sorted. A run with +# `--known-failing` fails on a case that fails and is not listed here, and on a listed case that +# passes: a fix removes its line in the same pull request. +# Baseline: rig-cases-solids-frames 45f69c0e5 with SMLib 60b1c6a, aarch64 Linux. diff --git a/tests/kernel-cases/frames/PATHS b/tests/kernel-cases/frames/PATHS new file mode 100644 index 0000000000..f09de15ae3 --- /dev/null +++ b/tests/kernel-cases/frames/PATHS @@ -0,0 +1,9 @@ +# Source files whose change must rerun the frames area (frame members, inserted profiles). +apps/solidcraft-cli/src/kernel_cases.rs +crates/doc/src/eval_frame.rs +crates/doc/src/frame.rs +crates/engine/src/cmd/frame.rs +crates/engine/src/cmd/sketch.rs +crates/kernel/src/** +crates/smlib/** +tests/kernel-cases/frames/** diff --git a/tests/kernel-cases/frames/cov-frame-member-bar-along-x/expected.json b/tests/kernel-cases/frames/cov-frame-member-bar-along-x/expected.json new file mode 100644 index 0000000000..1ad1fdad04 --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-member-bar-along-x/expected.json @@ -0,0 +1,22 @@ +{ + "sources": [], + "what": "a 20x10 bar member along a 100 mm line on X", + "source": "analytic", + "method": "along +X the profile's y is world up (Z) and x = y x d = world Y; centred on the line (anchor origin = the bar's centre): x 0..100, y -10..10, z -5..5; V = 20000, A = 2(2000+1000+200)", + "body_count": 1, + "faces": 6, + "volume_mm3": 20000.0, + "area_mm2": 6400.0, + "bbox": { + "min": [ + 0, + -10, + -5 + ], + "max": [ + 100, + 10, + 5 + ] + } +} diff --git a/tests/kernel-cases/frames/cov-frame-member-bar-along-x/recipe.json b/tests/kernel-cases/frames/cov-frame-member-bar-along-x/recipe.json new file mode 100644 index 0000000000..92e9fa692f --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-member-bar-along-x/recipe.json @@ -0,0 +1,47 @@ +{ + "commands": [ + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Frame" + } + }, + { + "command": "sketch.line", + "params": { + "points": [ + [ + 0, + 0 + ], + [ + 100, + 0 + ] + ], + "ids": [ + "l1" + ], + "infer": false + } + }, + { + "command": "sketch.finish", + "params": { + "sketch": "Frame" + } + }, + { + "command": "frame.member", + "params": { + "sketch": "Frame", + "profile": { + "kind": "bar", + "width": 20, + "height": 10 + } + } + } + ] +} diff --git a/tests/kernel-cases/frames/cov-frame-member-tube-post-at-its-corner/expected.json b/tests/kernel-cases/frames/cov-frame-member-tube-post-at-its-corner/expected.json new file mode 100644 index 0000000000..7960647301 --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-member-tube-post-at-its-corner/expected.json @@ -0,0 +1,21 @@ +{ + "sources": [], + "what": "a vertical rectangular tube 40x30x3 (sharp corners) on a 50 mm line, anchored at the profile's bottom left corner", + "source": "analytic", + "method": "a vertical member's x is world X, y = d x X = world Y; the bottom left corner on the line: x 0..40, y 0..30, z 0..50; section 40*30 - 34*24 = 384, V = 19200; faces 4 outside + 4 inside + 2 ends", + "body_count": 1, + "faces": 10, + "volume_mm3": 19200.0, + "bbox": { + "min": [ + 0, + 0, + 0 + ], + "max": [ + 40, + 30, + 50 + ] + } +} diff --git a/tests/kernel-cases/frames/cov-frame-member-tube-post-at-its-corner/recipe.json b/tests/kernel-cases/frames/cov-frame-member-tube-post-at-its-corner/recipe.json new file mode 100644 index 0000000000..bb1f4333b0 --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-member-tube-post-at-its-corner/recipe.json @@ -0,0 +1,66 @@ +{ + "commands": [ + { + "command": "sketch.create", + "params": { + "plane": { + "origin": [ + 0, + 0, + 0 + ], + "x_dir": [ + 1, + 0, + 0 + ], + "y_dir": [ + 0, + 0, + 1 + ] + }, + "name": "Post" + } + }, + { + "command": "sketch.line", + "params": { + "points": [ + [ + 0, + 0 + ], + [ + 0, + 50 + ] + ], + "ids": [ + "l1" + ], + "infer": false + } + }, + { + "command": "sketch.finish", + "params": { + "sketch": "Post" + } + }, + { + "command": "frame.member", + "params": { + "sketch": "Post", + "profile": { + "kind": "rect_tube", + "width": 40, + "height": 30, + "wall": 3, + "outer_radius": 0 + }, + "anchor": "bottom_left" + } + } + ] +} diff --git a/tests/kernel-cases/frames/cov-frame-member-tube-wall-too-thick-refused/expected.json b/tests/kernel-cases/frames/cov-frame-member-tube-wall-too-thick-refused/expected.json new file mode 100644 index 0000000000..3d775625d3 --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-member-tube-wall-too-thick-refused/expected.json @@ -0,0 +1,8 @@ +{ + "sources": [], + "what": "a 40x40 tube with a 20 mm wall has no hole: refused", + "source": "analytic", + "method": "the wall must be under half the smaller side (20): a clean refusal naming it", + "outcome": "refused", + "refusal": "must be less than half the smaller side" +} diff --git a/tests/kernel-cases/frames/cov-frame-member-tube-wall-too-thick-refused/recipe.json b/tests/kernel-cases/frames/cov-frame-member-tube-wall-too-thick-refused/recipe.json new file mode 100644 index 0000000000..0da9066ceb --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-member-tube-wall-too-thick-refused/recipe.json @@ -0,0 +1,48 @@ +{ + "commands": [ + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Frame" + } + }, + { + "command": "sketch.line", + "params": { + "points": [ + [ + 0, + 0 + ], + [ + 100, + 0 + ] + ], + "ids": [ + "l1" + ], + "infer": false + } + }, + { + "command": "sketch.finish", + "params": { + "sketch": "Frame" + } + }, + { + "command": "frame.member", + "params": { + "sketch": "Frame", + "profile": { + "kind": "rect_tube", + "width": 40, + "height": 40, + "wall": 20 + } + } + } + ] +} diff --git a/tests/kernel-cases/frames/cov-frame-member-two-lines-two-bodies/expected.json b/tests/kernel-cases/frames/cov-frame-member-two-lines-two-bodies/expected.json new file mode 100644 index 0000000000..1a7ec0eff6 --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-member-two-lines-two-bodies/expected.json @@ -0,0 +1,20 @@ +{ + "sources": [], + "what": "round bar members d10 on two lines meeting at a corner: one body per line", + "source": "analytic", + "method": "each member a cylinder r5 the line's length: 25 pi (100 + 50); two bodies (they overlap at the corner, kept apart)", + "body_count": 2, + "volume_mm3": 11780.972450961724, + "bbox": { + "min": [ + -5, + -5, + -5 + ], + "max": [ + 100, + 50, + 5 + ] + } +} diff --git a/tests/kernel-cases/frames/cov-frame-member-two-lines-two-bodies/recipe.json b/tests/kernel-cases/frames/cov-frame-member-two-lines-two-bodies/recipe.json new file mode 100644 index 0000000000..ce4e42bf23 --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-member-two-lines-two-bodies/recipe.json @@ -0,0 +1,65 @@ +{ + "commands": [ + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Frame" + } + }, + { + "command": "sketch.line", + "params": { + "points": [ + [ + 0, + 0 + ], + [ + 100, + 0 + ] + ], + "ids": [ + "l1" + ], + "infer": false + } + }, + { + "command": "sketch.line", + "params": { + "points": [ + [ + 0, + 0 + ], + [ + 0, + 50 + ] + ], + "ids": [ + "l2" + ], + "infer": false + } + }, + { + "command": "sketch.finish", + "params": { + "sketch": "Frame" + } + }, + { + "command": "frame.member", + "params": { + "sketch": "Frame", + "profile": { + "kind": "round_bar", + "diameter": 10 + } + } + } + ] +} diff --git a/tests/kernel-cases/frames/cov-frame-profile-insert-channel-anchored-and-turned/expected.json b/tests/kernel-cases/frames/cov-frame-profile-insert-channel-anchored-and-turned/expected.json new file mode 100644 index 0000000000..26fe9f9dfe --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-profile-insert-channel-anchored-and-turned/expected.json @@ -0,0 +1,21 @@ +{ + "sources": [], + "what": "a channel profile 60x30 (web 5, flanges 6, sharp) inserted at (10,10) by its bottom left corner and turned 90 deg", + "source": "analytic", + "method": "section 2*30*6 + 5*48 = 600, V = 12000 at 20 deep; bounding box 30 wide, 60 high from its corner, turned 90 deg ccw about it: x 10-60..10, y 10..40", + "body_count": 1, + "faces": 10, + "volume_mm3": 12000.0, + "bbox": { + "min": [ + -50, + 10, + 0 + ], + "max": [ + 10, + 40, + 20 + ] + } +} diff --git a/tests/kernel-cases/frames/cov-frame-profile-insert-channel-anchored-and-turned/recipe.json b/tests/kernel-cases/frames/cov-frame-profile-insert-channel-anchored-and-turned/recipe.json new file mode 100644 index 0000000000..912be5bd3e --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-profile-insert-channel-anchored-and-turned/recipe.json @@ -0,0 +1,44 @@ +{ + "commands": [ + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Section" + } + }, + { + "command": "frame.profile.insert", + "params": { + "profile": { + "kind": "channel", + "height": 60, + "width": 30, + "web": 5, + "flange": 6, + "root_radius": 0, + "toe_radius": 0 + }, + "at": [ + 10, + 10 + ], + "anchor": "bottom_left", + "angle": 1.5707963267948966 + } + }, + { + "command": "sketch.finish", + "params": { + "sketch": "Section" + } + }, + { + "command": "solid.extrude", + "params": { + "sketch": "Section", + "distance": 20 + } + } + ] +} diff --git a/tests/kernel-cases/frames/cov-frame-profile-insert-i-beam-extruded/expected.json b/tests/kernel-cases/frames/cov-frame-profile-insert-i-beam-extruded/expected.json new file mode 100644 index 0000000000..79c717bd15 --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-profile-insert-i-beam-extruded/expected.json @@ -0,0 +1,21 @@ +{ + "sources": [], + "what": "an I-beam profile (100x50, web 4.5, flanges 7, sharp roots) inserted into a sketch and extruded 100", + "source": "analytic", + "method": "section 2*50*7 + 4.5*(100-14) = 1087, centred on the origin: V = 108700; faces 12 sides + 2 ends", + "body_count": 1, + "faces": 14, + "volume_mm3": 108700.0, + "bbox": { + "min": [ + -25, + -50, + 0 + ], + "max": [ + 25, + 50, + 100 + ] + } +} diff --git a/tests/kernel-cases/frames/cov-frame-profile-insert-i-beam-extruded/recipe.json b/tests/kernel-cases/frames/cov-frame-profile-insert-i-beam-extruded/recipe.json new file mode 100644 index 0000000000..b206d837f2 --- /dev/null +++ b/tests/kernel-cases/frames/cov-frame-profile-insert-i-beam-extruded/recipe.json @@ -0,0 +1,37 @@ +{ + "commands": [ + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Section" + } + }, + { + "command": "frame.profile.insert", + "params": { + "profile": { + "kind": "i_beam", + "height": 100, + "width": 50, + "web": 4.5, + "flange": 7, + "root_radius": 0 + } + } + }, + { + "command": "sketch.finish", + "params": { + "sketch": "Section" + } + }, + { + "command": "solid.extrude", + "params": { + "sketch": "Section", + "distance": 100 + } + } + ] +}