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 {
