From 20383ae3e721d93b6dce981b09475c4e2e524989 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Wed, 13 Nov 2024 17:05:33 -0800 Subject: [PATCH 1/3] Update deprecated Xcode in CI (#2114) This changelist updates a deprecated version of Xcode in our GitHub CI. --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c11603dd70..b2d5f182bf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -68,10 +68,10 @@ jobs: cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON python: 3.9 - - name: MacOS_Xcode_14_Python311 + - name: MacOS_Xcode_15_Python311 os: macos-14 compiler: xcode - compiler_version: "14.3" + compiler_version: "15.1" python: 3.11 static_analysis: ON cmake_config: -DCMAKE_EXPORT_COMPILE_COMMANDS=ON From 65dbd3937db8093011b825e9e5bf0b9ae9757abf Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Thu, 14 Nov 2024 10:31:09 -0500 Subject: [PATCH 2/3] Skip comments in functional equivalence tests (#2110) Skip `comment` blocks when checking for functional equivalency as they should not affect the comparison. --- source/MaterialXCore/Element.cpp | 22 ++++++++++++++++--- .../MaterialXTest/MaterialXCore/Document.cpp | 8 +++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp index 648d7df000..043d6f4092 100644 --- a/source/MaterialXCore/Element.cpp +++ b/source/MaterialXCore/Element.cpp @@ -426,9 +426,25 @@ bool Element::isEquivalent(ConstElementPtr rhs, const ElementEquivalenceOptions& } } - // Compare children. - const vector& children = getChildren(); - const vector& rhsChildren = rhs->getChildren(); + // Compare all child elements that affect functional equivalence. + vector children; + for (ElementPtr child : getChildren()) + { + if (child->getCategory() == CommentElement::CATEGORY) + { + continue; + } + children.push_back(child); + } + vector rhsChildren; + for (ElementPtr child : rhs->getChildren()) + { + if (child->getCategory() == CommentElement::CATEGORY) + { + continue; + } + rhsChildren.push_back(child); + } if (children.size() != rhsChildren.size()) { if (results) diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index ae7623084e..f3a207fc84 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -150,6 +150,9 @@ TEST_CASE("Document equivalence", "[document]") unsigned int index = 0; mx::ElementPtr child = doc->addNodeGraph("mygraph"); mx::NodeGraphPtr graph = child->asA(); + // Add comment block at the start of the first doc to check skipping + mx::ElementPtr comment = doc->addChildOfCategory(mx::CommentElement::CATEGORY); + comment->setDocString("Comment 1"); for (auto it = inputMap.begin(); it != inputMap.end(); ++it) { const std::string inputType = (*it).first; @@ -205,6 +208,11 @@ TEST_CASE("Document equivalence", "[document]") input->setName("input_" + inputType); } } + // Add comment blocks at end of second doc to check value and count checks + comment = doc2->addChildOfCategory(mx::CommentElement::CATEGORY); + comment->setDocString("Comment 2"); + comment = doc2->addChildOfCategory(mx::CommentElement::CATEGORY); + comment->setDocString("Comment 3"); mx::ElementEquivalenceOptions options; mx::ElementEquivalenceResultVec results; From a368aac8ccc4f8cf7a9d1d5189826b040eced893 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Sat, 16 Nov 2024 18:27:38 -0500 Subject: [PATCH 3/3] Cleanup options for equivalence testing (#2115) User facing naming changes for the functional equivalence API. There are no logic changes. --- source/MaterialXCore/Element.cpp | 12 +++--- source/MaterialXCore/Element.h | 37 +++++++++---------- .../MaterialXTest/MaterialXCore/Document.cpp | 12 +++--- .../PyMaterialX/PyMaterialXCore/PyElement.cpp | 8 ++-- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp index 043d6f4092..3bede2fe74 100644 --- a/source/MaterialXCore/Element.cpp +++ b/source/MaterialXCore/Element.cpp @@ -396,14 +396,14 @@ bool Element::isEquivalent(ConstElementPtr rhs, const ElementEquivalenceOptions& StringVec rhsAttributeNames = rhs->getAttributeNames(); // Filter out any attributes specified in the options. - const StringSet& skipAttributes = options.skipAttributes; - if (!skipAttributes.empty()) + const StringSet& attributeExclusionList = options.attributeExclusionList; + if (!attributeExclusionList.empty()) { attributeNames.erase(std::remove_if(attributeNames.begin(), attributeNames.end(), - [&skipAttributes](const string& attr) { return skipAttributes.find(attr) != skipAttributes.end(); }), + [&attributeExclusionList](const string& attr) { return attributeExclusionList.find(attr) != attributeExclusionList.end(); }), attributeNames.end()); rhsAttributeNames.erase(std::remove_if(rhsAttributeNames.begin(), rhsAttributeNames.end(), - [&skipAttributes](const string& attr) { return skipAttributes.find(attr) != skipAttributes.end(); }), + [&attributeExclusionList](const string& attr) { return attributeExclusionList.find(attr) != attributeExclusionList.end(); }), rhsAttributeNames.end()); } @@ -714,7 +714,7 @@ bool ValueElement::isAttributeEquivalent(ConstElementPtr rhs, const string& attr { // Perform value comparisons bool performedValueComparison = false; - if (!options.skipValueComparisons) + if (options.performValueComparisons) { const StringSet uiAttributes = { @@ -724,7 +724,7 @@ bool ValueElement::isAttributeEquivalent(ConstElementPtr rhs, const string& attr }; // Get precision and format options - ScopedFloatFormatting fmt(options.format, options.precision); + ScopedFloatFormatting fmt(options.floatFormat, options.floatPrecision); ConstValueElementPtr rhsValueElement = rhs->asA(); diff --git a/source/MaterialXCore/Element.h b/source/MaterialXCore/Element.h index fb4bbe07ce..05eb2235f3 100644 --- a/source/MaterialXCore/Element.h +++ b/source/MaterialXCore/Element.h @@ -1389,34 +1389,33 @@ class MX_CORE_API ElementEquivalenceOptions public: ElementEquivalenceOptions() { - format = Value::getFloatFormat(); - precision = Value::getFloatPrecision(); - skipAttributes = {}; - skipValueComparisons = false; + performValueComparisons = true; + floatFormat = Value::getFloatFormat(); + floatPrecision = Value::getFloatPrecision(); + attributeExclusionList = {}; }; ~ElementEquivalenceOptions() { } - /// Floating point format option for floating point value comparisons - Value::FloatFormat format; + /// Perform value comparisons as opposed to literal string comparisons. + /// Default is true. + bool performValueComparisons; - /// Floating point precision option for floating point value comparisons - int precision; + /// Floating point format to use for floating point value comparisons + Value::FloatFormat floatFormat; - /// Attribute filtering options. By default all attributes are considered. - /// Name, category attributes cannot be skipped. + /// Floating point precision to use for floating point value comparisons + int floatPrecision; + + /// Specifies the set of attributes that should be excluded when performing a comparison. + /// By default all attributes are considered. Name and category attributes cannot be excluded. /// - /// For example UI attribute comparision be skipped by setting: - /// skipAttributes = { + /// For example, to exclude UI and documentation attributes from consideration the follow may be set: + /// attributeExclusionList = { /// ValueElement::UI_MIN_ATTRIBUTE, ValueElement::UI_MAX_ATTRIBUTE, /// ValueElement::UI_SOFT_MIN_ATTRIBUTE, ValueElement::UI_SOFT_MAX_ATTRIBUTE, /// ValueElement::UI_STEP_ATTRIBUTE, Element::XPOS_ATTRIBUTE, - /// Element::YPOS_ATTRIBUTE }; - StringSet skipAttributes; - - /// Do not perform any value comparisions. Instead perform exact string comparisons for attributes - /// Default is false. The operator==() method can be used instead as it always performs - /// a strict comparison. Default is false. - bool skipValueComparisons; + /// Element::YPOS_ATTRIBUTE, Element::DOC_ATTRIBUTE }; + StringSet attributeExclusionList; }; /// @class ExceptionOrphanedElement diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index f3a207fc84..b593969ccb 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -217,27 +217,27 @@ TEST_CASE("Document equivalence", "[document]") mx::ElementEquivalenceOptions options; mx::ElementEquivalenceResultVec results; - // Check skipping all value compares - options.skipValueComparisons = true; + // Check that this fails when not performing value comparisons + options.performValueComparisons = false; bool equivalent = doc->isEquivalent(doc2, options, &results); REQUIRE(!equivalent); // Check attibute values - options.skipValueComparisons = false; + options.performValueComparisons = true; results.clear(); equivalent = doc->isEquivalent(doc2, options, &results); REQUIRE(equivalent); unsigned int currentPrecision = mx::Value::getFloatPrecision(); // This will compare 0.012345608 versus: 1, 0.012345611 for input10 - options.precision = 8; + options.floatPrecision = 8; equivalent = doc->isEquivalent(doc2, options); REQUIRE(!equivalent); - options.precision = currentPrecision; + options.floatPrecision = currentPrecision; // Check attribute filtering of inputs results.clear(); - options.skipAttributes = { mx::ValueElement::UI_MIN_ATTRIBUTE, mx::ValueElement::UI_MAX_ATTRIBUTE }; + options.attributeExclusionList = { mx::ValueElement::UI_MIN_ATTRIBUTE, mx::ValueElement::UI_MAX_ATTRIBUTE }; for (mx::InputPtr floatInput : floatInputs) { floatInput->setAttribute(mx::ValueElement::UI_MIN_ATTRIBUTE, "0.9"); diff --git a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp index cb70d04704..004fa0a670 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp @@ -224,10 +224,10 @@ void bindPyElement(py::module& mod) .def_readwrite("attributeName", &mx::ElementEquivalenceResult::attributeName); py::class_(mod, "ElementEquivalenceOptions") - .def_readwrite("format", &mx::ElementEquivalenceOptions::format) - .def_readwrite("precision", &mx::ElementEquivalenceOptions::precision) - .def_readwrite("skipAttributes", &mx::ElementEquivalenceOptions::skipAttributes) - .def_readwrite("skipValueComparisons", &mx::ElementEquivalenceOptions::skipValueComparisons) + .def_readwrite("performValueComparisons", &mx::ElementEquivalenceOptions::performValueComparisons) + .def_readwrite("floatFormat", &mx::ElementEquivalenceOptions::floatFormat) + .def_readwrite("floatPrecision", &mx::ElementEquivalenceOptions::floatPrecision) + .def_readwrite("attributeExclusionList", &mx::ElementEquivalenceOptions::attributeExclusionList) .def(py::init<>()); py::class_(mod, "StringResolver")