Make this fork actually compile: first green Catch2 run in its history

206/206 targets built, 139 [CadDocument] cases / 1960 assertions passing —
identical to snaporca's suite. Until now this fork had never compiled at all:
CMake died at configure, so the M1-M8 "suite green" figures were snaporca's
alone and the ports rested on patch-apply plus byte-identical sources.

Three fixes here; the deps work is in the orcacad-deps image (see below).

1. kernel-test.sh mounts deps_src. pybind11 is vendored in-tree and CMakeLists
   requires its headers; without the mount the container fell back to the
   image's baked tree, which predates it.

2. tests/libslic3r/test_3mf.cpp: repair the upstream-merge conflict resolution.
   Resolving it as a union dropped the three closing braces of our SCENARIO, so
   upstream's SCENARIO opened inside ours ("a function-definition is not allowed
   here", plus 12 cascading catch2 registry errors). Restored from the pre-merge
   file; whole-file brace balance is now 0 and the case count reconciles as
   5 (ours) + 8 (upstream) - 3 (shared) = 10, with both CAD recipe tests intact.

3. tests/libslic3r/test_caddocument.cpp: REQUIRE_CONTAINS / CHECK_CONTAINS.
   Catch2 v2 (snaporca) spells substring-match Matchers::Contains; v3 (here)
   spells it ContainsSubstring and gives Contains an incompatible meaning,
   range-contains-ELEMENT, which fails to COMPILE against std::string. Four
   sites had been hand-adapted long ago, but M2-M8 kept porting in un-adapted
   Contains calls — 16 of them — and nothing objected because nothing compiled.
   Both forks now use the same find()-based macros, so the assertion lines are
   byte-identical again and future format-patch ports carry across unchanged.
   Five orphaned `using Catch::Matchers::Contains;` lines removed with them.

The deps gap that blocked configure needed five additions on top of
snaporca-deps, built into image orcacad-deps: Eigen 5.0.1, Python 3.12.13
(exact, with Development.Embed), wxWidgets 3.3.2 (was 3.1.5), CGAL 5.6.3
(was 5.4 — mainline's own MeshBoolean.cpp calls CGAL::parameters::default_values,
added in 5.5), plus the pybind11 mount above. OCCT V7_6_0, Boost 1.84.0 and
OpenCV 4.6.0 are pinned identically in both forks and were reused as-is.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tommaso Bianchi
2026-07-25 13:46:07 +02:00
co-authored by Claude Opus 5
parent 113e75e7b3
commit 1633005bba
3 changed files with 37 additions and 25 deletions
+1
View File
@@ -85,6 +85,7 @@ docker run --rm \
-v "$REPO/resources":/OrcaSlicer/resources \ -v "$REPO/resources":/OrcaSlicer/resources \
-v "$REPO/CMakeLists.txt":/OrcaSlicer/CMakeLists.txt \ -v "$REPO/CMakeLists.txt":/OrcaSlicer/CMakeLists.txt \
-v "$REPO/cmake":/OrcaSlicer/cmake \ -v "$REPO/cmake":/OrcaSlicer/cmake \
-v "$REPO/deps_src":/OrcaSlicer/deps_src \
-v "$VOL":/OrcaSlicer/build \ -v "$VOL":/OrcaSlicer/build \
"$IMAGE" \ "$IMAGE" \
bash -lc "set -e bash -lc "set -e
+4
View File
@@ -229,6 +229,10 @@ SCENARIO("CAD recipe is embedded in the BBS 3mf archive", "[3mf]") {
REQUIRE(got.size() == recipe.size()); REQUIRE(got.size() == recipe.size());
REQUIRE(got == recipe); REQUIRE(got == recipe);
} }
}
}
}
// .3mf multi-nozzle round-trip. // .3mf multi-nozzle round-trip.
// Locks the load/save handling for the H2C multi-nozzle plate metadata: // Locks the load/save handling for the H2C multi-nozzle plate metadata:
// * filament_volume_maps -> plate config "filament_volume_map" (with the >1 -> 0 clamp) // * filament_volume_maps -> plate config "filament_volume_map" (with the >1 -> 0 clamp)
+32 -25
View File
@@ -1,5 +1,17 @@
#include <catch2/catch_all.hpp> // mainline OrcaSlicer ships Catch2 v3 (v2 was catch2/catch.hpp) #include <catch2/catch_all.hpp> // mainline OrcaSlicer ships Catch2 v3 (v2 was catch2/catch.hpp)
// Substring assertions, spelled so this file compiles UNCHANGED on both forks.
// Catch2 v2 (snaporca) spells it Matchers::Contains; v3 (orca_cad / mainline) spells it
// Matchers::ContainsSubstring and gives Contains an incompatible meaning — range-contains-
// ELEMENT — which fails to compile against a std::string rather than failing a test.
// Using find() sidesteps the rename entirely; INFO keeps the actual string in the report.
#define REQUIRE_CONTAINS(str, sub) \
do { const std::string _actual = (str); INFO("actual: " << _actual); \
REQUIRE(_actual.find(sub) != std::string::npos); } while (0)
#define CHECK_CONTAINS(str, sub) \
do { const std::string _actual = (str); INFO("actual: " << _actual); \
CHECK(_actual.find(sub) != std::string::npos); } while (0)
#include "libslic3r/CadDocument.hpp" #include "libslic3r/CadDocument.hpp"
#include "libslic3r/GeometryEngine.hpp" #include "libslic3r/GeometryEngine.hpp"
#include "libslic3r/SketchEngine.hpp" #include "libslic3r/SketchEngine.hpp"
@@ -1996,7 +2008,7 @@ TEST_CASE("deserialize_recipe rejects future version with error", "[CadDocument]
} }
REQUIRE_FALSE(doc.deserialize_recipe(oss.str())); REQUIRE_FALSE(doc.deserialize_recipe(oss.str()));
REQUIRE_FALSE(doc.error.empty()); REQUIRE_FALSE(doc.error.empty());
CHECK_THAT(doc.error, Catch::Matchers::ContainsSubstring("newer version")); CHECK_CONTAINS(doc.error, "newer version");
} }
TEST_CASE("deserialize_recipe rejects older version with error", "[CadDocument]") TEST_CASE("deserialize_recipe rejects older version with error", "[CadDocument]")
@@ -2010,7 +2022,7 @@ TEST_CASE("deserialize_recipe rejects older version with error", "[CadDocument]"
} }
REQUIRE_FALSE(doc.deserialize_recipe(oss.str())); REQUIRE_FALSE(doc.deserialize_recipe(oss.str()));
REQUIRE_FALSE(doc.error.empty()); REQUIRE_FALSE(doc.error.empty());
CHECK_THAT(doc.error, Catch::Matchers::ContainsSubstring("older version")); CHECK_CONTAINS(doc.error, "older version");
} }
TEST_CASE("deserialize_recipe handles truncated blob without throwing", "[CadDocument]") TEST_CASE("deserialize_recipe handles truncated blob without throwing", "[CadDocument]")
@@ -2659,7 +2671,7 @@ TEST_CASE("helix: invalid inputs fail cleanly", "[CadDocument]")
std::string err; std::string err;
REQUIRE(doc.build_helix_wire(doc.features[0], err).IsNull()); REQUIRE(doc.build_helix_wire(doc.features[0], err).IsNull());
REQUIRE_FALSE(err.empty()); REQUIRE_FALSE(err.empty());
CHECK_THAT(err, Catch::Matchers::ContainsSubstring("flat spiral")); CHECK_CONTAINS(err, "flat spiral");
} }
SECTION("absurd turn count") { SECTION("absurd turn count") {
CadDocument doc; CadDocument doc;
@@ -2674,7 +2686,7 @@ TEST_CASE("helix: invalid inputs fail cleanly", "[CadDocument]")
std::string err; std::string err;
REQUIRE(doc.build_helix_wire(doc.features[0], err).IsNull()); REQUIRE(doc.build_helix_wire(doc.features[0], err).IsNull());
REQUIRE_FALSE(err.empty()); REQUIRE_FALSE(err.empty());
CHECK_THAT(err, Catch::Matchers::ContainsSubstring("negative")); CHECK_CONTAINS(err, "negative");
} }
} }
@@ -3970,7 +3982,6 @@ TEST_CASE("rib adds material to a box", "[CadDocument][rib]")
TEST_CASE("rib non-line entity rejected safely", "[CadDocument][rib]") TEST_CASE("rib non-line entity rejected safely", "[CadDocument][rib]")
{ {
using Catch::Matchers::Contains;
CadDocument doc; CadDocument doc;
int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 20, 20, 10, "Box"); int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 20, 20, 10, "Box");
@@ -3986,7 +3997,7 @@ TEST_CASE("rib non-line entity rejected safely", "[CadDocument][rib]")
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_FALSE(doc.error.empty()); REQUIRE_FALSE(doc.error.empty());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("rib")); REQUIRE_CONTAINS(doc.error, "rib");
} }
TEST_CASE("rib round-trip serialization", "[CadDocument][rib]") TEST_CASE("rib round-trip serialization", "[CadDocument][rib]")
@@ -4207,7 +4218,7 @@ TEST_CASE("delete_face with bad face index fails safely", "[CadDocument][deletef
doc.add_delete_face(0, {9999}, "Bad"); doc.add_delete_face(0, {9999}, "Bad");
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("face")); REQUIRE_CONTAINS(doc.error, "face");
} }
TEST_CASE("delete_face round-trip serialization", "[CadDocument][deleteface]") TEST_CASE("delete_face round-trip serialization", "[CadDocument][deleteface]")
@@ -4341,7 +4352,7 @@ TEST_CASE("hole: standards table lookup", "[CadDocument][hole]")
try { try {
doc.add_hole_standard("M999", 0, true, 10, 0, 0, SketchPlane::XY(), "H"); doc.add_hole_standard("M999", 0, true, 10, 0, 0, SketchPlane::XY(), "H");
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
CHECK_THAT(std::string(ex.what()), Catch::Matchers::Contains("standard")); CHECK_CONTAINS(std::string(ex.what()), "standard");
} }
} }
@@ -4464,7 +4475,7 @@ TEST_CASE("cycle detected fails recompute with error", "[CadDocument][variables]
doc.variables = {{"a", "b"}, {"b", "a"}}; doc.variables = {{"a", "b"}, {"b", "a"}};
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("cycle")); REQUIRE_CONTAINS(doc.error, "cycle");
} }
TEST_CASE("unknown parameter fails recompute", "[CadDocument][variables]") TEST_CASE("unknown parameter fails recompute", "[CadDocument][variables]")
@@ -4476,7 +4487,7 @@ TEST_CASE("unknown parameter fails recompute", "[CadDocument][variables]")
doc.features[sk].expr = {{"nope", "1"}}; doc.features[sk].expr = {{"nope", "1"}};
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("unknown parameter")); REQUIRE_CONTAINS(doc.error, "unknown parameter");
} }
TEST_CASE("unknown identifier fails recompute", "[CadDocument][variables]") TEST_CASE("unknown identifier fails recompute", "[CadDocument][variables]")
@@ -4489,7 +4500,7 @@ TEST_CASE("unknown identifier fails recompute", "[CadDocument][variables]")
doc.variables = {{"x", "y+1"}}; doc.variables = {{"x", "y+1"}};
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("unknown identifier")); REQUIRE_CONTAINS(doc.error, "unknown identifier");
} }
TEST_CASE("parametric recipe round-trips through serialize/deserialize", "[CadDocument][variables]") TEST_CASE("parametric recipe round-trips through serialize/deserialize", "[CadDocument][variables]")
@@ -4607,7 +4618,7 @@ TEST_CASE("surface-extrude bad ref safe", "[CadDocument][surface]")
int fi = doc.add_surface_extrude(999, 10, "Bad"); int fi = doc.add_surface_extrude(999, 10, "Bad");
REQUIRE(fi == 0); REQUIRE(fi == 0);
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("surface-extrude")); REQUIRE_CONTAINS(doc.error, "surface-extrude");
} }
TEST_CASE("surface round-trip serialize/deserialize", "[CadDocument][surface]") TEST_CASE("surface round-trip serialize/deserialize", "[CadDocument][surface]")
@@ -4730,7 +4741,7 @@ TEST_CASE("thicken-surface on non-sheet fails", "[CadDocument][surface]")
doc.add_thicken_surface(0, 2.0, false, "Bad"); doc.add_thicken_surface(0, 2.0, false, "Bad");
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("sheet")); REQUIRE_CONTAINS(doc.error, "sheet");
} }
TEST_CASE("thicken-surface round-trip serialize/deserialize", "[CadDocument][surface]") TEST_CASE("thicken-surface round-trip serialize/deserialize", "[CadDocument][surface]")
@@ -4839,13 +4850,13 @@ TEST_CASE("surface-loft / surface-fill bad refs safe", "[CadDocument][surface]")
CadDocument doc; CadDocument doc;
doc.add_surface_loft({999}, false, "Bad"); doc.add_surface_loft({999}, false, "Bad");
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("surface-loft")); REQUIRE_CONTAINS(doc.error, "surface-loft");
} }
{ {
CadDocument doc; CadDocument doc;
doc.add_surface_fill(999, "Bad"); doc.add_surface_fill(999, "Bad");
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("surface-fill")); REQUIRE_CONTAINS(doc.error, "surface-fill");
} }
} }
@@ -5135,7 +5146,6 @@ TEST_CASE("mate round-trip serialization", "[CadDocument][mate]")
TEST_CASE("version 2 blob is rejected", "[CadDocument][mate]") TEST_CASE("version 2 blob is rejected", "[CadDocument][mate]")
{ {
using Catch::Matchers::Contains;
CadDocument doc; CadDocument doc;
int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 10, 10, 0, "Box"); int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 10, 10, 0, "Box");
@@ -5155,12 +5165,11 @@ TEST_CASE("version 2 blob is rejected", "[CadDocument][mate]")
CadDocument fresh; CadDocument fresh;
REQUIRE_FALSE(fresh.deserialize_recipe(blob)); REQUIRE_FALSE(fresh.deserialize_recipe(blob));
REQUIRE_THAT(fresh.error, Catch::Matchers::Contains("older version")); REQUIRE_CONTAINS(fresh.error, "older version");
} }
TEST_CASE("mate error: out of range connectors", "[CadDocument][mate]") TEST_CASE("mate error: out of range connectors", "[CadDocument][mate]")
{ {
using Catch::Matchers::Contains;
CadDocument doc; CadDocument doc;
int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 10, 10, 0, "Box"); int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 10, 10, 0, "Box");
@@ -5175,23 +5184,22 @@ TEST_CASE("mate error: out of range connectors", "[CadDocument][mate]")
doc.add_mate(0, 999, cs, 0, 0, false, "Bad"); doc.add_mate(0, 999, cs, 0, 0, false, "Bad");
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("mate_cs_a out of range")); REQUIRE_CONTAINS(doc.error, "mate_cs_a out of range");
doc.features.pop_back(); doc.error.clear(); doc.features.pop_back(); doc.error.clear();
doc.add_mate(0, cs, 999, 0, 0, false, "Bad"); doc.add_mate(0, cs, 999, 0, 0, false, "Bad");
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("mate_cs_b out of range")); REQUIRE_CONTAINS(doc.error, "mate_cs_b out of range");
doc.features.pop_back(); doc.error.clear(); doc.features.pop_back(); doc.error.clear();
doc.add_mate(0, sk, cs, 0, 0, false, "Bad"); doc.add_mate(0, sk, cs, 0, 0, false, "Bad");
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("not a valid CoordSys")); REQUIRE_CONTAINS(doc.error, "not a valid CoordSys");
doc.features.pop_back(); doc.error.clear(); doc.features.pop_back(); doc.error.clear();
} }
TEST_CASE("mate error: no associated body", "[CadDocument][mate]") TEST_CASE("mate error: no associated body", "[CadDocument][mate]")
{ {
using Catch::Matchers::Contains;
CadDocument doc; CadDocument doc;
int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 10, 10, 0, "Box"); int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 10, 10, 0, "Box");
@@ -5210,12 +5218,11 @@ TEST_CASE("mate error: no associated body", "[CadDocument][mate]")
doc.add_mate(0, cs_fixed, cs_moving, 0, 0, false, "Bad"); doc.add_mate(0, cs_fixed, cs_moving, 0, 0, false, "Bad");
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("no associated body")); REQUIRE_CONTAINS(doc.error, "no associated body");
} }
TEST_CASE("mate error: disabled connector", "[CadDocument][mate]") TEST_CASE("mate error: disabled connector", "[CadDocument][mate]")
{ {
using Catch::Matchers::Contains;
CadDocument doc; CadDocument doc;
int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 10, 10, 0, "Box"); int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 10, 10, 0, "Box");
@@ -5234,7 +5241,7 @@ TEST_CASE("mate error: disabled connector", "[CadDocument][mate]")
doc.add_mate(0, cs_fixed, cs_moving, 0, 0, false, "Bad"); doc.add_mate(0, cs_fixed, cs_moving, 0, 0, false, "Bad");
REQUIRE_FALSE(doc.recompute()); REQUIRE_FALSE(doc.recompute());
REQUIRE_THAT(doc.error, Catch::Matchers::Contains("not a valid CoordSys")); REQUIRE_CONTAINS(doc.error, "not a valid CoordSys");
} }
TEST_CASE("ordering: fillet after mate resolves face ids", "[CadDocument][mate]") TEST_CASE("ordering: fillet after mate resolves face ids", "[CadDocument][mate]")