mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-31 06:42:07 +00:00
Merge branch 'main' into feature/h2c_support_clean
This commit is contained in:
@@ -85,3 +85,22 @@ TEST_CASE("Per-object wall filament override is honored", "[MultiFilament]")
|
||||
CHECK(tools_for_role(gcode, "perimeter") == std::set<int>{ 0, 1 });
|
||||
CHECK(tools_for_role(gcode, "infill") == std::set<int>{ 0 }); // infill not overridden: stays on F1
|
||||
}
|
||||
|
||||
// max_layer_height can be shorter than the extruder count (normalization sizes it to the
|
||||
// filament count under single_extruder_multi_material). calc_max_layer_height() in ToolOrdering
|
||||
// indexed it per-nozzle and read past the end. Shortened directly here to isolate that read;
|
||||
// the other per-extruder keys stay extruder-length so slicing reaches the code under test.
|
||||
TEST_CASE("Multi-extruder slice stays in bounds with a short max_layer_height", "[MultiFilament]")
|
||||
{
|
||||
DynamicPrintConfig config = multifilament_config(2);
|
||||
config.set_deserialize_strict({
|
||||
{ "nozzle_diameter", "0.4,0.4" },
|
||||
{ "printer_extruder_id", "1,2" },
|
||||
{ "printer_extruder_variant", "Direct Drive Standard,Direct Drive Standard" },
|
||||
{ "extruder_printable_height", "0,0" },
|
||||
{ "max_layer_height", "0.3" }, // deliberately one entry short
|
||||
});
|
||||
Print print;
|
||||
init_and_process_print({ cube(20) }, print, config);
|
||||
REQUIRE_FALSE(print.objects().front()->layers().empty());
|
||||
}
|
||||
|
||||
@@ -93,3 +93,14 @@ SCENARIO("Support layer Z honors contact distance", "[SupportMaterial]")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// extrude_support once held a `static` lambda capturing `this`, so a second export in the
|
||||
// same process dereferenced a returned stack frame (ASan: stack-use-after-return).
|
||||
TEST_CASE("Support G-code emission survives a second slice in the same process", "[SupportMaterial][Regression]")
|
||||
{
|
||||
const std::string first = slice({ TestMesh::overhang }, { { "enable_support", 1 } });
|
||||
REQUIRE(! layers_with_role(first, "support").empty());
|
||||
|
||||
const std::string second = slice({ TestMesh::overhang }, { { "enable_support", 1 } });
|
||||
REQUIRE(! layers_with_role(second, "support").empty());
|
||||
}
|
||||
|
||||
@@ -52,6 +52,11 @@ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") {
|
||||
SECTION("math: round(-13.4)") { REQUIRE(parser.process("{round(-13.4)}") == "-13"); }
|
||||
SECTION("math: round(13.6)") { REQUIRE(parser.process("{round(13.6)}") == "14"); }
|
||||
SECTION("math: round(-13.6)") { REQUIRE(parser.process("{round(-13.6)}") == "-14"); }
|
||||
SECTION("math: round(13.5)") { REQUIRE(parser.process("{round(13.5)}") == "14"); }
|
||||
SECTION("math: floor(13.9)") { REQUIRE(parser.process("{floor(13.9)}") == "13"); }
|
||||
SECTION("math: floor(-13.1)") { REQUIRE(parser.process("{floor(-13.1)}") == "-14"); }
|
||||
SECTION("math: ceil(13.1)") { REQUIRE(parser.process("{ceil(13.1)}") == "14"); }
|
||||
SECTION("math: ceil(-13.9)") { REQUIRE(parser.process("{ceil(-13.9)}") == "-13"); }
|
||||
SECTION("math: digits(5, 15)") { REQUIRE(parser.process("{digits(5, 15)}") == " 5"); }
|
||||
SECTION("math: digits(5., 15)") { REQUIRE(parser.process("{digits(5., 15)}") == " 5"); }
|
||||
SECTION("math: zdigits(5, 15)") { REQUIRE(parser.process("{zdigits(5, 15)}") == "000000000000005"); }
|
||||
@@ -65,6 +70,8 @@ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") {
|
||||
SECTION("math: interpolate_table(13.84375892476, (0, 0), (20, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(13.84375892476, (0, 0), (20, 20))}")) == Catch::Approx(13.84375892476)); }
|
||||
SECTION("math: interpolate_table(13, (0, 0), (20, 20), (30, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(13, (0, 0), (20, 20), (30, 20))}")) == Catch::Approx(13.)); }
|
||||
SECTION("math: interpolate_table(25, (0, 0), (20, 20), (30, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(25, (0, 0), (20, 20), (30, 20))}")) == Catch::Approx(20.)); }
|
||||
// Only the grammar's built-in functions are callable; any other name is an undefined variable and throws.
|
||||
SECTION("math: a non-built-in function name throws") { REQUIRE_THROWS(parser.process("{sqrt(16)}")); }
|
||||
|
||||
// regex_replace(subject, /pattern/, replacement): the string-transform primitive.
|
||||
SECTION("regex_replace: strips a file extension") { REQUIRE(parser.process("{regex_replace(\"part.stl\", /\\.[^.]*$/, \"\")}") == "part"); }
|
||||
|
||||
Reference in New Issue
Block a user