From 6ed688dfc552f1ccfeae14c4c700eabd3366b86f Mon Sep 17 00:00:00 2001 From: Clifford Garwood Date: Wed, 22 Apr 2026 17:14:18 -0400 Subject: [PATCH] test(preset): regression test for child>parent variant-vector truncation Adds a Catch2 scenario that builds a 2-extruder child DynamicPrintConfig inheriting from a 1-extruder parent, calls update_non_diff_values_to_base_config through the real printer_options_with_variant_1 / _2 key sets, and asserts that printer_extruder_id, printer_extruder_variant, and retraction_length retain their full size after the merge. Covers three distinct set_with_restore instantiations (Ints, Strings, Floats) and verifies both size preservation and per-extruder value preservation. Verified load-bearing: with the guard in update_non_diff_values_to_base_config temporarily removed, the test fails with "1 == 2" on pe_id.values.size() and retraction_length.values.size(); with the guard restored, all six assertions pass. Co-Authored-By: Claude Opus 4.7 --- tests/libslic3r/test_config.cpp | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/libslic3r/test_config.cpp b/tests/libslic3r/test_config.cpp index 5591842c64..2bee0d7d11 100644 --- a/tests/libslic3r/test_config.cpp +++ b/tests/libslic3r/test_config.cpp @@ -265,6 +265,56 @@ SCENARIO("DynamicPrintConfig serialization", "[Config]") { } } +SCENARIO("update_non_diff_values_to_base_config preserves child vectors when child has more extruders than parent", + "[Config][Variant]") { + GIVEN("A 2-extruder child printer config inheriting from a 1-extruder parent") { + Slic3r::DynamicPrintConfig child; + Slic3r::DynamicPrintConfig parent; + + child.set_key_value("nozzle_diameter", new Slic3r::ConfigOptionFloats({0.4, 0.4})); + child.set_key_value("printer_extruder_id", new Slic3r::ConfigOptionInts({1, 2})); + child.set_key_value("printer_extruder_variant", new Slic3r::ConfigOptionStrings({"Direct Drive Standard", "Direct Drive Standard"})); + child.set_key_value("retraction_length", new Slic3r::ConfigOptionFloats({1.5, 1.5})); + + parent.set_key_value("nozzle_diameter", new Slic3r::ConfigOptionFloats({0.4})); + parent.set_key_value("printer_extruder_id", new Slic3r::ConfigOptionInts({1})); + parent.set_key_value("printer_extruder_variant", new Slic3r::ConfigOptionStrings({"Direct Drive Standard"})); + parent.set_key_value("retraction_length", new Slic3r::ConfigOptionFloats({0.8})); + + const Slic3r::t_config_option_keys keys = { + "retraction_length", "printer_extruder_id", "printer_extruder_variant" + }; + const std::set different_keys = { + "retraction_length", "printer_extruder_id", "printer_extruder_variant" + }; + + WHEN("update_non_diff_values_to_base_config is called") { + std::string id_name = "printer_extruder_id"; + std::string var_name = "printer_extruder_variant"; + child.update_non_diff_values_to_base_config( + parent, keys, different_keys, id_name, var_name, + Slic3r::printer_options_with_variant_1, + Slic3r::printer_options_with_variant_2); + + THEN("printer_extruder_id retains size 2") { + REQUIRE(child.option("printer_extruder_id")->values.size() == 2); + } + THEN("printer_extruder_variant retains size 2") { + REQUIRE(child.option("printer_extruder_variant")->values.size() == 2); + } + THEN("retraction_length retains size 2") { + REQUIRE(child.option("retraction_length")->values.size() == 2); + } + THEN("printer_extruder_id values are preserved for both extruders") { + auto* pe_id = child.option("printer_extruder_id"); + REQUIRE(pe_id->values.size() == 2); + REQUIRE(pe_id->values[0] == 1); + REQUIRE(pe_id->values[1] == 2); + } + } + } +} + // SCENARIO("DynamicPrintConfig JSON serialization", "[Config]") { // WHEN("DynamicPrintConfig is serialized and deserialized") { // auto now = std::chrono::high_resolution_clock::now();