#include #include "libslic3r/libslic3r.h" #include "libslic3r/GCode/GCodeProcessor.hpp" #include #include using namespace Slic3r; // Bambu firmware uses the " FEATURE: " style reserved tags, everything else the Slic3r-compatible // "TYPE:" style, so which list applies depends on the printer kind passed in. TEST_CASE("Reserved keyword detection follows the printer kind it is given", "[GCodeProcessor]") { struct Case { const char* name; std::string gcode; bool reserved_on_bbl; bool reserved_on_non_bbl; }; const auto test_case = GENERATE(values({ {"compatible feature tag", ";TYPE:Prime tower", false, true}, {"compatible layer tag", ";LAYER_CHANGE", false, true}, {"bbl feature tag", "; FEATURE: Outer wall", true, false}, {"tag shared by both lists", ";_GP_FIRST_LINE_M73_PLACEHOLDER", true, true}, {"bbl spells this one with a leading space", ";COLOR_CHANGE", false, true}, {"ordinary comment", "; heat the bed", false, false}, {"not a comment at all", "G1 X10 Y10 F3000", false, false}, // A tag counts only as the whole comment's prefix, so neither a tag mentioned mid-comment // nor one trailing a real command is a reserved use. {"tag text later in the comment", "; the TYPE:Prime tower marker", false, false}, {"tag trailing a command", "G1 X10 ;TYPE:Prime tower", false, false}, })); DYNAMIC_SECTION(test_case.name) { std::vector tags; REQUIRE(GCodeProcessor::contains_reserved_tags(test_case.gcode, 5, tags, true) == test_case.reserved_on_bbl); tags.clear(); REQUIRE(GCodeProcessor::contains_reserved_tags(test_case.gcode, 5, tags, false) == test_case.reserved_on_non_bbl); } } TEST_CASE("Reserved keyword detection reports every offending line", "[GCodeProcessor]") { const std::string gcode = ";TYPE:Prime tower\nG1 X10\n;LAYER_CHANGE\n"; std::vector tags; REQUIRE(GCodeProcessor::contains_reserved_tags(gcode, 5, tags, false)); REQUIRE(tags.size() == 2); // Reported in the order they appear, which is what makes the max_count cut-off meaningful. CHECK(tags[0] == "TYPE:Prime tower"); CHECK(tags[1] == "LAYER_CHANGE"); SECTION("the reported count is capped at max_count") { tags.clear(); REQUIRE(GCodeProcessor::contains_reserved_tags(gcode, 1, tags, false)); CHECK(tags.size() == 1); CHECK(tags[0] == "TYPE:Prime tower"); } SECTION("a max_count of zero still reports the first tag") { tags.clear(); REQUIRE(GCodeProcessor::contains_reserved_tags(gcode, 0, tags, false)); CHECK(tags.size() == 1); } SECTION("g-code with nothing reserved in it reports nothing") { tags.clear(); CHECK_FALSE(GCodeProcessor::contains_reserved_tags("G28\n; home all axes\n", 5, tags, false)); CHECK(tags.empty()); } }