From 6e7c81b98680f07b277f224d7f12fcd1851fca80 Mon Sep 17 00:00:00 2001 From: Cory Cross Date: Tue, 4 Nov 2025 09:48:50 -0800 Subject: [PATCH] Add diff compare method for DynamicConfig Help the unit test report errors better. --- src/libslic3r/Config.cpp | 75 ++++++++++++++++++++++++++++++++++++++++ src/libslic3r/Config.hpp | 36 +++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index 75935b2177..ce1a8d6799 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -1703,6 +1703,81 @@ t_config_option_keys DynamicConfig::keys() const return keys; } +DynamicConfig::DynamicConfigDifference DynamicConfig::diff_report(const DynamicConfig& rhs) const { + DynamicConfig::DynamicConfigDifference result; + + std::set all_keys; + + for (const auto& kvp : this->options) { + all_keys.insert(kvp.first); + } + for (const auto& kvp : rhs.options) { + all_keys.insert(kvp.first); + } + + for (const auto& key : all_keys) { + auto left_it = this->options.find(key); + auto right_it = rhs.options.find(key); + + bool left_has = (left_it != this->options.end()); + bool right_has = (right_it != rhs.options.end()); + + if (left_has && right_has) { + if (*left_it->second != *right_it->second) { + result.differences[key] = { + left_it->second->serialize(), + right_it->second->serialize() + }; + } + } else if (left_has) { + result.differences[key] = { + left_it->second->serialize(), + std::nullopt + }; + } else if (right_has) { + result.differences[key] = { + std::nullopt, + right_it->second->serialize() + }; + } + } + return result; +} + +std::ostream& operator<<(std::ostream& os, const DynamicConfig::DynamicConfigDifference& diff) { + if (!diff.is_different()) { + os << "Configurations are identical.\n"; + return os; + } + + int missing_right=0, missing_left=0, differ=0; + os << "DynamicConfig Differences Found (" << diff.differences.size() << " keys):\n"; + for (const auto& kvp : diff.differences) { + const auto& key = kvp.first; + const auto& detail = kvp.second; + + os << " Key: **" << key << "**\n"; + + if (detail.is_missing_key()) { + // Determine which side is missing the key + if (detail.left_value.has_value()) { + os << " - **Missing in Right**: Key exists in left config. Value: " << detail.left_value.value() << "\n"; + missing_right++; + } else { + os << " - **Missing in Left**: Key exists in right config. Value: " << detail.right_value.value() << "\n"; + missing_left++; + } + } else if (detail.is_different_value()) { + differ++; + os << " - **Value Differs**:\n"; + os << " -> Left Value: " << detail.left_value.value() << "\n"; + os << " -> Right Value: " << detail.right_value.value() << "\n"; + } + } + os << "Summary: " << missing_right << " missing on right, " << missing_left << " missing on left, and " << differ << " have differing values\n"; + return os; +} + void StaticConfig::set_defaults() { // use defaults from definition diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 40c0fc7c5f..b94d617315 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -2783,6 +2783,40 @@ public: std::map>::const_iterator cend() const { return options.cend(); } size_t size() const { return options.size(); } + /** + * @brief Detailed information about the difference found for a single key. + */ + struct KeyDifference { + std::optional left_value; + std::optional right_value; + + bool is_missing_key() const { + return !left_value.has_value() || !right_value.has_value(); + } + bool is_different_value() const { + return left_value.has_value() && right_value.has_value() && (left_value.value() != right_value.value()); + } + }; + + /** + * @brief The full report object containing all detected differences. + */ + struct DynamicConfigDifference { + std::map differences; + + bool is_different() const { + return !differences.empty(); + } + }; + + /** + * @brief Computes the symmetric difference between this DynamicConfig (left) + * and another DynamicConfig (rhs). + * @param rhs The right-hand side config to compare against. + * @return DynamicConfigDifference report. + */ + DynamicConfigDifference diff_report(const DynamicConfig& rhs) const; + private: std::map> options; @@ -2790,6 +2824,8 @@ private: template void serialize(Archive &ar) { ar(options); } }; +std::ostream& operator<<(std::ostream& os, const DynamicConfig::DynamicConfigDifference& diff); + // Configuration store with a static definition of configuration values. // In Slic3r, the static configuration stores are during the slicing / g-code generation for efficiency reasons, // because the configuration values could be accessed directly.