mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-08 10:37:40 +00:00
test: finish the temp-file cleanup (#14976)
Follow-up to #14785. Routes the tests that still hand-rolled temp paths through the shared helpers and unifies the temp guards. - Add ScopedTemporaryDir and a shared ScopedTemporaryPath base under it and ScopedTemporaryFile. - Move test_3mf's round-trip .3mf output out of the TEST_DATA_DIR source tree (a fixed-name leak) and test_toolordering's fixed-name temp .gcode (a sharding collision) onto ScopedTemporaryFile. - Move test_config, test_slicing_pipeline_bindings, the test_3mf backup dirs, and test_preset_bundle_loading onto the guards. - Make slic3rutils ScopedDataDir compose ScopedTemporaryDir; dedupe test_network_versions' fixture and delete test_plugin_lifecycle's duplicate.
This commit is contained in:
@@ -155,10 +155,8 @@ SCENARIO("H2C multi-nozzle .3mf round-trip", "[3mf][MultiNozzle]") {
|
||||
|
||||
// store_bbs_3mf stages Metadata/project_settings.config through the model's backup path;
|
||||
// point it at a writable temp dir (the default lives under a read-only root in CI).
|
||||
std::string backup_dir =
|
||||
(boost::filesystem::temp_directory_path() / boost::filesystem::unique_path("orca_mn_%%%%%%%%")).string();
|
||||
boost::filesystem::create_directories(backup_dir);
|
||||
model.set_backup_path(backup_dir);
|
||||
ScopedTemporaryDir backup_dir("orca_mn");
|
||||
model.set_backup_path(backup_dir.string());
|
||||
|
||||
// Global (printer) config: give nozzle_volume_type a non-default value so the slice_info
|
||||
// read-back is a meaningful assertion (High Flow == 1).
|
||||
@@ -180,7 +178,8 @@ SCENARIO("H2C multi-nozzle .3mf round-trip", "[3mf][MultiNozzle]") {
|
||||
plate->config.set_key_value("enable_filament_dynamic_map", new ConfigOptionBool(true));
|
||||
|
||||
WHEN("stored to and reloaded from a .3mf") {
|
||||
std::string test_file = std::string(TEST_DATA_DIR) + "/test_3mf/mn_roundtrip.3mf";
|
||||
ScopedTemporaryFile temp(".3mf");
|
||||
const std::string test_file = temp.string();
|
||||
|
||||
StoreParams store_params;
|
||||
store_params.path = test_file.c_str();
|
||||
@@ -202,8 +201,6 @@ SCENARIO("H2C multi-nozzle .3mf round-trip", "[3mf][MultiNozzle]") {
|
||||
bool loaded = load_bbs_3mf(test_file.c_str(), &dst_config, &ctxt, &dst_model, &dst_plates,
|
||||
&project_presets, &is_bbl_3mf, &is_orca_3mf, &file_version, nullptr,
|
||||
LoadStrategy::LoadModel | LoadStrategy::LoadConfig);
|
||||
boost::filesystem::remove(test_file);
|
||||
|
||||
THEN("every multi-nozzle key round-trips as expected") {
|
||||
REQUIRE(loaded);
|
||||
REQUIRE(dst_plates.size() >= 1);
|
||||
@@ -233,7 +230,6 @@ SCENARIO("H2C multi-nozzle .3mf round-trip", "[3mf][MultiNozzle]") {
|
||||
release_PlateData_list(dst_plates);
|
||||
}
|
||||
delete plate; // store_bbs_3mf does not take ownership of the source plate
|
||||
boost::filesystem::remove_all(backup_dir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,10 +246,8 @@ SCENARIO("Non-standard nozzle diameter survives .3mf save on a single-nozzle pri
|
||||
REQUIRE(load_stl(src_file.c_str(), &model));
|
||||
model.add_default_instances();
|
||||
|
||||
std::string backup_dir =
|
||||
(boost::filesystem::temp_directory_path() / boost::filesystem::unique_path("orca_nd_%%%%%%%%")).string();
|
||||
boost::filesystem::create_directories(backup_dir);
|
||||
model.set_backup_path(backup_dir);
|
||||
ScopedTemporaryDir backup_dir("orca_nd");
|
||||
model.set_backup_path(backup_dir.string());
|
||||
|
||||
// Single extruder with a non-standard 0.5 mm nozzle; extruder_max_nozzle_count stays at its
|
||||
// default (no nozzle cluster), so the writer must emit the exact config diameter.
|
||||
@@ -276,7 +270,8 @@ SCENARIO("Non-standard nozzle diameter survives .3mf save on a single-nozzle pri
|
||||
plate->slice_filaments_info.push_back(fi);
|
||||
|
||||
WHEN("stored to and reloaded from a .3mf") {
|
||||
std::string test_file = std::string(TEST_DATA_DIR) + "/test_3mf/nd_roundtrip.3mf";
|
||||
ScopedTemporaryFile temp(".3mf");
|
||||
const std::string test_file = temp.string();
|
||||
|
||||
StoreParams store_params;
|
||||
store_params.path = test_file.c_str();
|
||||
@@ -296,8 +291,6 @@ SCENARIO("Non-standard nozzle diameter survives .3mf save on a single-nozzle pri
|
||||
bool loaded = load_bbs_3mf(test_file.c_str(), &dst_config, &ctxt, &dst_model, &dst_plates,
|
||||
&project_presets, &is_bbl_3mf, &is_orca_3mf, &file_version, nullptr,
|
||||
LoadStrategy::LoadModel | LoadStrategy::LoadConfig);
|
||||
boost::filesystem::remove(test_file);
|
||||
|
||||
THEN("the saved nozzle diameter is the exact 0.5, not the rounded 0.4") {
|
||||
REQUIRE(loaded);
|
||||
REQUIRE(dst_plates.size() >= 1);
|
||||
@@ -315,7 +308,6 @@ SCENARIO("Non-standard nozzle diameter survives .3mf save on a single-nozzle pri
|
||||
release_PlateData_list(dst_plates);
|
||||
}
|
||||
delete plate; // store_bbs_3mf does not take ownership of the source plate
|
||||
boost::filesystem::remove_all(backup_dir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -436,10 +428,8 @@ SCENARIO("Nozzle-group metadata .3mf round-trip", "[3mf][MultiNozzle]") {
|
||||
REQUIRE(load_stl(src_file.c_str(), &model));
|
||||
model.add_default_instances();
|
||||
|
||||
std::string backup_dir =
|
||||
(boost::filesystem::temp_directory_path() / boost::filesystem::unique_path("orca_ng_%%%%%%%%")).string();
|
||||
boost::filesystem::create_directories(backup_dir);
|
||||
model.set_backup_path(backup_dir);
|
||||
ScopedTemporaryDir backup_dir("orca_ng");
|
||||
model.set_backup_path(backup_dir.string());
|
||||
|
||||
DynamicPrintConfig config = DynamicPrintConfig::full_print_config();
|
||||
|
||||
@@ -459,7 +449,8 @@ SCENARIO("Nozzle-group metadata .3mf round-trip", "[3mf][MultiNozzle]") {
|
||||
plate->config.set_key_value("filament_map", new ConfigOptionInts({ 1, 2, 1 }));
|
||||
|
||||
WHEN("stored to and reloaded from a .3mf") {
|
||||
std::string test_file = std::string(TEST_DATA_DIR) + "/test_3mf/ng_roundtrip.3mf";
|
||||
ScopedTemporaryFile temp(".3mf");
|
||||
const std::string test_file = temp.string();
|
||||
|
||||
StoreParams store_params;
|
||||
store_params.path = test_file.c_str();
|
||||
@@ -479,8 +470,6 @@ SCENARIO("Nozzle-group metadata .3mf round-trip", "[3mf][MultiNozzle]") {
|
||||
bool loaded = load_bbs_3mf(test_file.c_str(), &dst_config, &ctxt, &dst_model, &dst_plates,
|
||||
&project_presets, &is_bbl_3mf, &is_orca_3mf, &file_version, nullptr,
|
||||
LoadStrategy::LoadModel | LoadStrategy::LoadConfig);
|
||||
boost::filesystem::remove(test_file);
|
||||
|
||||
THEN("the <nozzle> tags round-trip into the loaded plate's nozzles_info") {
|
||||
REQUIRE(loaded);
|
||||
REQUIRE(dst_plates.size() >= 1);
|
||||
@@ -506,6 +495,5 @@ SCENARIO("Nozzle-group metadata .3mf round-trip", "[3mf][MultiNozzle]") {
|
||||
release_PlateData_list(dst_plates);
|
||||
}
|
||||
delete plate;
|
||||
boost::filesystem::remove_all(backup_dir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "libslic3r/PrintConfigConstants.hpp"
|
||||
#include "libslic3r/LocalesUtils.hpp"
|
||||
|
||||
#include "test_utils.hpp"
|
||||
|
||||
#include <cereal/types/polymorphic.hpp>
|
||||
#include <cereal/types/string.hpp>
|
||||
#include <cereal/types/vector.hpp>
|
||||
@@ -407,8 +409,7 @@ SCENARIO("update_diff_values_to_child_config tolerates legacy machine-limit vect
|
||||
// }
|
||||
|
||||
TEST_CASE("save_to_json round-trips plugin capability references as strings", "[Config][plugins]") {
|
||||
namespace fs = boost::filesystem;
|
||||
const fs::path tmp = fs::temp_directory_path() / fs::unique_path("orca_plugins_%%%%-%%%%.json");
|
||||
ScopedTemporaryFile tmp(".json");
|
||||
const std::vector<std::string> refs = {
|
||||
"local_plugin;;inset",
|
||||
"cloud_plugin;550e8400-e29b-41d4-a716-446655440000;inset"
|
||||
@@ -435,8 +436,6 @@ TEST_CASE("save_to_json round-trips plugin capability references as strings", "[
|
||||
REQUIRE(reloaded.load_from_json(tmp.string(), substitutions, true, key_values, reason) == 0);
|
||||
CHECK(reason.empty());
|
||||
CHECK(reloaded.option<ConfigOptionStrings>("slicing_pipeline_plugin")->values == refs);
|
||||
|
||||
fs::remove(tmp);
|
||||
}
|
||||
|
||||
TEST_CASE("plugin capability references survive string-map serialization", "[Config][plugins]") {
|
||||
|
||||
@@ -5,28 +5,14 @@
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
|
||||
#include "test_utils.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
|
||||
namespace {
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
struct TempPresetDir {
|
||||
fs::path path;
|
||||
|
||||
TempPresetDir()
|
||||
{
|
||||
path = fs::temp_directory_path() / fs::unique_path("orcaslicer-preset-%%%%-%%%%-%%%%");
|
||||
fs::create_directories(path);
|
||||
}
|
||||
|
||||
~TempPresetDir()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
fs::remove_all(path, ec);
|
||||
}
|
||||
};
|
||||
|
||||
void write_print_preset(const DynamicPrintConfig &default_config, const fs::path &file, const std::string &name, const std::string &inherits = {})
|
||||
{
|
||||
DynamicPrintConfig config(default_config);
|
||||
@@ -82,17 +68,17 @@ struct RenameTestCollection : public PresetCollection
|
||||
|
||||
TEST_CASE("Preset identity is canonicalized from load path", "[Preset][Identity]")
|
||||
{
|
||||
TempPresetDir temp_dir;
|
||||
ScopedTemporaryDir temp_dir;
|
||||
PresetBundle bundle;
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
|
||||
write_print_preset(bundle.prints.default_preset().config, temp_dir.path / PRESET_PRINT_NAME / "User.json", "User");
|
||||
write_print_preset(bundle.prints.default_preset().config, temp_dir.path / PRESET_LOCAL_DIR / "bundle-1" / PRESET_PRINT_NAME / "LocalBundle.json", "LocalBundle");
|
||||
write_print_preset(bundle.prints.default_preset().config, temp_dir.path / PRESET_SUBSCRIBED_DIR / "remote-1" / PRESET_PRINT_NAME / "Subscribed.json", "Subscribed");
|
||||
write_print_preset(bundle.prints.default_preset().config, temp_dir.path() / PRESET_PRINT_NAME / "User.json", "User");
|
||||
write_print_preset(bundle.prints.default_preset().config, temp_dir.path() / PRESET_LOCAL_DIR / "bundle-1" / PRESET_PRINT_NAME / "LocalBundle.json", "LocalBundle");
|
||||
write_print_preset(bundle.prints.default_preset().config, temp_dir.path() / PRESET_SUBSCRIBED_DIR / "remote-1" / PRESET_PRINT_NAME / "Subscribed.json", "Subscribed");
|
||||
|
||||
bundle.prints.load_presets(temp_dir.path.string(), PRESET_PRINT_NAME, substitutions, ForwardCompatibilitySubstitutionRule::Disable);
|
||||
bundle.prints.load_presets((temp_dir.path / PRESET_LOCAL_DIR / "bundle-1").string(), PRESET_PRINT_NAME, substitutions, ForwardCompatibilitySubstitutionRule::Disable);
|
||||
bundle.prints.load_presets((temp_dir.path / PRESET_SUBSCRIBED_DIR / "remote-1").string(), PRESET_PRINT_NAME, substitutions, ForwardCompatibilitySubstitutionRule::Disable);
|
||||
bundle.prints.load_presets(temp_dir.path().string(), PRESET_PRINT_NAME, substitutions, ForwardCompatibilitySubstitutionRule::Disable);
|
||||
bundle.prints.load_presets((temp_dir.path() / PRESET_LOCAL_DIR / "bundle-1").string(), PRESET_PRINT_NAME, substitutions, ForwardCompatibilitySubstitutionRule::Disable);
|
||||
bundle.prints.load_presets((temp_dir.path() / PRESET_SUBSCRIBED_DIR / "remote-1").string(), PRESET_PRINT_NAME, substitutions, ForwardCompatibilitySubstitutionRule::Disable);
|
||||
|
||||
const Preset *root_user = bundle.prints.find_preset("User");
|
||||
REQUIRE(root_user != nullptr);
|
||||
@@ -112,14 +98,14 @@ TEST_CASE("Preset identity is canonicalized from load path", "[Preset][Identity]
|
||||
|
||||
TEST_CASE("Legacy bundle import without bundle metadata stays in the user preset directory", "[Preset][Identity]")
|
||||
{
|
||||
TempPresetDir temp_dir;
|
||||
ScopedTemporaryDir temp_dir;
|
||||
PresetBundle bundle;
|
||||
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
std::vector<std::string> result;
|
||||
int overwrite = 0;
|
||||
std::string file = (temp_dir.path / "legacy-bundle" / "Imported.json").string();
|
||||
const fs::path user_root = temp_dir.path / "user";
|
||||
std::string file = (temp_dir.path() / "legacy-bundle" / "Imported.json").string();
|
||||
const fs::path user_root = temp_dir.path() / "user";
|
||||
|
||||
write_print_preset(bundle.prints.default_preset().config, file, "Imported");
|
||||
fs::create_directories(user_root);
|
||||
@@ -252,7 +238,7 @@ TEST_CASE("find_preset2 auto-matches removed Generic vendor profiles to the libr
|
||||
|
||||
TEST_CASE("Renamed parent is normalized into a loaded preset's inherits", "[Preset][Rename]")
|
||||
{
|
||||
TempPresetDir temp_dir;
|
||||
ScopedTemporaryDir temp_dir;
|
||||
RenameTestCollection coll;
|
||||
|
||||
// Current parent, renamed from "Old Process".
|
||||
@@ -262,10 +248,10 @@ TEST_CASE("Renamed parent is normalized into a loaded preset's inherits", "[Pres
|
||||
|
||||
// A user preset on disk that still inherits the OLD name.
|
||||
write_preset_with_inherits(coll.default_preset().config,
|
||||
temp_dir.path / PRESET_PRINT_NAME / "Child.json", "Child", "Old Process");
|
||||
temp_dir.path() / PRESET_PRINT_NAME / "Child.json", "Child", "Old Process");
|
||||
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
coll.load_presets(temp_dir.path.string(), PRESET_PRINT_NAME, substitutions,
|
||||
coll.load_presets(temp_dir.path().string(), PRESET_PRINT_NAME, substitutions,
|
||||
ForwardCompatibilitySubstitutionRule::Disable);
|
||||
|
||||
const Preset *child = coll.find_preset("Child");
|
||||
@@ -279,17 +265,17 @@ TEST_CASE("Renamed parent is normalized into a loaded preset's inherits", "[Pres
|
||||
|
||||
TEST_CASE("Removed Generic parent is normalized into a loaded filament's inherits", "[Preset][Rename]")
|
||||
{
|
||||
TempPresetDir temp_dir;
|
||||
ScopedTemporaryDir temp_dir;
|
||||
PresetBundle bundle;
|
||||
|
||||
add_inmemory_preset(bundle.filaments, "Generic PLA @System");
|
||||
|
||||
// A user filament that still inherits a removed "<vendor> Generic PLA" profile.
|
||||
write_preset_with_inherits(bundle.filaments.default_preset().config,
|
||||
temp_dir.path / PRESET_FILAMENT_NAME / "MyPLA.json", "MyPLA", "Voron Generic PLA");
|
||||
temp_dir.path() / PRESET_FILAMENT_NAME / "MyPLA.json", "MyPLA", "Voron Generic PLA");
|
||||
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
bundle.filaments.load_presets(temp_dir.path.string(), PRESET_FILAMENT_NAME, substitutions,
|
||||
bundle.filaments.load_presets(temp_dir.path().string(), PRESET_FILAMENT_NAME, substitutions,
|
||||
ForwardCompatibilitySubstitutionRule::Disable);
|
||||
|
||||
const Preset *child = bundle.filaments.find_preset("MyPLA");
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
|
||||
#include "test_utils.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
@@ -708,10 +710,9 @@ TEST_CASE("Sequential selector prints publish a stitched result and cache the pl
|
||||
REQUIRE(print.config().filament_self_index.values.size() >= print.config().filament_map.values.size());
|
||||
|
||||
// Export must consume the cached plans and produce g-code without throwing.
|
||||
boost::filesystem::path gcode_path = boost::filesystem::temp_directory_path() / "orca_seq_dynamic_publish_test.gcode";
|
||||
REQUIRE_NOTHROW(print.export_gcode(gcode_path.string(), nullptr, nullptr));
|
||||
REQUIRE(boost::filesystem::exists(gcode_path));
|
||||
boost::filesystem::remove(gcode_path);
|
||||
ScopedTemporaryFile gcode(".gcode");
|
||||
REQUIRE_NOTHROW(print.export_gcode(gcode.string(), nullptr, nullptr));
|
||||
REQUIRE(boost::filesystem::exists(gcode.path()));
|
||||
}
|
||||
|
||||
TEST_CASE("Per-variant expansion gives migrating filaments one slot per variant", "[PrintConfig][H2C][Dynamic]")
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "test_utils.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Point data_dir() at a throwaway directory for the lifetime of a test and
|
||||
@@ -13,24 +15,20 @@ namespace Slic3r {
|
||||
// disposable tree and tests don't leak state into each other.
|
||||
struct ScopedDataDir
|
||||
{
|
||||
ScopedTemporaryDir tmp; // owns the temp dir (create + recursive remove)
|
||||
boost::filesystem::path dir; // = tmp.path(); kept as a member for callers
|
||||
std::string previous;
|
||||
boost::filesystem::path dir;
|
||||
|
||||
explicit ScopedDataDir(const std::string& tag)
|
||||
: tmp("orca-" + tag), dir(tmp.path()), previous(data_dir())
|
||||
{
|
||||
namespace fs = boost::filesystem;
|
||||
previous = data_dir();
|
||||
dir = fs::temp_directory_path() / fs::unique_path("orca-" + tag + "-%%%%-%%%%");
|
||||
fs::create_directories(dir);
|
||||
set_data_dir(dir.string());
|
||||
}
|
||||
|
||||
~ScopedDataDir()
|
||||
{
|
||||
set_data_dir(previous);
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::remove_all(dir, ec);
|
||||
}
|
||||
~ScopedDataDir() { set_data_dir(previous); } // tmp removes the directory
|
||||
|
||||
// The plugin manager scans {data_dir}/orca_plugins.
|
||||
boost::filesystem::path plugins_dir() const { return dir / "orca_plugins"; }
|
||||
|
||||
ScopedDataDir(const ScopedDataDir&) = delete;
|
||||
ScopedDataDir& operator=(const ScopedDataDir&) = delete;
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "slic3r/Utils/bambu_networking.hpp"
|
||||
|
||||
#include "plugin_test_utils.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
@@ -25,27 +27,16 @@ static const char* PLUGIN_EXT = ".so";
|
||||
|
||||
struct PluginFolderFixture
|
||||
{
|
||||
fs::path root;
|
||||
std::string previous_data_dir;
|
||||
ScopedDataDir data{"netver"};
|
||||
|
||||
PluginFolderFixture()
|
||||
{
|
||||
previous_data_dir = data_dir();
|
||||
root = fs::temp_directory_path() / fs::unique_path("orca-netver-%%%%%%%%");
|
||||
fs::create_directories(root / "plugins");
|
||||
set_data_dir(root.string());
|
||||
}
|
||||
|
||||
~PluginFolderFixture()
|
||||
{
|
||||
set_data_dir(previous_data_dir);
|
||||
boost::system::error_code ec;
|
||||
fs::remove_all(root, ec);
|
||||
fs::create_directories(data.dir / "plugins");
|
||||
}
|
||||
|
||||
void add_plugin(const std::string& version)
|
||||
{
|
||||
boost::nowide::ofstream f((root / "plugins" / (PLUGIN_PREFIX + version + PLUGIN_EXT)).string());
|
||||
boost::nowide::ofstream f((data.dir / "plugins" / (PLUGIN_PREFIX + version + PLUGIN_EXT)).string());
|
||||
f << "stub";
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <slic3r/plugin/PluginFsUtils.hpp>
|
||||
#include <slic3r/plugin/PythonInterpreter.hpp>
|
||||
|
||||
#include "plugin_test_utils.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -25,32 +27,6 @@ namespace fs = boost::filesystem;
|
||||
|
||||
namespace {
|
||||
|
||||
// Point data_dir() at a throwaway directory for the lifetime of a test and restore the previous
|
||||
// value afterwards, so discovery scans a disposable {data_dir}/orca_plugins tree and tests don't
|
||||
// leak state into each other.
|
||||
struct ScopedDataDir
|
||||
{
|
||||
std::string previous;
|
||||
fs::path dir;
|
||||
|
||||
explicit ScopedDataDir(const std::string& tag)
|
||||
{
|
||||
previous = data_dir();
|
||||
dir = fs::temp_directory_path() / fs::unique_path("orca-" + tag + "-%%%%-%%%%");
|
||||
fs::create_directories(dir);
|
||||
set_data_dir(dir.string());
|
||||
}
|
||||
|
||||
~ScopedDataDir()
|
||||
{
|
||||
set_data_dir(previous);
|
||||
boost::system::error_code ec;
|
||||
fs::remove_all(dir, ec);
|
||||
}
|
||||
|
||||
fs::path plugins_dir() const { return dir / "orca_plugins"; }
|
||||
};
|
||||
|
||||
// Brings the plugin system up, and tears it down explicitly at the end of the test.
|
||||
//
|
||||
// Shutting the interpreter down here, rather than leaving it to PythonInterpreter's static
|
||||
|
||||
@@ -16,6 +16,8 @@ TEST_CASE("SlicingPipeline capability-type string maps round-trip", "[slicing_pi
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/ExPolygon.hpp"
|
||||
#include "libslic3r/Surface.hpp"
|
||||
|
||||
#include "test_utils.hpp"
|
||||
#include "libslic3r/Layer.hpp"
|
||||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
#include "libslic3r/ExtrusionEntityCollection.hpp"
|
||||
@@ -142,7 +144,7 @@ TEST_CASE("orca.slicing psGCodePostProcess context: file edit in place + config
|
||||
import_orca_module();
|
||||
py::gil_scoped_acquire gil;
|
||||
|
||||
const fs::path gpath = fs::temp_directory_path() / fs::unique_path("orca_pp_%%%%-%%%%.gcode");
|
||||
ScopedTemporaryFile gpath(".gcode");
|
||||
{
|
||||
boost::nowide::ofstream ofs(gpath.string());
|
||||
ofs << "; header\nG1 X0 Y0\n";
|
||||
@@ -196,9 +198,7 @@ _pp_result = Stamp().execute(_pp_ctx)
|
||||
boost::nowide::ifstream ifs(gpath.string());
|
||||
std::stringstream ss; ss << ifs.rdbuf(); contents = ss.str();
|
||||
}
|
||||
CHECK(contents.find("; stamped by File") != std::string::npos);
|
||||
fs::remove(gpath);
|
||||
}
|
||||
CHECK(contents.find("; stamped by File") != std::string::npos);}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Toolpath helpers for the raw-graph tests.
|
||||
|
||||
@@ -27,26 +27,47 @@ inline Slic3r::TriangleMesh load_model(const std::string &obj_filename)
|
||||
return mesh;
|
||||
}
|
||||
|
||||
// RAII holder for a unique temporary file path, removed when the guard goes out
|
||||
// of scope so a failing assertion never leaks it. Uses the system temp dir with
|
||||
// a unique name (parallel-safe, cross-platform). The file itself is created by
|
||||
// whoever writes to path()/string(); this only reserves the name and cleans up.
|
||||
class ScopedTemporaryFile
|
||||
// ---------------------------------------------------------------------------
|
||||
// Scoped temporary paths
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Owns a unique path under the system temp dir, "<prefix>-<unique>[<extension>]"
|
||||
// (parallel-safe, cross-platform). Shared base for the two RAII temp guards below.
|
||||
class ScopedTemporaryPath
|
||||
{
|
||||
public:
|
||||
const boost::filesystem::path &path() const { return m_path; }
|
||||
std::string string() const { return m_path.string(); }
|
||||
ScopedTemporaryPath(const ScopedTemporaryPath &) = delete;
|
||||
ScopedTemporaryPath &operator=(const ScopedTemporaryPath &) = delete;
|
||||
|
||||
protected:
|
||||
ScopedTemporaryPath(const std::string &prefix, const std::string &extension)
|
||||
: m_path(boost::filesystem::temp_directory_path()
|
||||
/ boost::filesystem::unique_path(prefix + "-%%%%-%%%%-%%%%" + extension))
|
||||
{}
|
||||
~ScopedTemporaryPath() = default; // non-virtual: never deleted through a base pointer
|
||||
|
||||
boost::filesystem::path m_path;
|
||||
};
|
||||
|
||||
// A temp file the caller creates by writing to path()/string(); the guard only
|
||||
// reserves the name and removes the file on scope exit.
|
||||
class ScopedTemporaryFile : public ScopedTemporaryPath
|
||||
{
|
||||
public:
|
||||
explicit ScopedTemporaryFile(const std::string &extension = ".tmp")
|
||||
: m_path(boost::filesystem::temp_directory_path()
|
||||
/ boost::filesystem::unique_path("orca-%%%%-%%%%-%%%%" + extension))
|
||||
{}
|
||||
: ScopedTemporaryPath("orca", extension) {}
|
||||
~ScopedTemporaryFile() { boost::system::error_code ec; boost::filesystem::remove(m_path, ec); }
|
||||
ScopedTemporaryFile(const ScopedTemporaryFile &) = delete;
|
||||
ScopedTemporaryFile &operator=(const ScopedTemporaryFile &) = delete;
|
||||
};
|
||||
|
||||
const boost::filesystem::path &path() const { return m_path; }
|
||||
std::string string() const { return m_path.string(); }
|
||||
|
||||
private:
|
||||
boost::filesystem::path m_path;
|
||||
// A temp directory created on construction and removed recursively on scope exit.
|
||||
class ScopedTemporaryDir : public ScopedTemporaryPath
|
||||
{
|
||||
public:
|
||||
explicit ScopedTemporaryDir(const std::string &prefix = "orca")
|
||||
: ScopedTemporaryPath(prefix, "") { boost::filesystem::create_directories(m_path); }
|
||||
~ScopedTemporaryDir() { boost::system::error_code ec; boost::filesystem::remove_all(m_path, ec); }
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -66,7 +87,7 @@ inline std::string debug_artifact_path(const std::string &name)
|
||||
boost::filesystem::path dir = boost::filesystem::temp_directory_path()
|
||||
/ boost::filesystem::unique_path("orca-test-artifacts-%%%%-%%%%");
|
||||
boost::filesystem::create_directories(dir);
|
||||
std::printf("Debug test artifacts will be written to %s\n", dir.string().c_str());
|
||||
std::fprintf(stderr, "Debug test artifacts will be written to %s\n", dir.string().c_str());
|
||||
return dir;
|
||||
}();
|
||||
boost::filesystem::path full = root / name;
|
||||
@@ -75,57 +96,52 @@ inline std::string debug_artifact_path(const std::string &name)
|
||||
}
|
||||
|
||||
// Dump a mesh as OBJ.
|
||||
inline void write_debug_obj(const std::string &name, const Slic3r::TriangleMesh &mesh)
|
||||
inline void write_debug_obj([[maybe_unused]] const std::string &name,
|
||||
[[maybe_unused]] const Slic3r::TriangleMesh &mesh)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
mesh.WriteOBJFile(debug_artifact_path(name).c_str());
|
||||
#else
|
||||
(void) name; (void) mesh;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void write_debug_obj(const std::string &name, const indexed_triangle_set &its)
|
||||
inline void write_debug_obj([[maybe_unused]] const std::string &name,
|
||||
[[maybe_unused]] const indexed_triangle_set &its)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
its_write_obj(its, debug_artifact_path(name).c_str());
|
||||
#else
|
||||
(void) name; (void) its;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Dump a mesh as ASCII STL.
|
||||
inline void write_debug_stl(const std::string &name, const Slic3r::TriangleMesh &mesh)
|
||||
inline void write_debug_stl([[maybe_unused]] const std::string &name,
|
||||
[[maybe_unused]] const Slic3r::TriangleMesh &mesh)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
mesh.write_ascii(debug_artifact_path(name).c_str());
|
||||
#else
|
||||
(void) name; (void) mesh;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Draw an SVG artifact through a callback that receives the open SVG. Second
|
||||
// overload takes a BoundingBox when the drawing needs one.
|
||||
template<class Draw>
|
||||
inline void write_debug_svg(const std::string &name, Draw &&draw)
|
||||
inline void write_debug_svg([[maybe_unused]] const std::string &name, [[maybe_unused]] Draw &&draw)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
Slic3r::SVG svg(debug_artifact_path(name));
|
||||
draw(svg);
|
||||
svg.Close();
|
||||
#else
|
||||
(void) name; (void) draw;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class Draw>
|
||||
inline void write_debug_svg(const std::string &name, const Slic3r::BoundingBox &bbox, Draw &&draw)
|
||||
inline void write_debug_svg([[maybe_unused]] const std::string &name,
|
||||
[[maybe_unused]] const Slic3r::BoundingBox &bbox,
|
||||
[[maybe_unused]] Draw &&draw)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
Slic3r::SVG svg(debug_artifact_path(name), bbox);
|
||||
draw(svg);
|
||||
svg.Close();
|
||||
#else
|
||||
(void) name; (void) bbox; (void) draw;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -133,13 +149,11 @@ inline void write_debug_svg(const std::string &name, const Slic3r::BoundingBox &
|
||||
// artifact. operator<< is resolved by ADL at the call site, so this header needn't
|
||||
// include the producer's headers.
|
||||
template<class Produce>
|
||||
inline void write_debug_stream(const std::string &name, Produce &&produce)
|
||||
inline void write_debug_stream([[maybe_unused]] const std::string &name, [[maybe_unused]] Produce &&produce)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
std::ofstream out(debug_artifact_path(name), std::ios::out | std::ios::binary);
|
||||
out << produce();
|
||||
#else
|
||||
(void) name; (void) produce;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user