Ported test_config.cpp from upstream Slic3r.
Extended ConfigBase with set() functions similar to the upstream Slic3r. ConfigBase::set_deserialize() newly throws if the operation fails. Extrusion width parameters are newly tested for negative values.
This commit is contained in:
parent
b7af51fd6d
commit
13cc74ef0a
@ -425,7 +425,30 @@ std::string ConfigBase::opt_serialize(const t_config_option_key &opt_key) const
|
|||||||
return opt->serialize();
|
return opt->serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfigBase::set_deserialize(const t_config_option_key &opt_key_src, const std::string &value_src, bool append)
|
void ConfigBase::set(const std::string &opt_key, int value, bool create)
|
||||||
|
{
|
||||||
|
ConfigOption *opt = this->option_throw(opt_key, create);
|
||||||
|
switch (opt->type()) {
|
||||||
|
case coInt: static_cast<ConfigOptionInt*>(opt)->value = value; break;
|
||||||
|
case coFloat: static_cast<ConfigOptionFloat*>(opt)->value = value; break;
|
||||||
|
case coFloatOrPercent: static_cast<ConfigOptionFloatOrPercent*>(opt)->value = value; static_cast<ConfigOptionFloatOrPercent*>(opt)->percent = false; break;
|
||||||
|
case coString: static_cast<ConfigOptionString*>(opt)->value = std::to_string(value); break;
|
||||||
|
default: throw BadOptionTypeException("Configbase::set() - conversion from int not possible");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigBase::set(const std::string &opt_key, double value, bool create)
|
||||||
|
{
|
||||||
|
ConfigOption *opt = this->option_throw(opt_key, create);
|
||||||
|
switch (opt->type()) {
|
||||||
|
case coFloat: static_cast<ConfigOptionFloat*>(opt)->value = value; break;
|
||||||
|
case coFloatOrPercent: static_cast<ConfigOptionFloatOrPercent*>(opt)->value = value; static_cast<ConfigOptionFloatOrPercent*>(opt)->percent = false; break;
|
||||||
|
case coString: static_cast<ConfigOptionString*>(opt)->value = std::to_string(value); break;
|
||||||
|
default: throw BadOptionTypeException("Configbase::set() - conversion from float not possible");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigBase::set_deserialize_nothrow(const t_config_option_key &opt_key_src, const std::string &value_src, bool append)
|
||||||
{
|
{
|
||||||
t_config_option_key opt_key = opt_key_src;
|
t_config_option_key opt_key = opt_key_src;
|
||||||
std::string value = value_src;
|
std::string value = value_src;
|
||||||
@ -438,12 +461,16 @@ bool ConfigBase::set_deserialize(const t_config_option_key &opt_key_src, const s
|
|||||||
return this->set_deserialize_raw(opt_key, value, append);
|
return this->set_deserialize_raw(opt_key, value, append);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfigBase::set_deserialize(std::initializer_list<SetDeserializeItem> items)
|
void ConfigBase::set_deserialize(const t_config_option_key &opt_key_src, const std::string &value_src, bool append)
|
||||||
|
{
|
||||||
|
if (! this->set_deserialize_nothrow(opt_key_src, value_src, append))
|
||||||
|
throw BadOptionTypeException("ConfigBase::set_deserialize() failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigBase::set_deserialize(std::initializer_list<SetDeserializeItem> items)
|
||||||
{
|
{
|
||||||
bool deserialized = true;
|
|
||||||
for (const SetDeserializeItem &item : items)
|
for (const SetDeserializeItem &item : items)
|
||||||
deserialized &= this->set_deserialize(item.opt_key, item.opt_value, item.append);
|
this->set_deserialize(item.opt_key, item.opt_value, item.append);
|
||||||
return deserialized;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfigBase::set_deserialize_raw(const t_config_option_key &opt_key_src, const std::string &value, bool append)
|
bool ConfigBase::set_deserialize_raw(const t_config_option_key &opt_key_src, const std::string &value, bool append)
|
||||||
@ -831,7 +858,7 @@ bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra,
|
|||||||
static_cast<ConfigOptionString*>(opt_base)->value = value;
|
static_cast<ConfigOptionString*>(opt_base)->value = value;
|
||||||
} else {
|
} else {
|
||||||
// Any scalar value of a type different from Bool and String.
|
// Any scalar value of a type different from Bool and String.
|
||||||
if (! this->set_deserialize(opt_key, value, false)) {
|
if (! this->set_deserialize_nothrow(opt_key, value, false)) {
|
||||||
boost::nowide::cerr << "Invalid value supplied for --" << token.c_str() << std::endl;
|
boost::nowide::cerr << "Invalid value supplied for --" << token.c_str() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,16 @@ public:
|
|||||||
std::runtime_error(std::string("No definition exception: ") + opt_key) {}
|
std::runtime_error(std::string("No definition exception: ") + opt_key) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Indicate that an unsupported accessor was called on a config option.
|
||||||
|
class BadOptionTypeException : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BadOptionTypeException() :
|
||||||
|
std::runtime_error("Bad option type exception") {}
|
||||||
|
BadOptionTypeException(const char* message) :
|
||||||
|
std::runtime_error(message) {}
|
||||||
|
};
|
||||||
|
|
||||||
// Type of a configuration value.
|
// Type of a configuration value.
|
||||||
enum ConfigOptionType {
|
enum ConfigOptionType {
|
||||||
coVectorType = 0x4000,
|
coVectorType = 0x4000,
|
||||||
@ -117,10 +127,10 @@ public:
|
|||||||
virtual ConfigOption* clone() const = 0;
|
virtual ConfigOption* clone() const = 0;
|
||||||
// Set a value from a ConfigOption. The two options should be compatible.
|
// Set a value from a ConfigOption. The two options should be compatible.
|
||||||
virtual void set(const ConfigOption *option) = 0;
|
virtual void set(const ConfigOption *option) = 0;
|
||||||
virtual int getInt() const { throw std::runtime_error("Calling ConfigOption::getInt on a non-int ConfigOption"); }
|
virtual int getInt() const { throw BadOptionTypeException("Calling ConfigOption::getInt on a non-int ConfigOption"); }
|
||||||
virtual double getFloat() const { throw std::runtime_error("Calling ConfigOption::getFloat on a non-float ConfigOption"); }
|
virtual double getFloat() const { throw BadOptionTypeException("Calling ConfigOption::getFloat on a non-float ConfigOption"); }
|
||||||
virtual bool getBool() const { throw std::runtime_error("Calling ConfigOption::getBool on a non-boolean ConfigOption"); }
|
virtual bool getBool() const { throw BadOptionTypeException("Calling ConfigOption::getBool on a non-boolean ConfigOption"); }
|
||||||
virtual void setInt(int /* val */) { throw std::runtime_error("Calling ConfigOption::setInt on a non-int ConfigOption"); }
|
virtual void setInt(int /* val */) { throw BadOptionTypeException("Calling ConfigOption::setInt on a non-int ConfigOption"); }
|
||||||
virtual bool operator==(const ConfigOption &rhs) const = 0;
|
virtual bool operator==(const ConfigOption &rhs) const = 0;
|
||||||
bool operator!=(const ConfigOption &rhs) const { return ! (*this == rhs); }
|
bool operator!=(const ConfigOption &rhs) const { return ! (*this == rhs); }
|
||||||
bool is_scalar() const { return (int(this->type()) & int(coVectorType)) == 0; }
|
bool is_scalar() const { return (int(this->type()) & int(coVectorType)) == 0; }
|
||||||
@ -1513,32 +1523,48 @@ protected:
|
|||||||
public:
|
public:
|
||||||
// Non-virtual methods:
|
// Non-virtual methods:
|
||||||
bool has(const t_config_option_key &opt_key) const { return this->option(opt_key) != nullptr; }
|
bool has(const t_config_option_key &opt_key) const { return this->option(opt_key) != nullptr; }
|
||||||
|
|
||||||
const ConfigOption* option(const t_config_option_key &opt_key) const
|
const ConfigOption* option(const t_config_option_key &opt_key) const
|
||||||
{ return const_cast<ConfigBase*>(this)->option(opt_key, false); }
|
{ return const_cast<ConfigBase*>(this)->option(opt_key, false); }
|
||||||
|
|
||||||
ConfigOption* option(const t_config_option_key &opt_key, bool create = false)
|
ConfigOption* option(const t_config_option_key &opt_key, bool create = false)
|
||||||
{ return this->optptr(opt_key, create); }
|
{ return this->optptr(opt_key, create); }
|
||||||
|
|
||||||
template<typename TYPE>
|
template<typename TYPE>
|
||||||
TYPE* option(const t_config_option_key &opt_key, bool create = false)
|
TYPE* option(const t_config_option_key &opt_key, bool create = false)
|
||||||
{
|
{
|
||||||
ConfigOption *opt = this->optptr(opt_key, create);
|
ConfigOption *opt = this->optptr(opt_key, create);
|
||||||
return (opt == nullptr || opt->type() != TYPE::static_type()) ? nullptr : static_cast<TYPE*>(opt);
|
return (opt == nullptr || opt->type() != TYPE::static_type()) ? nullptr : static_cast<TYPE*>(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TYPE>
|
template<typename TYPE>
|
||||||
const TYPE* option(const t_config_option_key &opt_key) const
|
const TYPE* option(const t_config_option_key &opt_key) const
|
||||||
{ return const_cast<ConfigBase*>(this)->option<TYPE>(opt_key, false); }
|
{ return const_cast<ConfigBase*>(this)->option<TYPE>(opt_key, false); }
|
||||||
template<typename TYPE>
|
|
||||||
TYPE* option_throw(const t_config_option_key &opt_key, bool create = false)
|
ConfigOption* option_throw(const t_config_option_key &opt_key, bool create = false)
|
||||||
{
|
{
|
||||||
ConfigOption *opt = this->optptr(opt_key, create);
|
ConfigOption *opt = this->optptr(opt_key, create);
|
||||||
if (opt == nullptr)
|
if (opt == nullptr)
|
||||||
throw UnknownOptionException(opt_key);
|
throw UnknownOptionException(opt_key);
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ConfigOption* option_throw(const t_config_option_key &opt_key) const
|
||||||
|
{ return const_cast<ConfigBase*>(this)->option_throw(opt_key, false); }
|
||||||
|
|
||||||
|
template<typename TYPE>
|
||||||
|
TYPE* option_throw(const t_config_option_key &opt_key, bool create = false)
|
||||||
|
{
|
||||||
|
ConfigOption *opt = this->option_throw(opt_key, create);
|
||||||
if (opt->type() != TYPE::static_type())
|
if (opt->type() != TYPE::static_type())
|
||||||
throw std::runtime_error("Conversion to a wrong type");
|
throw BadOptionTypeException("Conversion to a wrong type");
|
||||||
return static_cast<TYPE*>(opt);
|
return static_cast<TYPE*>(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TYPE>
|
template<typename TYPE>
|
||||||
const TYPE* option_throw(const t_config_option_key &opt_key) const
|
const TYPE* option_throw(const t_config_option_key &opt_key) const
|
||||||
{ return const_cast<ConfigBase*>(this)->option_throw<TYPE>(opt_key, false); }
|
{ return const_cast<ConfigBase*>(this)->option_throw<TYPE>(opt_key, false); }
|
||||||
|
|
||||||
// Apply all keys of other ConfigBase defined by this->def() to this ConfigBase.
|
// Apply all keys of other ConfigBase defined by this->def() to this ConfigBase.
|
||||||
// An UnknownOptionException is thrown in case some option keys of other are not defined by this->def(),
|
// An UnknownOptionException is thrown in case some option keys of other are not defined by this->def(),
|
||||||
// or this ConfigBase is of a StaticConfig type and it does not support some of the keys, and ignore_nonexistent is not set.
|
// or this ConfigBase is of a StaticConfig type and it does not support some of the keys, and ignore_nonexistent is not set.
|
||||||
@ -1551,9 +1577,25 @@ public:
|
|||||||
t_config_option_keys diff(const ConfigBase &other) const;
|
t_config_option_keys diff(const ConfigBase &other) const;
|
||||||
t_config_option_keys equal(const ConfigBase &other) const;
|
t_config_option_keys equal(const ConfigBase &other) const;
|
||||||
std::string opt_serialize(const t_config_option_key &opt_key) const;
|
std::string opt_serialize(const t_config_option_key &opt_key) const;
|
||||||
|
|
||||||
|
// Set a value. Convert numeric types using a C style implicit conversion / promotion model.
|
||||||
|
// Throw if option is not avaiable and create is not enabled,
|
||||||
|
// or if the conversion is not possible.
|
||||||
|
// Conversion to string is always possible.
|
||||||
|
void set(const std::string &opt_key, bool value, bool create = false)
|
||||||
|
{ this->option_throw<ConfigOptionBool>(opt_key, create)->value = value; }
|
||||||
|
void set(const std::string &opt_key, int value, bool create = false);
|
||||||
|
void set(const std::string &opt_key, double value, bool create = false);
|
||||||
|
void set(const std::string &opt_key, const char *value, bool create = false)
|
||||||
|
{ this->option_throw<ConfigOptionString>(opt_key, create)->value = value; }
|
||||||
|
void set(const std::string &opt_key, const std::string &value, bool create = false)
|
||||||
|
{ this->option_throw<ConfigOptionString>(opt_key, create)->value = value; }
|
||||||
|
|
||||||
// Set a configuration value from a string, it will call an overridable handle_legacy()
|
// Set a configuration value from a string, it will call an overridable handle_legacy()
|
||||||
// to resolve renamed and removed configuration keys.
|
// to resolve renamed and removed configuration keys.
|
||||||
bool set_deserialize(const t_config_option_key &opt_key, const std::string &str, bool append = false);
|
bool set_deserialize_nothrow(const t_config_option_key &opt_key_src, const std::string &value_src, bool append = false);
|
||||||
|
// May throw BadOptionTypeException() if the operation fails.
|
||||||
|
void set_deserialize(const t_config_option_key &opt_key, const std::string &str, bool append = false);
|
||||||
struct SetDeserializeItem {
|
struct SetDeserializeItem {
|
||||||
SetDeserializeItem(const char *opt_key, const char *opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
|
SetDeserializeItem(const char *opt_key, const char *opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
|
||||||
SetDeserializeItem(const std::string &opt_key, const std::string &opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
|
SetDeserializeItem(const std::string &opt_key, const std::string &opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
|
||||||
@ -1567,7 +1609,8 @@ public:
|
|||||||
SetDeserializeItem(const std::string &opt_key, const double value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {}
|
SetDeserializeItem(const std::string &opt_key, const double value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {}
|
||||||
std::string opt_key; std::string opt_value; bool append = false;
|
std::string opt_key; std::string opt_value; bool append = false;
|
||||||
};
|
};
|
||||||
bool set_deserialize(std::initializer_list<SetDeserializeItem> items);
|
// May throw BadOptionTypeException() if the operation fails.
|
||||||
|
void set_deserialize(std::initializer_list<SetDeserializeItem> items);
|
||||||
|
|
||||||
double get_abs_value(const t_config_option_key &opt_key) const;
|
double get_abs_value(const t_config_option_key &opt_key) const;
|
||||||
double get_abs_value(const t_config_option_key &opt_key, double ratio_over) const;
|
double get_abs_value(const t_config_option_key &opt_key, double ratio_over) const;
|
||||||
|
@ -433,6 +433,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
"If left zero, default extrusion width will be used if set, otherwise 1.125 x nozzle diameter will be used. "
|
"If left zero, default extrusion width will be used if set, otherwise 1.125 x nozzle diameter will be used. "
|
||||||
"If expressed as percentage (for example 200%), it will be computed over layer height.");
|
"If expressed as percentage (for example 200%), it will be computed over layer height.");
|
||||||
def->sidetext = L("mm or %");
|
def->sidetext = L("mm or %");
|
||||||
|
def->min = 0;
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
||||||
|
|
||||||
@ -541,6 +542,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
"(see the tooltips for perimeter extrusion width, infill extrusion width etc). "
|
"(see the tooltips for perimeter extrusion width, infill extrusion width etc). "
|
||||||
"If expressed as percentage (for example: 230%), it will be computed over layer height.");
|
"If expressed as percentage (for example: 230%), it will be computed over layer height.");
|
||||||
def->sidetext = L("mm or %");
|
def->sidetext = L("mm or %");
|
||||||
|
def->min = 0;
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
||||||
|
|
||||||
@ -863,6 +865,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
"If set to zero, it will use the default extrusion width.");
|
"If set to zero, it will use the default extrusion width.");
|
||||||
def->sidetext = L("mm or %");
|
def->sidetext = L("mm or %");
|
||||||
def->ratio_over = "first_layer_height";
|
def->ratio_over = "first_layer_height";
|
||||||
|
def->min = 0;
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloatOrPercent(200, true));
|
def->set_default_value(new ConfigOptionFloatOrPercent(200, true));
|
||||||
|
|
||||||
@ -994,6 +997,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
"You may want to use fatter extrudates to speed up the infill and make your parts stronger. "
|
"You may want to use fatter extrudates to speed up the infill and make your parts stronger. "
|
||||||
"If expressed as percentage (for example 90%) it will be computed over layer height.");
|
"If expressed as percentage (for example 90%) it will be computed over layer height.");
|
||||||
def->sidetext = L("mm or %");
|
def->sidetext = L("mm or %");
|
||||||
|
def->min = 0;
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
||||||
|
|
||||||
@ -1406,6 +1410,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
"If expressed as percentage (for example 200%) it will be computed over layer height.");
|
"If expressed as percentage (for example 200%) it will be computed over layer height.");
|
||||||
def->sidetext = L("mm or %");
|
def->sidetext = L("mm or %");
|
||||||
def->aliases = { "perimeters_extrusion_width" };
|
def->aliases = { "perimeters_extrusion_width" };
|
||||||
|
def->min = 0;
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
||||||
|
|
||||||
@ -1743,6 +1748,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
"If left zero, default extrusion width will be used if set, otherwise 1.125 x nozzle diameter will be used. "
|
"If left zero, default extrusion width will be used if set, otherwise 1.125 x nozzle diameter will be used. "
|
||||||
"If expressed as percentage (for example 90%) it will be computed over layer height.");
|
"If expressed as percentage (for example 90%) it will be computed over layer height.");
|
||||||
def->sidetext = L("mm or %");
|
def->sidetext = L("mm or %");
|
||||||
|
def->min = 0;
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
||||||
|
|
||||||
@ -1917,6 +1923,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
"If left zero, default extrusion width will be used if set, otherwise nozzle diameter will be used. "
|
"If left zero, default extrusion width will be used if set, otherwise nozzle diameter will be used. "
|
||||||
"If expressed as percentage (for example 90%) it will be computed over layer height.");
|
"If expressed as percentage (for example 90%) it will be computed over layer height.");
|
||||||
def->sidetext = L("mm or %");
|
def->sidetext = L("mm or %");
|
||||||
|
def->min = 0;
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
||||||
|
|
||||||
@ -2076,6 +2083,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
"If left zero, default extrusion width will be used if set, otherwise nozzle diameter will be used. "
|
"If left zero, default extrusion width will be used if set, otherwise nozzle diameter will be used. "
|
||||||
"If expressed as percentage (for example 90%) it will be computed over layer height.");
|
"If expressed as percentage (for example 90%) it will be computed over layer height.");
|
||||||
def->sidetext = L("mm or %");
|
def->sidetext = L("mm or %");
|
||||||
|
def->min = 0;
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
||||||
|
|
||||||
|
1
tests/data/test_config/new_from_ini.ini
Normal file
1
tests/data/test_config/new_from_ini.ini
Normal file
@ -0,0 +1 @@
|
|||||||
|
filament_colour = #ABCD
|
@ -2,6 +2,7 @@ get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
|
|||||||
add_executable(${_TEST_NAME}_tests
|
add_executable(${_TEST_NAME}_tests
|
||||||
${_TEST_NAME}_tests.cpp
|
${_TEST_NAME}_tests.cpp
|
||||||
test_3mf.cpp
|
test_3mf.cpp
|
||||||
|
test_config.cpp
|
||||||
test_geometry.cpp
|
test_geometry.cpp
|
||||||
test_polygon.cpp
|
test_polygon.cpp
|
||||||
)
|
)
|
||||||
|
203
tests/libslic3r/test_config.cpp
Normal file
203
tests/libslic3r/test_config.cpp
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
#include "libslic3r/PrintConfig.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( "perimeter_extrusion_width is set to 250%, a valid value") {
|
||||||
|
config.set_deserialize("perimeter_extrusion_width", "250%");
|
||||||
|
THEN( "The config is read as valid.") {
|
||||||
|
REQUIRE(config.validate().empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "perimeter_extrusion_width is set to -10, an invalid value") {
|
||||||
|
config.set("perimeter_extrusion_width", -10);
|
||||||
|
THEN( "Validate returns error") {
|
||||||
|
REQUIRE(! config.validate().empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN( "perimeters is set to -10, an invalid value") {
|
||||||
|
config.set("perimeters", -10);
|
||||||
|
THEN( "Validate returns error") {
|
||||||
|
REQUIRE(! 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("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("bed_temperature", "100");
|
||||||
|
THEN("The underlying value is set correctly.") {
|
||||||
|
REQUIRE(config.opt<ConfigOptionInts>("bed_temperature")->get_at(0) == 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
//FIXME better design accessors for vector elements.
|
||||||
|
WHEN("An integer-based option is set through the integer interface") {
|
||||||
|
config.set("bed_temperature", 100);
|
||||||
|
THEN("The underlying value is set correctly.") {
|
||||||
|
REQUIRE(config.opt<ConfigOptionInts>("bed_temperature")->get_at(0) == 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
WHEN("An floating-point option is set through the integer interface") {
|
||||||
|
config.set("perimeter_speed", 10);
|
||||||
|
THEN("The underlying value is set correctly.") {
|
||||||
|
REQUIRE(config.opt<ConfigOptionFloat>("perimeter_speed")->getFloat() == 10.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("A floating-point option is set through the double interface") {
|
||||||
|
config.set("perimeter_speed", 5.5);
|
||||||
|
THEN("The underlying value is set correctly.") {
|
||||||
|
REQUIRE(config.opt<ConfigOptionFloat>("perimeter_speed")->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("bed_temperature", 5.5), BadOptionTypeException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("A numeric option is set to a non-numeric value.") {
|
||||||
|
THEN("A BadOptionTypeException exception is thown.") {
|
||||||
|
REQUIRE_THROWS_AS(config.set_deserialize("perimeter_speed", "zzzz"), BadOptionTypeException);
|
||||||
|
}
|
||||||
|
THEN("The value does not change.") {
|
||||||
|
REQUIRE(config.opt<ConfigOptionFloat>("perimeter_speed")->getFloat() == 60.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("A string option is set through the string interface") {
|
||||||
|
config.set("printhost_apikey", "100");
|
||||||
|
THEN("The underlying value is set correctly.") {
|
||||||
|
REQUIRE(config.opt<ConfigOptionString>("printhost_apikey")->value == "100");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("A string option is set through the integer interface") {
|
||||||
|
config.set("printhost_apikey", 100);
|
||||||
|
THEN("The underlying value is set correctly.") {
|
||||||
|
REQUIRE(config.opt<ConfigOptionString>("printhost_apikey")->value == "100");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("A string option is set through the double interface") {
|
||||||
|
config.set("printhost_apikey", 100.5);
|
||||||
|
THEN("The underlying value is set correctly.") {
|
||||||
|
REQUIRE(config.opt<ConfigOptionString>("printhost_apikey")->value == std::to_string(100.5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN("A float or percent is set as a percent through the string interface.") {
|
||||||
|
config.set_deserialize("first_layer_extrusion_width", "100%");
|
||||||
|
THEN("Value and percent flag are 100/true") {
|
||||||
|
auto tmp = config.opt<ConfigOptionFloatOrPercent>("first_layer_extrusion_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("first_layer_extrusion_width", "100");
|
||||||
|
THEN("Value and percent flag are 100/false") {
|
||||||
|
auto tmp = config.opt<ConfigOptionFloatOrPercent>("first_layer_extrusion_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("first_layer_extrusion_width", 100);
|
||||||
|
THEN("Value and percent flag are 100/false") {
|
||||||
|
auto tmp = config.opt<ConfigOptionFloatOrPercent>("first_layer_extrusion_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("first_layer_extrusion_width", 100.5);
|
||||||
|
THEN("Value and percent flag are 100.5/false") {
|
||||||
|
auto tmp = config.opt<ConfigOptionFloatOrPercent>("first_layer_extrusion_width");
|
||||||
|
REQUIRE(tmp->percent == false);
|
||||||
|
REQUIRE(tmp->value == 100.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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") == 0.3);
|
||||||
|
REQUIRE(config.opt_int("raft_layers") == 0);
|
||||||
|
REQUIRE(config.opt_bool("support_material") == false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("getFloat called on an option that has been set.") {
|
||||||
|
config.set("layer_height", 0.5);
|
||||||
|
THEN("The set value is returned.") {
|
||||||
|
REQUIRE(config.opt_float("layer_height") == 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user