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 <[email protected]> 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 <[email protected]> Authored: Thu May 31 12:03:50 2018 -0400 Committer: Marc Parisi <[email protected]> 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
