This is an automated email from the ASF dual-hosted git repository.

martinzink pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git

commit 87be640553ea94ee870ecaf36e83e1d4b55ec63d
Author: Ferenc Gerlits <[email protected]>
AuthorDate: Mon Feb 14 10:08:57 2022 +0100

    MINIFICPP-1751 Bugfix: expression language properties could not be updated
    
    Closes #1258
    
    Signed-off-by: Martin Zink <[email protected]>
---
 .../expression-language/ProcessContextExpr.cpp     |  11 ++
 .../expression-language/ProcessContextExpr.h       |   4 +
 .../tests/ProcessContextExprTests.cpp              | 129 +++++++++++++++++++++
 libminifi/include/core/ProcessContext.h            |   8 +-
 4 files changed, 148 insertions(+), 4 deletions(-)

diff --git a/extensions/expression-language/ProcessContextExpr.cpp 
b/extensions/expression-language/ProcessContextExpr.cpp
index b9cc1d1..20af1b4 100644
--- a/extensions/expression-language/ProcessContextExpr.cpp
+++ b/extensions/expression-language/ProcessContextExpr.cpp
@@ -64,6 +64,17 @@ bool ProcessContextExpr::getDynamicProperty(const Property 
&property, std::strin
   return true;
 }
 
+
+bool ProcessContextExpr::setProperty(const std::string& property, std::string 
value) {
+  expressions_.erase(property);
+  return ProcessContext::setProperty(property, value);
+}
+
+bool ProcessContextExpr::setDynamicProperty(const std::string& property, 
std::string value) {
+  dynamic_property_expressions_.erase(property);
+  return ProcessContext::setDynamicProperty(property, value);
+}
+
 } /* namespace core */
 } /* namespace minifi */
 } /* namespace nifi */
diff --git a/extensions/expression-language/ProcessContextExpr.h 
b/extensions/expression-language/ProcessContextExpr.h
index 31f48ef..f8d0310 100644
--- a/extensions/expression-language/ProcessContextExpr.h
+++ b/extensions/expression-language/ProcessContextExpr.h
@@ -65,6 +65,10 @@ class ProcessContextExpr final : public core::ProcessContext 
{
 
   bool getDynamicProperty(const Property &property, std::string &value, const 
std::shared_ptr<FlowFile> &flow_file) override;
 
+  bool setProperty(const std::string& property, std::string value) override;
+
+  bool setDynamicProperty(const std::string& property, std::string value) 
override;
+
  private:
   std::unordered_map<std::string, 
org::apache::nifi::minifi::expression::Expression> expressions_;
   std::unordered_map<std::string, 
org::apache::nifi::minifi::expression::Expression> 
dynamic_property_expressions_;
diff --git a/extensions/expression-language/tests/ProcessContextExprTests.cpp 
b/extensions/expression-language/tests/ProcessContextExprTests.cpp
new file mode 100644
index 0000000..2cb5974
--- /dev/null
+++ b/extensions/expression-language/tests/ProcessContextExprTests.cpp
@@ -0,0 +1,129 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <string>
+
+#include "core/ProcessContext.h"
+#include "core/Resource.h"
+#include "ProcessContextExpr.h"
+#include "Processor.h"
+#include "Property.h"
+#include "TestBase.h"
+
+namespace org::apache::nifi::minifi {
+
+class DummyProcessor : public core::Processor {
+ public:
+  using core::Processor::Processor;
+  EXTENSIONAPI static core::Property SimpleProperty;
+  EXTENSIONAPI static core::Property ExpressionLanguageProperty;
+  void initialize() override { setSupportedProperties({SimpleProperty, 
ExpressionLanguageProperty}); }
+  bool supportsDynamicProperties() override { return true; }
+};
+
+core::Property DummyProcessor::SimpleProperty{
+    core::PropertyBuilder::createProperty("Simple Property")
+        ->withDescription("Just a simple string property")
+        ->build()};
+
+core::Property DummyProcessor::ExpressionLanguageProperty{
+    core::PropertyBuilder::createProperty("Expression Language Property")
+        ->withDescription("A property which supports expression language")
+        ->supportsExpressionLanguage(true)
+        ->build()};
+
+REGISTER_RESOURCE(DummyProcessor, "A processor that does nothing.");
+
+}  // namespace org::apache::nifi::minifi
+
+TEST_CASE("ProcessContextExpr can update existing processor properties", 
"[setProperty][getProperty]") {
+  TestController test_controller;
+  std::shared_ptr<TestPlan> test_plan = test_controller.createPlan();
+  std::shared_ptr<minifi::core::Processor> dummy_processor = 
test_plan->addProcessor("DummyProcessor", "dummy_processor");
+  std::shared_ptr<minifi::core::ProcessContext> context = [test_plan] { 
test_plan->runNextProcessor(); return test_plan->getCurrentContext(); }();
+  REQUIRE(dynamic_pointer_cast<minifi::core::ProcessContextExpr>(context) != 
nullptr);
+
+  SECTION("Set and get simple property") {
+    SECTION("Using a Property reference parameter") {
+      context->setProperty(minifi::DummyProcessor::SimpleProperty, "foo");
+      CHECK(context->getProperty(minifi::DummyProcessor::SimpleProperty, 
nullptr) == "foo");
+
+      context->setProperty(minifi::DummyProcessor::SimpleProperty, "bar");
+      CHECK(context->getProperty(minifi::DummyProcessor::SimpleProperty, 
nullptr) == "bar");
+    }
+
+    SECTION("Using a string parameter") {
+      context->setProperty(minifi::DummyProcessor::SimpleProperty.getName(), 
"foo");
+      CHECK(context->getProperty(minifi::DummyProcessor::SimpleProperty, 
nullptr) == "foo");
+
+      context->setProperty(minifi::DummyProcessor::SimpleProperty.getName(), 
"bar");
+      CHECK(context->getProperty(minifi::DummyProcessor::SimpleProperty, 
nullptr) == "bar");
+    }
+  }
+
+  SECTION("Set and get expression language property") {
+    SECTION("Using a Property reference parameter") {
+      context->setProperty(minifi::DummyProcessor::ExpressionLanguageProperty, 
"foo");
+      
CHECK(context->getProperty(minifi::DummyProcessor::ExpressionLanguageProperty, 
nullptr) == "foo");
+
+      context->setProperty(minifi::DummyProcessor::ExpressionLanguageProperty, 
"bar");
+      
CHECK(context->getProperty(minifi::DummyProcessor::ExpressionLanguageProperty, 
nullptr) == "bar");
+    }
+
+    SECTION("Using a string parameter") {
+      
context->setProperty(minifi::DummyProcessor::ExpressionLanguageProperty.getName(),
 "foo");
+      
CHECK(context->getProperty(minifi::DummyProcessor::ExpressionLanguageProperty, 
nullptr) == "foo");
+
+      
context->setProperty(minifi::DummyProcessor::ExpressionLanguageProperty.getName(),
 "bar");
+      
CHECK(context->getProperty(minifi::DummyProcessor::ExpressionLanguageProperty, 
nullptr) == "bar");
+    }
+  }
+
+  SECTION("Set and get simple dynamic property") {
+    const auto simple_property{
+        minifi::core::PropertyBuilder::createProperty("Simple Dynamic 
Property")
+        ->withDescription("A simple dynamic string property")
+        ->build()};
+    std::string property_value;
+
+    context->setDynamicProperty(simple_property.getName(), "foo");
+    CHECK(context->getDynamicProperty(simple_property, property_value, 
nullptr));
+    CHECK(property_value == "foo");
+
+    context->setDynamicProperty(simple_property.getName(), "bar");
+    CHECK(context->getDynamicProperty(simple_property, property_value, 
nullptr));
+    CHECK(property_value == "bar");
+  }
+
+  SECTION("Set and get expression language dynamic property") {
+    const auto expression_language_property{
+        minifi::core::PropertyBuilder::createProperty("Expression Language 
Dynamic Property")
+        ->withDescription("A dynamic property which supports expression 
language")
+        ->supportsExpressionLanguage(true)
+        ->build()};
+    std::string property_value;
+
+    context->setDynamicProperty(expression_language_property.getName(), "foo");
+    CHECK(context->getDynamicProperty(expression_language_property, 
property_value, nullptr));
+    CHECK(property_value == "foo");
+
+    context->setDynamicProperty(expression_language_property.getName(), "bar");
+    CHECK(context->getDynamicProperty(expression_language_property, 
property_value, nullptr));
+    CHECK(property_value == "bar");
+  }
+}
diff --git a/libminifi/include/core/ProcessContext.h 
b/libminifi/include/core/ProcessContext.h
index 40de4ff..c134305 100644
--- a/libminifi/include/core/ProcessContext.h
+++ b/libminifi/include/core/ProcessContext.h
@@ -151,15 +151,15 @@ class ProcessContext : public 
controller::ControllerServiceLookup, public core::
     return processor_node_->getDynamicPropertyKeys();
   }
   // Sets the property value using the property's string name
-  bool setProperty(const std::string &name, std::string value) {
+  virtual bool setProperty(const std::string &name, std::string value) {
     return processor_node_->setProperty(name, value);
   }  // Sets the dynamic property value using the property's string name
-  bool setDynamicProperty(const std::string &name, std::string value) {
+  virtual bool setDynamicProperty(const std::string &name, std::string value) {
     return processor_node_->setDynamicProperty(name, value);
   }
   // Sets the property value using the Property object
-  bool setProperty(const Property& prop, std::string value) {
-    return processor_node_->setProperty(prop, value);
+  bool setProperty(const Property& property, std::string value) {
+    return setProperty(property.getName(), value);
   }
   // Whether the relationship is supported
   bool isSupportedRelationship(Relationship relationship) const {

Reply via email to