mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-31 08:22:02 +08:00
Wrote accessor tests and accompanying implementation.
This commit is contained in:
parent
40cedc350c
commit
7861037556
@ -12,7 +12,7 @@ SCENARIO("Generic config validation performs as expected.") {
|
||||
GIVEN("A config generated from default options") {
|
||||
auto config {Slic3r::Config::new_from_defaults()};
|
||||
WHEN( "perimeter_extrusion_width is set to 250%, a valid value") {
|
||||
config->set("perimeter_extrusion_width", "250\%");
|
||||
config->set("perimeter_extrusion_width", "250%");
|
||||
THEN( "The config is read as valid.") {
|
||||
REQUIRE(config->validate() == true);
|
||||
}
|
||||
@ -29,59 +29,99 @@ SCENARIO("Generic config validation performs as expected.") {
|
||||
REQUIRE(except_thrown == true);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN( "perimeters is set to -10, an invalid value") {
|
||||
config->set("perimeters", -10);
|
||||
THEN( "An InvalidOptionValue exception is thrown.") {
|
||||
auto except_thrown {false};
|
||||
try {
|
||||
config->validate();
|
||||
} catch (const InvalidOptionValue& e) {
|
||||
except_thrown = true;
|
||||
}
|
||||
REQUIRE(except_thrown == true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Config accessor functions perform as expected.", "[!mayfail]") {
|
||||
SCENARIO("Config accessor functions perform as expected.") {
|
||||
GIVEN("A config generated from default options") {
|
||||
auto config {Slic3r::Config::new_from_defaults()};
|
||||
WHEN("A numeric option is set through the string interface") {
|
||||
config->set("bed_temperature", "100");
|
||||
THEN("The underlying value is set correctly.") {
|
||||
REQUIRE(false);
|
||||
REQUIRE(config->get<ConfigOptionInt>("bed_temperature").getInt() == 100);
|
||||
}
|
||||
}
|
||||
WHEN("An integer-based option is set through the integer interface") {
|
||||
config->set("bed_temperature", 100);
|
||||
THEN("The underlying value is set correctly.") {
|
||||
REQUIRE(false);
|
||||
REQUIRE(config->get<ConfigOptionInt>("bed_temperature").getInt() == 100);
|
||||
}
|
||||
}
|
||||
WHEN("An floating-point option is set through the integer interface") {
|
||||
config->set("perimeter_speed", 10);
|
||||
THEN("The underlying value is set correctly.") {
|
||||
REQUIRE(false);
|
||||
REQUIRE(config->get<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(false);
|
||||
REQUIRE(config->get<ConfigOptionFloat>("perimeter_speed").getFloat() == 5.5);
|
||||
}
|
||||
}
|
||||
WHEN("An integer-based option is set through the double interface") {
|
||||
config->set("bed_temperature", 5.5);
|
||||
THEN("The underlying value is set, rounded to the nearest integer.") {
|
||||
REQUIRE(false);
|
||||
REQUIRE(config->get<ConfigOptionInt>("bed_temperature").getInt() == 6);
|
||||
}
|
||||
}
|
||||
WHEN("A numeric option is set to a non-numeric value.") {
|
||||
auto except_thrown {false};
|
||||
try {
|
||||
config->set("perimeter_extrusion_width", "zzzz");
|
||||
} catch (const InvalidOptionType& e) {
|
||||
config->set("perimeter_speed", "zzzz");
|
||||
} catch (const InvalidOptionValue& e) {
|
||||
except_thrown = true;
|
||||
}
|
||||
THEN("An exception is thown.") {
|
||||
THEN("An InvalidOptionValue exception is thown.") {
|
||||
REQUIRE(except_thrown == true);
|
||||
}
|
||||
THEN("The value does not change.") {
|
||||
REQUIRE(false);
|
||||
REQUIRE(config->get<ConfigOptionFloat>("perimeter_speed").getFloat() == 60.0);
|
||||
}
|
||||
}
|
||||
WHEN("An invalid option is requested during set.") {
|
||||
WHEN("An invalid option is requested during set (string).") {
|
||||
auto except_thrown {false};
|
||||
try {
|
||||
config->set("deadbeef_invalid_option", "1");
|
||||
} catch (const InvalidOptionType& e) {
|
||||
except_thrown = true;
|
||||
}
|
||||
THEN("An exception is thrown.") {
|
||||
THEN("An InvalidOptionType exception is thrown.") {
|
||||
REQUIRE(except_thrown == true);
|
||||
}
|
||||
}
|
||||
WHEN("An invalid option is requested during set (double).") {
|
||||
auto except_thrown {false};
|
||||
try {
|
||||
config->set("deadbeef_invalid_option", 1.0);
|
||||
} catch (const InvalidOptionType& e) {
|
||||
except_thrown = true;
|
||||
}
|
||||
THEN("An InvalidOptionType exception is thrown.") {
|
||||
REQUIRE(except_thrown == true);
|
||||
}
|
||||
}
|
||||
WHEN("An invalid option is requested during set (int).") {
|
||||
auto except_thrown {false};
|
||||
try {
|
||||
config->set("deadbeef_invalid_option", 1);
|
||||
} catch (const InvalidOptionType& e) {
|
||||
except_thrown = true;
|
||||
}
|
||||
THEN("An InvalidOptionType exception is thrown.") {
|
||||
REQUIRE(except_thrown == true);
|
||||
}
|
||||
}
|
||||
@ -92,7 +132,18 @@ SCENARIO("Config accessor functions perform as expected.", "[!mayfail]") {
|
||||
} catch (const InvalidOptionType& e) {
|
||||
except_thrown = true;
|
||||
}
|
||||
THEN("An exception is thrown.") {
|
||||
THEN("An InvalidOptionType exception is thrown.") {
|
||||
REQUIRE(except_thrown == true);
|
||||
}
|
||||
}
|
||||
WHEN("An invalid option is requested during get_ptr.") {
|
||||
auto except_thrown {false};
|
||||
try {
|
||||
config->get_ptr<std::string>("deadbeef_invalid_option", false);
|
||||
} catch (const InvalidOptionType& e) {
|
||||
except_thrown = true;
|
||||
}
|
||||
THEN("An InvalidOptionType exception is thrown.") {
|
||||
REQUIRE(except_thrown == true);
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ Config::validate()
|
||||
try {
|
||||
tmp_opt = get_ptr<ConfigOptionVectorBase>(k);
|
||||
} catch (std::bad_cast) {
|
||||
throw InvalidOptionValue((std::string("Invalid value for ") + std::string(k)).c_str());
|
||||
throw InvalidOptionType((std::string("(cast failure) Invalid value for ") + std::string(k)).c_str());
|
||||
}
|
||||
auto tmp_str {tmp_opt->vserialize()};
|
||||
values.insert(values.end(), tmp_str.begin(), tmp_str.end());
|
||||
@ -75,11 +75,10 @@ Config::validate()
|
||||
}
|
||||
// Verify each value
|
||||
for (auto v : values) {
|
||||
Slic3r::Log::debug("Config::validate", v);
|
||||
if (type == "i" || type == "f" || opt.type == coPercent || opt.type == coFloatOrPercent) {
|
||||
if (opt.type == coPercent || opt.type == coFloatOrPercent)
|
||||
v = std::regex_replace(v, std::regex("%$"), std::string(""));
|
||||
if (!is_valid_int(type, opt, v) || !is_valid_float(type, opt, v)) {
|
||||
if ((type == "i" && !is_valid_int(type, opt, v)) || !is_valid_float(type, opt, v)) {
|
||||
throw InvalidOptionValue((std::string("Invalid value for ") + std::string(k)).c_str());
|
||||
}
|
||||
}
|
||||
@ -91,46 +90,130 @@ Config::validate()
|
||||
void
|
||||
Config::set(const t_config_option_key& opt_key, const std::string& value)
|
||||
{
|
||||
try {
|
||||
const auto& def {print_config_def.options.at(opt_key)};
|
||||
switch (def.type) {
|
||||
case coInt:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInt*>(this->optptr(opt_key, true))};
|
||||
ptr->setInt(std::stoi(value));
|
||||
} break;
|
||||
case coInts:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->optptr(opt_key, true))};
|
||||
if (!ptr->deserialize(value, true) ) {
|
||||
throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value."));
|
||||
}
|
||||
} break;
|
||||
case coFloat:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->optptr(opt_key, true))};
|
||||
ptr->setFloat(std::stod(value));
|
||||
} break;
|
||||
case coFloatOrPercent:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->optptr(opt_key, true))};
|
||||
const size_t perc = value.find("%");
|
||||
ptr->percent = (perc != std::string::npos);
|
||||
if (ptr->percent)
|
||||
ptr->setFloat(std::stod(std::string(value).replace(value.find("%"), std::string("%").length(), "")));
|
||||
else
|
||||
ptr->setFloat(std::stod(value));
|
||||
} break;
|
||||
case coFloats:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->optptr(opt_key, true))};
|
||||
if (!ptr->deserialize(value, true) ) {
|
||||
throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value."));
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
Slic3r::Log::warn("Config::set", "Unknown set type.");
|
||||
}
|
||||
} catch (std::invalid_argument &e) {
|
||||
throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value."));
|
||||
} catch (std::out_of_range &e) {
|
||||
throw InvalidOptionType(std::string(opt_key) + std::string(" is an invalid Slic3r option."));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::set(const t_config_option_key& opt_key, const int value)
|
||||
{
|
||||
const auto& def {print_config_def.options.at(opt_key)};
|
||||
switch (def.type) {
|
||||
case coInt:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInt*>(this->optptr(opt_key, true))};
|
||||
ptr->setInt(value);
|
||||
} break;
|
||||
case coInts:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(value), true);
|
||||
} break;
|
||||
case coFloat:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
} break;
|
||||
case coFloatOrPercent:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
} break;
|
||||
case coFloats:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(value), true);
|
||||
} break;
|
||||
default:
|
||||
Slic3r::Log::warn("Config::set", "Unknown set type.");
|
||||
try {
|
||||
const auto& def {print_config_def.options.at(opt_key)};
|
||||
switch (def.type) {
|
||||
case coInt:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInt*>(this->optptr(opt_key, true))};
|
||||
ptr->setInt(value);
|
||||
} break;
|
||||
case coInts:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(value), true);
|
||||
} break;
|
||||
case coFloat:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
} break;
|
||||
case coFloatOrPercent:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
} break;
|
||||
case coFloats:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(value), true);
|
||||
} break;
|
||||
default:
|
||||
Slic3r::Log::warn("Config::set", "Unknown set type.");
|
||||
}
|
||||
|
||||
} catch (std::out_of_range &e) {
|
||||
throw InvalidOptionType(std::string(opt_key) + std::string(" is an invalid Slic3r option."));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::set(const t_config_option_key& opt_key, const double value)
|
||||
{
|
||||
try {
|
||||
const auto& def {print_config_def.options.at(opt_key)};
|
||||
switch (def.type) {
|
||||
case coInt:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInt*>(this->optptr(opt_key, true))};
|
||||
ptr->setInt(std::round(value));
|
||||
} break;
|
||||
case coInts:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(std::round(value)), true);
|
||||
} break;
|
||||
case coFloat:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
} break;
|
||||
case coFloatOrPercent:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
} break;
|
||||
case coFloats:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(value), true);
|
||||
} break;
|
||||
default:
|
||||
Slic3r::Log::warn("Config::set", "Unknown set type.");
|
||||
}
|
||||
} catch (std::out_of_range &e) {
|
||||
throw InvalidOptionType(std::string(opt_key) + std::string(" is an invalid Slic3r option."));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -18,6 +18,7 @@ namespace Slic3r {
|
||||
class InvalidOptionValue : public std::runtime_error {
|
||||
public:
|
||||
InvalidOptionValue(const char* v) : runtime_error(v) {}
|
||||
InvalidOptionValue(const std::string v) : runtime_error(v.c_str()) {}
|
||||
};
|
||||
|
||||
/// Exception class to handle config options that don't exist.
|
||||
@ -27,6 +28,7 @@ class InvalidConfigOption : public std::runtime_error {};
|
||||
class InvalidOptionType : public std::runtime_error {
|
||||
public:
|
||||
InvalidOptionType(const char* v) : runtime_error(v) {}
|
||||
InvalidOptionType(const std::string v) : runtime_error(v.c_str()) {}
|
||||
};
|
||||
|
||||
class Config;
|
||||
@ -60,12 +62,14 @@ public:
|
||||
/// format than longwinded dynamic_cast<>
|
||||
template <class T>
|
||||
T& get(const t_config_option_key& opt_key, bool create=false) {
|
||||
if (print_config_def.options.count(opt_key) == 0) throw InvalidOptionType(opt_key + std::string(" is an invalid option."));
|
||||
return *(dynamic_cast<T*>(this->optptr(opt_key, create)));
|
||||
}
|
||||
|
||||
/// Template function to dynamic cast and leave it in pointer form.
|
||||
template <class T>
|
||||
T* get_ptr(const t_config_option_key& opt_key, bool create=false) {
|
||||
if (print_config_def.options.count(opt_key) == 0) throw InvalidOptionType(opt_key + std::string(" is an invalid option."));
|
||||
return dynamic_cast<T*>(this->optptr(opt_key, create));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user