diff --git a/tests/libslic3r/test_preset_bundle_loading.cpp b/tests/libslic3r/test_preset_bundle_loading.cpp index 5341e6c621..29c38395ac 100644 --- a/tests/libslic3r/test_preset_bundle_loading.cpp +++ b/tests/libslic3r/test_preset_bundle_loading.cpp @@ -1031,6 +1031,93 @@ TEST_CASE("Manifest-backed resolution reuses the vendor tree it already loaded", CHECK_THAT(travel_speed(fresh, "second.json"), Catch::Matchers::WithinAbs(222.0, 1e-6)); } +TEST_CASE("Manifest-backed resolution does not keep a vendor tree that failed to load", "[Preset][Bundle][Regression]") +{ + ScopedTemporaryDir dir; + const fs::path child_file = dir.path() / "Acme" / "process" / "child.json"; + auto write_manifest = [&](const std::string &leading_entry) { + std::ofstream((dir.path() / "Acme.json").string()) + << R"({"version":"1.0.0","name":"Acme","process_list":[)" << leading_entry + << R"({"name":"Acme Process","sub_path":"process/child.json"}]})"; + }; + write_manifest("123,"); + fs::create_directories(child_file.parent_path()); + std::ofstream(child_file.string()) + << R"({"type":"process","name":"Acme Process","from":"system",)" + << R"("instantiation":"true","layer_height":"0.2"})"; + + PresetBundle bundle; + auto resolve = [&](std::string &error) { + DynamicPrintConfig raw; + raw.option(BBL_JSON_KEY_INHERITS, true)->value = "fdm_process_common"; + return bundle.resolve_preset_config(raw, Preset::TYPE_PRINT, child_file.string(), + ForwardCompatibilitySubstitutionRule::EnableSilent, error); + }; + + std::string error; + CHECK_FALSE(resolve(error)); + CHECK_FALSE(error.empty()); + + write_manifest(""); + error.clear(); + CHECK(resolve(error)); + CHECK(error.empty()); +} + +TEST_CASE("Manifest-backed resolution reuses the library base for type-probed files", "[Preset][Bundle][Regression]") +{ + ScopedTemporaryDir dir; + const fs::path library_pet = dir.path() / PresetBundle::ORCA_FILAMENT_LIBRARY / "filament" / "pet.json"; + const fs::path filament_dir = dir.path() / "Acme" / "filament"; + + std::ofstream((dir.path() / (std::string(PresetBundle::ORCA_FILAMENT_LIBRARY) + ".json")).string()) + << R"({"version":"1.0.0","name":"OrcaFilamentLibrary","filament_list":[)" + << R"({"name":"fdm_filament_pet","sub_path":"filament/pet.json","filament_id":"GFL99"}]})"; + fs::create_directories(library_pet.parent_path()); + auto write_library_pet = [&](double density) { + std::ofstream(library_pet.string()) + << R"({"type":"filament","name":"fdm_filament_pet","from":"system",)" + << R"("filament_id":"GFL99","instantiation":"false",)" + << R"("filament_type":["PETG"],"filament_density":[")" << density << R"("]})"; + }; + write_library_pet(1.27); + + std::ofstream((dir.path() / "Acme.json").string()) + << R"({"version":"1.0.0","name":"Acme","filament_list":[)" + << R"({"name":"Acme PETG","sub_path":"filament/petg.json","filament_id":"GFA00"},)" + << R"({"name":"Acme PETG Matte","sub_path":"filament/petg_matte.json","filament_id":"GFA01"}]})"; + fs::create_directories(filament_dir); + auto write_child = [&](const std::string &file, const std::string &name, const std::string &filament_id) { + std::ofstream((filament_dir / file).string()) + << R"({"type":"filament","name":")" << name << R"(","from":"system",)" + << R"("filament_id":")" << filament_id << R"(","instantiation":"true","inherits":"fdm_filament_pet"})"; + }; + write_child("petg.json", "Acme PETG", "GFA00"); + write_child("petg_matte.json", "Acme PETG Matte", "GFA01"); + + auto density = [](const DynamicPrintConfig &config) { + return config.option("filament_density")->values.front(); + }; + + PresetBundle bundle; + DynamicPrintConfig first; + first.option(BBL_JSON_KEY_INHERITS, true)->value = "fdm_filament_pet"; + std::string error; + REQUIRE(bundle.resolve_preset_config(first, Preset::TYPE_FILAMENT, (filament_dir / "petg.json").string(), + ForwardCompatibilitySubstitutionRule::EnableSilent, error)); + CHECK_THAT(density(first), Catch::Matchers::WithinAbs(1.27, 1e-6)); + + // Only a reload would see this change. + write_library_pet(1.5); + + DynamicPrintConfig second; + Preset::Type type = Preset::TYPE_INVALID; + REQUIRE(bundle.resolve_preset_config_type(second, type, (filament_dir / "petg_matte.json").string(), + ForwardCompatibilitySubstitutionRule::EnableSilent, error)); + CHECK(type == Preset::TYPE_FILAMENT); + CHECK_THAT(density(second), Catch::Matchers::WithinAbs(1.27, 1e-6)); +} + // Orca: a filament in the Orca Filament Library that names its compatible printers has to hide the generic // library filament sharing its alias, the same way a vendor owned filament does. Otherwise both are compatible // with that printer and the plater combo box lists the shared alias twice.