You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ph...@apache.org on 2018/07/31 20:22:48 UTC

nifi-minifi-cpp git commit: MINIFICPP-465 Implemented regex validation of properties

Repository: nifi-minifi-cpp
Updated Branches:
  refs/heads/master 6beb78060 -> d5e5a4fea


MINIFICPP-465 Implemented regex validation of properties

This closes #350.

Signed-off-by: Marc Parisi <ph...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/commit/d5e5a4fe
Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/d5e5a4fe
Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/d5e5a4fe

Branch: refs/heads/master
Commit: d5e5a4feaceff572a12601d1ac200f2507d149fd
Parents: 6beb780
Author: Andrew I. Christianson <an...@andyic.org>
Authored: Thu May 31 12:03:50 2018 -0400
Committer: Marc Parisi <ph...@apache.org>
Committed: Tue Jul 31 16:22:33 2018 -0400

----------------------------------------------------------------------
 libminifi/src/core/Property.cpp                |  1 +
 libminifi/src/core/yaml/YamlConfiguration.cpp  | 26 +++++++--
 libminifi/test/unit/YamlConfigurationTests.cpp | 58 +++++++++++++++++++--
 3 files changed, 76 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/d5e5a4fe/libminifi/src/core/Property.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/Property.cpp b/libminifi/src/core/Property.cpp
index d5ff13a..4065dc7 100644
--- a/libminifi/src/core/Property.cpp
+++ b/libminifi/src/core/Property.cpp
@@ -73,6 +73,7 @@ const Property &Property::operator=(const Property &other) {
   description_ = other.description_;
   is_collection_ = other.is_collection_;
   is_required_ = other.is_required_;
+  valid_regex_ = other.valid_regex_;
   dependent_properties_ = other.dependent_properties_;
   exclusive_of_properties_ = other.exclusive_of_properties_;
   return *this;

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/d5e5a4fe/libminifi/src/core/yaml/YamlConfiguration.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/core/yaml/YamlConfiguration.cpp b/libminifi/src/core/yaml/YamlConfiguration.cpp
index f7bd4ba..902bd89 100644
--- a/libminifi/src/core/yaml/YamlConfiguration.cpp
+++ b/libminifi/src/core/yaml/YamlConfiguration.cpp
@@ -798,10 +798,9 @@ void YamlConfiguration::validateComponentProperties(const std::shared_ptr<Config
   for (const auto &prop_pair : component_properties) {
     if (prop_pair.second.getRequired()) {
       if (prop_pair.second.getValue().empty()) {
-        std::string reason("required property '");
-        reason.append(prop_pair.second.getName());
-        reason.append("' is not set");
-        raiseComponentError(component_name, yaml_section, reason);
+        std::stringstream reason;
+        reason << "required property '" << prop_pair.second.getName() << "' is not set";
+        raiseComponentError(component_name, yaml_section, reason.str());
       }
     }
   }
@@ -849,8 +848,27 @@ void YamlConfiguration::validateComponentProperties(const std::shared_ptr<Config
       }
     }
   }
+
+  // Validate regex properties
+  for (const auto &prop_pair : component_properties) {
+    const auto &prop_regex_str = prop_pair.second.getValidRegex();
+
+    if (!prop_regex_str.empty()) {
+      std::regex prop_regex(prop_regex_str);
+      if (!std::regex_match(prop_pair.second.getValue(), prop_regex)) {
+        std::stringstream reason;
+        reason << "property '"
+               << prop_pair.second.getName()
+               << "' does not match validation pattern '"
+               << prop_regex_str
+               << "'";
+        raiseComponentError(component_name, yaml_section, reason.str());
+      }
+    }
+  }
 #else
   logging::LOG_INFO(logger_) << "Validation of mutally-exclusive properties is disabled in this build.";
+  logging::LOG_INFO(logger_) << "Regex validation of properties is not available in this build.";
 #endif  // YAML_CONFIGURATION_USE_REGEX
 }
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/d5e5a4fe/libminifi/test/unit/YamlConfigurationTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/YamlConfigurationTests.cpp b/libminifi/test/unit/YamlConfigurationTests.cpp
index febf923..d495d75 100644
--- a/libminifi/test/unit/YamlConfigurationTests.cpp
+++ b/libminifi/test/unit/YamlConfigurationTests.cpp
@@ -18,7 +18,6 @@
 
 #include <map>
 #include <memory>
-#include <string>
 #include "core/repository/VolatileContentRepository.h"
 #include <core/RepositoryFactory.h>
 #include "core/yaml/YamlConfiguration.h"
@@ -455,11 +454,11 @@ Processors:
 
 class DummyComponent : public core::ConfigurableComponent {
  public:
-  bool supportsDynamicProperties() override {
+  virtual bool supportsDynamicProperties() {
     return false;
   }
 
-  bool canEdit() override {
+  virtual bool canEdit() {
     return true;
   }
 };
@@ -525,7 +524,6 @@ TEST_CASE("Test Exclusive Property", "[YamlConfigurationExclusiveProperty]") {
   LogTestController &logTestController = LogTestController::getInstance();
   logTestController.setDebug<TestPlan>();
   logTestController.setDebug<core::YamlConfiguration>();
-
   std::shared_ptr<core::Repository> testProvRepo = core::createRepository("provenancerepository", true);
   std::shared_ptr<core::Repository> testFlowFileRepo = core::createRepository("flowfilerepository", true);
   std::shared_ptr<minifi::Configure> configuration = std::make_shared<minifi::Configure>();
@@ -542,13 +540,33 @@ TEST_CASE("Test Exclusive Property", "[YamlConfigurationExclusiveProperty]") {
   REQUIRE(true);  // Expected to get here w/o any exceptions
 }
 
+TEST_CASE("Test Regex Property", "[YamlConfigurationRegexProperty]") {
+  TestController test_controller;
+  LogTestController &logTestController = LogTestController::getInstance();
+  logTestController.setDebug<TestPlan>();
+  logTestController.setDebug<core::YamlConfiguration>();
+  std::shared_ptr<core::Repository> testProvRepo = core::createRepository("provenancerepository", true);
+  std::shared_ptr<core::Repository> testFlowFileRepo = core::createRepository("flowfilerepository", true);
+  std::shared_ptr<minifi::Configure> configuration = std::make_shared<minifi::Configure>();
+  std::shared_ptr<minifi::io::StreamFactory> streamFactory = minifi::io::StreamFactory::getInstance(configuration);
+  std::shared_ptr<core::ContentRepository>
+      content_repo = std::make_shared<core::repository::VolatileContentRepository>();
+  core::YamlConfiguration yamlConfig(testProvRepo, testFlowFileRepo, content_repo, streamFactory, configuration);
+  const auto component = std::make_shared<DummyComponent>();
+  std::set<core::Property> props;
+  props.emplace(core::Property("Prop A", "Prop A desc", "val A", true, "", {}, {}));
+  props.emplace(core::Property("Prop B", "Prop B desc", "val B", true, "^val.*$", {}, {}));
+  component->setSupportedProperties(std::move(props));
+  yamlConfig.validateComponentProperties(component, "component A", "section A");
+  REQUIRE(true);  // Expected to get here w/o any exceptions
+}
+
 TEST_CASE("Test Exclusive Property 2", "[YamlConfigurationExclusiveProperty2]") {
   TestController test_controller;
 
   LogTestController &logTestController = LogTestController::getInstance();
   logTestController.setDebug<TestPlan>();
   logTestController.setDebug<core::YamlConfiguration>();
-
   std::shared_ptr<core::Repository> testProvRepo = core::createRepository("provenancerepository", true);
   std::shared_ptr<core::Repository> testFlowFileRepo = core::createRepository("flowfilerepository", true);
   std::shared_ptr<minifi::Configure> configuration = std::make_shared<minifi::Configure>();
@@ -572,4 +590,34 @@ TEST_CASE("Test Exclusive Property 2", "[YamlConfigurationExclusiveProperty2]")
   }
   REQUIRE(config_failed);
 }
+
+TEST_CASE("Test Regex Property 2", "[YamlConfigurationRegexProperty2]") {
+  TestController test_controller;
+  LogTestController &logTestController = LogTestController::getInstance();
+  logTestController.setDebug<TestPlan>();
+  logTestController.setDebug<core::YamlConfiguration>();
+  std::shared_ptr<core::Repository> testProvRepo = core::createRepository("provenancerepository", true);
+  std::shared_ptr<core::Repository> testFlowFileRepo = core::createRepository("flowfilerepository", true);
+  std::shared_ptr<minifi::Configure> configuration = std::make_shared<minifi::Configure>();
+  std::shared_ptr<minifi::io::StreamFactory> streamFactory = minifi::io::StreamFactory::getInstance(configuration);
+  std::shared_ptr<core::ContentRepository>
+      content_repo = std::make_shared<core::repository::VolatileContentRepository>();
+  core::YamlConfiguration yamlConfig(testProvRepo, testFlowFileRepo, content_repo, streamFactory, configuration);
+  const auto component = std::make_shared<DummyComponent>();
+  std::set<core::Property> props;
+  props.emplace(core::Property("Prop A", "Prop A desc", "val A", true, "", {}, {}));
+  props.emplace(core::Property("Prop B", "Prop B desc", "val B", true, "^notval.*$", {}, {}));
+  component->setSupportedProperties(std::move(props));
+  bool config_failed = false;
+  try {
+    yamlConfig.validateComponentProperties(component, "component A", "section A");
+  } catch (const std::exception &e) {
+    config_failed = true;
+    REQUIRE("Unable to parse configuration file for component named 'component A' because "
+            "property 'Prop B' does not match validation pattern '^notval.*$' "
+            "[in 'section A' section of configuration file]" == std::string(e.what()));
+  }
+  REQUIRE(config_failed);
+}
+
 #endif  // YAML_CONFIGURATION_USE_REGEX