mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-16 15:32:09 +00:00
I can't get geometry tests to do anything useful. I've added extra output, but it hasn't helped me figure out why they don't work yet. That's also probably the last broken 3mf test doesn't work. The config tests were mostly broken because of config name changes. The placeholder_parser tests have some things that may-or-may-not still apply to Orca.
261 lines
13 KiB
C++
261 lines
13 KiB
C++
#include <catch2/catch.hpp>
|
|
|
|
#include "libslic3r/PrintConfig.hpp"
|
|
#include "libslic3r/PrintConfigConstants.hpp"
|
|
#include "libslic3r/LocalesUtils.hpp"
|
|
|
|
#include <cereal/types/polymorphic.hpp>
|
|
#include <cereal/types/string.hpp>
|
|
#include <cereal/types/vector.hpp>
|
|
#include <cereal/archives/binary.hpp>
|
|
|
|
using namespace Slic3r;
|
|
|
|
SCENARIO("Generic config validation performs as expected.", "[Config]") {
|
|
GIVEN("A config generated from default options") {
|
|
Slic3r::DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
|
WHEN( "outer_wall_line_width is set to 250%, a valid value") {
|
|
config.set_deserialize_strict("outer_wall_line_width", "250%");
|
|
THEN( "The config is read as valid.") {
|
|
REQUIRE(config.validate().empty());
|
|
}
|
|
}
|
|
WHEN( "outer_wall_line_width is set to -10, an invalid value") {
|
|
config.set("outer_wall_line_width", -10);
|
|
THEN( "Validate returns error") {
|
|
REQUIRE_FALSE(config.validate().empty());
|
|
}
|
|
}
|
|
|
|
WHEN( "wall_loops is set to -10, an invalid value") {
|
|
config.set("wall_loops", -10);
|
|
THEN( "Validate returns error") {
|
|
REQUIRE_FALSE(config.validate().empty());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SCENARIO("Config accessor functions perform as expected.", "[Config]") {
|
|
GIVEN("A config generated from default options") {
|
|
Slic3r::DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
|
WHEN("A boolean option is set to a boolean value") {
|
|
REQUIRE_NOTHROW(config.set("gcode_comments", true));
|
|
THEN("The underlying value is set correctly.") {
|
|
REQUIRE(config.opt<ConfigOptionBool>("gcode_comments")->getBool() == true);
|
|
}
|
|
}
|
|
WHEN("A boolean option is set to a string value representing a 0 or 1") {
|
|
CHECK_NOTHROW(config.set_deserialize_strict("gcode_comments", "1"));
|
|
THEN("The underlying value is set correctly.") {
|
|
REQUIRE(config.opt<ConfigOptionBool>("gcode_comments")->getBool() == true);
|
|
}
|
|
}
|
|
WHEN("A boolean option is set to a string value representing something other than 0 or 1") {
|
|
THEN("A BadOptionTypeException exception is thrown.") {
|
|
REQUIRE_THROWS_AS(config.set("gcode_comments", "Z"), BadOptionTypeException);
|
|
}
|
|
AND_THEN("Value is unchanged.") {
|
|
REQUIRE(config.opt<ConfigOptionBool>("gcode_comments")->getBool() == false);
|
|
}
|
|
}
|
|
WHEN("A boolean option is set to an int value") {
|
|
THEN("A BadOptionTypeException exception is thrown.") {
|
|
REQUIRE_THROWS_AS(config.set("gcode_comments", 1), BadOptionTypeException);
|
|
}
|
|
}
|
|
WHEN("A numeric option is set from serialized string") {
|
|
config.set_deserialize_strict("raft_layers", "20");
|
|
THEN("The underlying value is set correctly.") {
|
|
REQUIRE(config.opt<ConfigOptionInt>("raft_layers")->getInt() == 20);
|
|
}
|
|
}
|
|
WHEN("An integer-based option is set through the integer interface") {
|
|
config.set("raft_layers", 100);
|
|
THEN("The underlying value is set correctly.") {
|
|
REQUIRE(config.opt<ConfigOptionInt>("raft_layers")->getInt() == 100);
|
|
}
|
|
}
|
|
WHEN("An floating-point option is set through the integer interface") {
|
|
config.set("default_acceleration", 10);
|
|
THEN("The underlying value is set correctly.") {
|
|
REQUIRE(config.opt<ConfigOptionFloat>("default_acceleration")->getFloat() == 10.0);
|
|
}
|
|
}
|
|
WHEN("A floating-point option is set through the double interface") {
|
|
config.set("default_acceleration", 5.5);
|
|
THEN("The underlying value is set correctly.") {
|
|
REQUIRE(config.opt<ConfigOptionFloat>("default_acceleration")->getFloat() == 5.5);
|
|
}
|
|
}
|
|
WHEN("An integer-based option is set through the double interface") {
|
|
THEN("A BadOptionTypeException exception is thrown.") {
|
|
REQUIRE_THROWS_AS(config.set("top_shell_layers", 5.5), BadOptionTypeException);
|
|
}
|
|
}
|
|
WHEN("A numeric option is set to a non-numeric value.") {
|
|
auto prev_value = config.opt<ConfigOptionFloat>("default_acceleration")->getFloat();
|
|
THEN("A BadOptionTypeException exception is thrown.") {
|
|
REQUIRE_THROWS_AS(config.set_deserialize_strict("default_acceleration", "zzzz"), BadOptionValueException);
|
|
}
|
|
THEN("The value does not change.") {
|
|
REQUIRE(config.opt<ConfigOptionFloat>("default_acceleration")->getFloat() == prev_value);
|
|
}
|
|
}
|
|
WHEN("A string option is set through the string interface") {
|
|
config.set("machine_end_gcode", "100");
|
|
THEN("The underlying value is set correctly.") {
|
|
REQUIRE(config.opt<ConfigOptionString>("machine_end_gcode")->value == "100");
|
|
}
|
|
}
|
|
WHEN("A string option is set through the integer interface") {
|
|
config.set("machine_end_gcode", 100);
|
|
THEN("The underlying value is set correctly.") {
|
|
REQUIRE(config.opt<ConfigOptionString>("machine_end_gcode")->value == "100");
|
|
}
|
|
}
|
|
WHEN("A string option is set through the double interface") {
|
|
config.set("machine_end_gcode", 100.5);
|
|
THEN("The underlying value is set correctly.") {
|
|
REQUIRE(config.opt<ConfigOptionString>("machine_end_gcode")->value == float_to_string_decimal_point(100.5));
|
|
}
|
|
}
|
|
WHEN("A float or percent is set as a percent through the string interface.") {
|
|
config.set_deserialize_strict("initial_layer_line_width", "100%");
|
|
THEN("Value and percent flag are 100/true") {
|
|
auto tmp = config.opt<ConfigOptionFloatOrPercent>("initial_layer_line_width");
|
|
REQUIRE(tmp->percent == true);
|
|
REQUIRE(tmp->value == 100);
|
|
}
|
|
}
|
|
WHEN("A float or percent is set as a float through the string interface.") {
|
|
config.set_deserialize_strict("initial_layer_line_width", "100");
|
|
THEN("Value and percent flag are 100/false") {
|
|
auto tmp = config.opt<ConfigOptionFloatOrPercent>("initial_layer_line_width");
|
|
REQUIRE(tmp->percent == false);
|
|
REQUIRE(tmp->value == 100);
|
|
}
|
|
}
|
|
WHEN("A float or percent is set as a float through the int interface.") {
|
|
config.set("initial_layer_line_width", 100);
|
|
THEN("Value and percent flag are 100/false") {
|
|
auto tmp = config.opt<ConfigOptionFloatOrPercent>("initial_layer_line_width");
|
|
REQUIRE(tmp->percent == false);
|
|
REQUIRE(tmp->value == 100);
|
|
}
|
|
}
|
|
WHEN("A float or percent is set as a float through the double interface.") {
|
|
config.set("initial_layer_line_width", 100.5);
|
|
THEN("Value and percent flag are 100.5/false") {
|
|
auto tmp = config.opt<ConfigOptionFloatOrPercent>("initial_layer_line_width");
|
|
REQUIRE(tmp->percent == false);
|
|
REQUIRE(tmp->value == 100.5);
|
|
}
|
|
}
|
|
WHEN("A numeric vector is set from serialized string") {
|
|
config.set_deserialize_strict("temperature_vitrification", "10,20");
|
|
THEN("The underlying value is set correctly.") {
|
|
CHECK(config.opt<ConfigOptionInts>("temperature_vitrification")->get_at(0) == 10);
|
|
CHECK(config.opt<ConfigOptionInts>("temperature_vitrification")->get_at(1) == 20);
|
|
}
|
|
}
|
|
// FIXME: Design better accessors for vector elements
|
|
// The following isn't supported and probably shouldn't be:
|
|
// WHEN("An integer-based vector option is set through the integer interface") {
|
|
// config.set("temperature_vitrification", 100);
|
|
// THEN("The underlying value is set correctly.") {
|
|
// REQUIRE(config.opt<ConfigOptionInts>("temperature_vitrification")->get_at(0) == 100);
|
|
// }
|
|
// }
|
|
WHEN("An integer-based vector option is set through the set_key_value interface") {
|
|
config.set_key_value("temperature_vitrification", new ConfigOptionInts{10,20});
|
|
THEN("The underlying value is set correctly.") {
|
|
CHECK(config.opt<ConfigOptionInts>("temperature_vitrification")->get_at(0) == 10);
|
|
CHECK(config.opt<ConfigOptionInts>("temperature_vitrification")->get_at(1) == 20);
|
|
}
|
|
}
|
|
WHEN("An invalid option is requested during set.") {
|
|
THEN("A BadOptionTypeException exception is thrown.") {
|
|
REQUIRE_THROWS_AS(config.set("deadbeef_invalid_option", 1), UnknownOptionException);
|
|
REQUIRE_THROWS_AS(config.set("deadbeef_invalid_option", 1.0), UnknownOptionException);
|
|
REQUIRE_THROWS_AS(config.set("deadbeef_invalid_option", "1"), UnknownOptionException);
|
|
REQUIRE_THROWS_AS(config.set("deadbeef_invalid_option", true), UnknownOptionException);
|
|
}
|
|
}
|
|
|
|
WHEN("An invalid option is requested during get.") {
|
|
THEN("A UnknownOptionException exception is thrown.") {
|
|
REQUIRE_THROWS_AS(config.option_throw<ConfigOptionString>("deadbeef_invalid_option", false), UnknownOptionException);
|
|
REQUIRE_THROWS_AS(config.option_throw<ConfigOptionFloat>("deadbeef_invalid_option", false), UnknownOptionException);
|
|
REQUIRE_THROWS_AS(config.option_throw<ConfigOptionInt>("deadbeef_invalid_option", false), UnknownOptionException);
|
|
REQUIRE_THROWS_AS(config.option_throw<ConfigOptionBool>("deadbeef_invalid_option", false), UnknownOptionException);
|
|
}
|
|
}
|
|
WHEN("An invalid option is requested during opt.") {
|
|
THEN("A UnknownOptionException exception is thrown.") {
|
|
REQUIRE_THROWS_AS(config.option_throw<ConfigOptionString>("deadbeef_invalid_option", false), UnknownOptionException);
|
|
REQUIRE_THROWS_AS(config.option_throw<ConfigOptionFloat>("deadbeef_invalid_option", false), UnknownOptionException);
|
|
REQUIRE_THROWS_AS(config.option_throw<ConfigOptionInt>("deadbeef_invalid_option", false), UnknownOptionException);
|
|
REQUIRE_THROWS_AS(config.option_throw<ConfigOptionBool>("deadbeef_invalid_option", false), UnknownOptionException);
|
|
}
|
|
}
|
|
|
|
WHEN("getX called on an unset option.") {
|
|
THEN("The default is returned.") {
|
|
REQUIRE(config.opt_float("layer_height") == INITIAL_LAYER_HEIGHT);
|
|
REQUIRE(config.opt_int("raft_layers") == INITIAL_RAFT_LAYERS);
|
|
REQUIRE(config.opt_bool("reduce_crossing_wall") == INITIAL_REDUCE_CROSSING_WALL);
|
|
}
|
|
}
|
|
|
|
WHEN("opt_float called on an option that has been set.") {
|
|
config.set("layer_height", INITIAL_LAYER_HEIGHT*2);
|
|
THEN("The set value is returned.") {
|
|
REQUIRE(config.opt_float("layer_height") == INITIAL_LAYER_HEIGHT*2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SCENARIO("Config ini load/save interface", "[Config]") {
|
|
WHEN("new_from_ini is called") {
|
|
Slic3r::DynamicPrintConfig config;
|
|
std::string path = std::string(TEST_DATA_DIR) + "/test_config/new_from_ini.ini";
|
|
config.load_from_ini(path, ForwardCompatibilitySubstitutionRule::Disable);
|
|
THEN("Config object contains ini file options.") {
|
|
REQUIRE(config.option_throw<ConfigOptionStrings>("filament_colour", false)->values.size() == 1);
|
|
REQUIRE(config.option_throw<ConfigOptionStrings>("filament_colour", false)->values.front() == "#ABCD");
|
|
}
|
|
}
|
|
}
|
|
|
|
SCENARIO("DynamicPrintConfig serialization", "[Config]") {
|
|
WHEN("DynamicPrintConfig is serialized and deserialized") {
|
|
FullPrintConfig full_print_config;
|
|
DynamicPrintConfig cfg;
|
|
cfg.apply(full_print_config, false);
|
|
|
|
std::string serialized;
|
|
try {
|
|
std::ostringstream ss;
|
|
cereal::BinaryOutputArchive oarchive(ss);
|
|
oarchive(cfg);
|
|
serialized = ss.str();
|
|
} catch (const std::runtime_error & /* e */) {
|
|
// e.what();
|
|
}
|
|
|
|
THEN("Config object contains ini file options.") {
|
|
DynamicPrintConfig cfg2;
|
|
try {
|
|
std::stringstream ss(serialized);
|
|
cereal::BinaryInputArchive iarchive(ss);
|
|
iarchive(cfg2);
|
|
} catch (const std::runtime_error & /* e */) {
|
|
// e.what();
|
|
}
|
|
REQUIRE(cfg == cfg2);
|
|
}
|
|
}
|
|
}
|