This is an automated email from the ASF dual-hosted git repository. lordgamez pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git
commit 30ddcb94629a0c1624b3a2a074c5b8d73d977b16 Author: Martin Zink <[email protected]> AuthorDate: Thu Apr 24 11:09:19 2025 +0200 MINIFICPP-2561 Properties with Allowed Values or Complex validators cannot support Expression Language Signed-off-by: Gabor Gyimesi <[email protected]> This closes #1965 --- cmake/Catch2.cmake | 4 +- .../include/core/PropertyDefinitionBuilder.h | 11 + core-framework/include/utils/PropertyErrors.h | 3 +- .../azure/processors/FetchAzureDataLakeStorage.h | 1 - .../azure/tests/FetchAzureDataLakeStorageTests.cpp | 14 +- .../libarchive/tests/CompressContentTests.cpp | 619 ++++++++++----------- .../llamacpp/tests/RunLlamaCppInferenceTests.cpp | 2 +- extensions/opc/include/putopc.h | 3 +- extensions/opc/tests/PutOpcProcessorTests.cpp | 22 +- extensions/sql/processors/FlowFileSource.h | 2 - extensions/standard-processors/processors/GetTCP.h | 2 - extensions/standard-processors/processors/PutTCP.h | 2 - .../standard-processors/processors/RetryFlowFile.h | 1 - .../standard-processors/tests/unit/GetTCPTests.cpp | 2 +- .../include/core/logging/LoggerConfiguration.h | 2 +- libminifi/test/unit/LogMetricsPublisherTests.cpp | 3 +- libminifi/test/unit/LoggerTests.cpp | 57 +- libminifi/test/unit/PropertyValidationTests.cpp | 18 +- 18 files changed, 394 insertions(+), 374 deletions(-) diff --git a/cmake/Catch2.cmake b/cmake/Catch2.cmake index 2986f0487..0ff92766f 100644 --- a/cmake/Catch2.cmake +++ b/cmake/Catch2.cmake @@ -20,8 +20,8 @@ include(FetchContent) FetchContent_Declare( Catch2 - URL https://github.com/catchorg/Catch2/archive/refs/tags/v3.8.1.tar.gz - URL_HASH SHA256=18b3f70ac80fccc340d8c6ff0f339b2ae64944782f8d2fca2bd705cf47cadb79 + URL https://github.com/catchorg/Catch2/archive/refs/tags/v3.9.1.tar.gz + URL_HASH SHA256=a215c2a723bd7483efd236dc86066842a389cb4e344c61119c978acdf24d39be SYSTEM ) FetchContent_MakeAvailable(Catch2) diff --git a/core-framework/include/core/PropertyDefinitionBuilder.h b/core-framework/include/core/PropertyDefinitionBuilder.h index 483dc2ec1..2ce5cdf69 100644 --- a/core-framework/include/core/PropertyDefinitionBuilder.h +++ b/core-framework/include/core/PropertyDefinitionBuilder.h @@ -99,6 +99,17 @@ struct PropertyDefinitionBuilder { } constexpr PropertyDefinition<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> build() { + if (property.name.size() == 0) { + throw std::logic_error("A Property must have a name"); + } + if (property.supports_expression_language) { + if (property.allowed_values.size() > 0) { + throw std::logic_error("Either supports EL or has allowed values"); + } + if (property.validator != &StandardPropertyValidators::NON_BLANK_VALIDATOR && property.validator != &StandardPropertyValidators::ALWAYS_VALID_VALIDATOR) { + throw std::logic_error("Only ALWAYS_VALID_VALIDATOR and NON_BLANK_VALIDATOR has EL support"); + } + } return property; } diff --git a/core-framework/include/utils/PropertyErrors.h b/core-framework/include/utils/PropertyErrors.h index 944d702a5..b8bc6715b 100644 --- a/core-framework/include/utils/PropertyErrors.h +++ b/core-framework/include/utils/PropertyErrors.h @@ -30,8 +30,7 @@ enum class PropertyErrorCode : std::underlying_type_t<std::byte> { NotSupportedProperty, DynamicPropertiesNotSupported, PropertyNotSet, - ValidationFailed, - EmptyString + ValidationFailed }; struct PropertyErrorCategory final : std::error_category { diff --git a/extensions/azure/processors/FetchAzureDataLakeStorage.h b/extensions/azure/processors/FetchAzureDataLakeStorage.h index d2a8e8565..bb9c4d338 100644 --- a/extensions/azure/processors/FetchAzureDataLakeStorage.h +++ b/extensions/azure/processors/FetchAzureDataLakeStorage.h @@ -47,7 +47,6 @@ class FetchAzureDataLakeStorage final : public AzureDataLakeStorageFileProcessor .build(); EXTENSIONAPI static constexpr auto NumberOfRetries = core::PropertyDefinitionBuilder<>::createProperty("Number of Retries") .withDescription("The number of automatic retries to perform if the download fails.") - .withValidator(core::StandardPropertyValidators::UNSIGNED_INTEGER_VALIDATOR) .withDefaultValue("0") .supportsExpressionLanguage(true) .build(); diff --git a/extensions/azure/tests/FetchAzureDataLakeStorageTests.cpp b/extensions/azure/tests/FetchAzureDataLakeStorageTests.cpp index 72df7ee20..70d63bc6d 100644 --- a/extensions/azure/tests/FetchAzureDataLakeStorageTests.cpp +++ b/extensions/azure/tests/FetchAzureDataLakeStorageTests.cpp @@ -118,7 +118,19 @@ TEST_CASE_METHOD(FetchAzureDataLakeStorageTestsFixture, "Fetch a range of the fi TEST_CASE_METHOD(FetchAzureDataLakeStorageTestsFixture, "Number of Retries is set", "[azureDataLakeStorageFetch]") { plan_->setProperty(azure_data_lake_storage_, minifi::azure::processors::FetchAzureDataLakeStorage::NumberOfRetries, "1"); test_controller_.runSession(plan_, true); - REQUIRE(mock_data_lake_storage_client_ptr_->getPassedFetchParams().number_of_retries == 1); + CHECK(mock_data_lake_storage_client_ptr_->getPassedFetchParams().number_of_retries == 1); +} + +TEST_CASE_METHOD(FetchAzureDataLakeStorageTestsFixture, "Valid Number of Retries is set via EL", "[azureDataLakeStorageFetch]") { + plan_->setProperty(azure_data_lake_storage_, minifi::azure::processors::FetchAzureDataLakeStorage::NumberOfRetries, "${literal(10):multiply(2):plus(1):multiply(2)}"); + test_controller_.runSession(plan_, true); + CHECK(mock_data_lake_storage_client_ptr_->getPassedFetchParams().number_of_retries == 42); +} + +TEST_CASE_METHOD(FetchAzureDataLakeStorageTestsFixture, "Invalid Number of Retries is set via EL", "[azureDataLakeStorageFetch]") { + plan_->setProperty(azure_data_lake_storage_, minifi::azure::processors::FetchAzureDataLakeStorage::NumberOfRetries, "${literal(\"asd\")}"); + REQUIRE_THROWS_WITH(test_controller_.runSession(plan_, true), "Expected parsable uint64_t from \"AzureDataLakeStorageProcessor::Number of Retries\", but got GeneralParsingError (Parsing Error:0)"); + CHECK_FALSE(mock_data_lake_storage_client_ptr_->getPassedFetchParams().number_of_retries); } TEST_CASE_METHOD(FetchAzureDataLakeStorageTestsFixture, "Fetch full file fails", "[azureDataLakeStorageFetch]") { diff --git a/extensions/libarchive/tests/CompressContentTests.cpp b/extensions/libarchive/tests/CompressContentTests.cpp index 157d75465..c731c60fa 100644 --- a/extensions/libarchive/tests/CompressContentTests.cpp +++ b/extensions/libarchive/tests/CompressContentTests.cpp @@ -17,39 +17,37 @@ */ #include <fstream> +#include <iostream> #include <map> #include <memory> -#include <utility> -#include <string> -#include <set> #include <random> +#include <set> #include <sstream> -#include <iostream> +#include <string> +#include <utility> +#include "CompressContent.h" #include "FlowController.h" -#include "unit/TestBase.h" -#include "unit/Catch.h" #include "catch2/generators/catch_generators.hpp" #include "core/Core.h" -#include "../../include/core/FlowFile.h" -#include "unit/ProvenanceTestHelper.h" -#include "core/Processor.h" +#include "core/FlowFile.h" #include "core/ProcessContext.h" #include "core/ProcessSession.h" -#include "CompressContent.h" +#include "core/Processor.h" #include "io/FileStream.h" -#include "processors/LogAttribute.h" #include "processors/GetFile.h" +#include "processors/LogAttribute.h" #include "processors/PutFile.h" -#include "utils/file/FileUtils.h" +#include "unit/Catch.h" +#include "unit/ProvenanceTestHelper.h" +#include "unit/TestBase.h" #include "unit/TestUtils.h" +#include "utils/file/FileUtils.h" #include "utils/gsl.h" class ReadCallback { public: - explicit ReadCallback(size_t size) - :buffer_{size} - {} + explicit ReadCallback(size_t size) : buffer_{size} {} ReadCallback(const ReadCallback&) = delete; ReadCallback(ReadCallback&&) = delete; ReadCallback& operator=(const ReadCallback&) = delete; @@ -60,8 +58,8 @@ class ReadCallback { int64_t total_read = 0; do { const auto ret = stream->read(std::span(buffer_).subspan(read_size_)); - if (ret == 0) break; - if (minifi::io::isError(ret)) return -1; + if (ret == 0) { break; } + if (minifi::io::isError(ret)) { return -1; } read_size_ += gsl::narrow<size_t>(ret); total_read += gsl::narrow<int64_t>(ret); } while (buffer_.size() != read_size_); @@ -96,7 +94,7 @@ class ReadCallback { * CompressTestController or a DecompressTestController. */ class CompressDecompressionTestController : public TestController { - protected: + public: static std::filesystem::path tempDir_; static std::filesystem::path raw_content_path_; static std::filesystem::path compressed_content_path_; @@ -176,31 +174,21 @@ class CompressDecompressionTestController : public TestController { session.commit(); } - void read(const std::shared_ptr<core::FlowFile>& file, ReadCallback& reader) const { - helper_session->read(file, std::ref(reader)); - } + void read(const std::shared_ptr<core::FlowFile>& file, ReadCallback& reader) const { helper_session->read(file, std::ref(reader)); } - public: - class RawContent{ + class RawContent { std::string content_; - explicit RawContent(std::string&& content_): content_(std::move(content_)) {} + explicit RawContent(std::string&& content_) : content_(std::move(content_)) {} friend class CompressDecompressionTestController; + public: - bool operator==(const std::string& actual) const noexcept { - return content_ == actual; - } - bool operator!=(const std::string& actual) const noexcept { - return content_ != actual; - } + bool operator==(const std::string& actual) const noexcept { return content_ == actual; } + bool operator!=(const std::string& actual) const noexcept { return content_ != actual; } }; - [[nodiscard]] static std::filesystem::path rawContentPath() { - return raw_content_path_; - } + [[nodiscard]] static std::filesystem::path rawContentPath() { return raw_content_path_; } - [[nodiscard]] static std::filesystem::path compressedPath() { - return compressed_content_path_; - } + [[nodiscard]] static std::filesystem::path compressedPath() { return compressed_content_path_; } [[nodiscard]] static RawContent getRawContent() { std::ifstream file; @@ -233,6 +221,7 @@ std::filesystem::path CompressDecompressionTestController::raw_content_path_; std::filesystem::path CompressDecompressionTestController::compressed_content_path_; class CompressTestController : public CompressDecompressionTestController { + public: static void initContentWithRandomData() { int random_seed = 0x454; std::ofstream file; @@ -240,12 +229,9 @@ class CompressTestController : public CompressDecompressionTestController { std::mt19937 gen(random_seed); std::uniform_int_distribution<> dis(0, 99); - for (int i = 0; i < 100000; i++) { - file << std::to_string(dis(gen)); - } + for (int i = 0; i < 100000; i++) { file << std::to_string(dis(gen)); } } - public: CompressTestController() { tempDir_ = get_global_controller().createTempDirectory(); REQUIRE(!tempDir_.empty()); @@ -255,18 +241,16 @@ class CompressTestController : public CompressDecompressionTestController { setupFlow(); } - template<class ...Args> - void writeCompressed(Args&& ...args) { + template<class... Args> + void writeCompressed(Args&&... args) { std::ofstream file(compressed_content_path_, std::ios::binary); file.write(std::forward<Args>(args)...); } }; -class DecompressTestController : public CompressDecompressionTestController{ +class DecompressTestController : public CompressDecompressionTestController { public: - DecompressTestController() { - setupFlow(); - } + DecompressTestController() { setupFlow(); } DecompressTestController(DecompressTestController&&) = delete; DecompressTestController(const DecompressTestController&) = delete; DecompressTestController& operator=(DecompressTestController&&) = delete; @@ -281,245 +265,267 @@ class DecompressTestController : public CompressDecompressionTestController{ using CompressionFormat = minifi::processors::compress_content::ExtendedCompressionFormat; using CompressionMode = minifi::processors::compress_content::CompressionMode; -TEST_CASE_METHOD(CompressTestController, "CompressFileGZip", "[compressfiletest1]") { - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressMode.name, std::string{magic_enum::enum_name(CompressionMode::compress)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, std::string{magic_enum::enum_name(CompressionFormat::GZIP)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); - REQUIRE(context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); - - auto flow = importFlowFile(rawContentPath()); - flow->setAttribute(core::SpecialFlowAttribute::FILENAME, "inputfile"); - - trigger(); - - // validate the compress content - std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; - std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords); - REQUIRE(flow1); - REQUIRE(flow1->getSize() > 0); +TEST_CASE("Compress and decompress GZip", "[compressfiletest1]") { { - REQUIRE(flow1->getSize() != flow->getSize()); - std::string attribute_value; - flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, attribute_value); - REQUIRE(attribute_value == "application/gzip"); - flow1->getAttribute(core::SpecialFlowAttribute::FILENAME, attribute_value); - REQUIRE(attribute_value == "inputfile.tar.gz"); - ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); - read(flow1, callback); - callback.archive_read(); - std::string content(reinterpret_cast<char *> (callback.archive_buffer_.data()), callback.archive_buffer_.size()); - REQUIRE(getRawContent() == content); - // write the compress content for next test - writeCompressed(reinterpret_cast<char *> (callback.buffer_.data()), callback.read_size_); + CompressTestController controller; + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressMode.name, + std::string{magic_enum::enum_name(CompressionMode::compress)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressFormat.name, + std::string{magic_enum::enum_name(CompressionFormat::GZIP)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); + + auto flow = controller.importFlowFile(controller.rawContentPath()); + flow->setAttribute(core::SpecialFlowAttribute::FILENAME, "inputfile"); + + controller.trigger(); + + // validate the compress content + std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; + std::shared_ptr<core::FlowFile> flow1 = controller.output->poll(expiredFlowRecords); + REQUIRE(flow1); + REQUIRE(flow1->getSize() > 0); + { + REQUIRE(flow1->getSize() != flow->getSize()); + std::string attribute_value; + flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, attribute_value); + REQUIRE(attribute_value == "application/gzip"); + flow1->getAttribute(core::SpecialFlowAttribute::FILENAME, attribute_value); + REQUIRE(attribute_value == "inputfile.tar.gz"); + ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); + controller.read(flow1, callback); + callback.archive_read(); + std::string content(reinterpret_cast<char*>(callback.archive_buffer_.data()), callback.archive_buffer_.size()); + REQUIRE(controller.getRawContent() == content); + // write the compress content for next test + controller.writeCompressed(reinterpret_cast<char*>(callback.buffer_.data()), callback.read_size_); + } } -} - -TEST_CASE_METHOD(DecompressTestController, "DecompressFileGZip", "[compressfiletest2]") { - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressMode.name, std::string{magic_enum::enum_name(CompressionMode::decompress)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, std::string{magic_enum::enum_name(CompressionFormat::GZIP)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); - REQUIRE(context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); - - auto flow = importFlowFile(compressedPath()); - flow->setAttribute(core::SpecialFlowAttribute::FILENAME, "inputfile.tar.gz"); - - trigger(); - - // validate the compress content - std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; - std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords); - REQUIRE(flow1); - REQUIRE(flow1->getSize() > 0); { - REQUIRE(flow1->getSize() != flow->getSize()); - std::string attribute_value; - REQUIRE_FALSE(flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, attribute_value)); - flow1->getAttribute(core::SpecialFlowAttribute::FILENAME, attribute_value); - REQUIRE(attribute_value == "inputfile"); - ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); - read(flow1, callback); - std::string content(reinterpret_cast<char *> (callback.buffer_.data()), callback.read_size_); - REQUIRE(getRawContent() == content); + DecompressTestController controller; + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressMode.name, + std::string{magic_enum::enum_name(CompressionMode::decompress)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressFormat.name, + std::string{magic_enum::enum_name(CompressionFormat::GZIP)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); + + auto flow = controller.importFlowFile(controller.compressedPath()); + flow->setAttribute(core::SpecialFlowAttribute::FILENAME, "inputfile.tar.gz"); + + controller.trigger(); + + // validate the compress content + std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; + std::shared_ptr<core::FlowFile> flow1 = controller.output->poll(expiredFlowRecords); + REQUIRE(flow1); + REQUIRE(flow1->getSize() > 0); + { + REQUIRE(flow1->getSize() != flow->getSize()); + std::string attribute_value; + REQUIRE_FALSE(flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, attribute_value)); + flow1->getAttribute(core::SpecialFlowAttribute::FILENAME, attribute_value); + REQUIRE(attribute_value == "inputfile"); + ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); + controller.read(flow1, callback); + std::string content(reinterpret_cast<char*>(callback.buffer_.data()), callback.read_size_); + REQUIRE(controller.getRawContent() == content); + } } } - -TEST_CASE_METHOD(CompressTestController, "CompressFileBZip", "[compressfiletest3]") { +TEST_CASE("Compress and decompress BZip", "[compressfiletest3]") { if (!archive_bzlib_version()) { return; } // minifi was compiled without BZip2 support - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressMode.name, std::string{magic_enum::enum_name(CompressionMode::compress)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, std::string{magic_enum::enum_name(CompressionFormat::BZIP2)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); - REQUIRE(context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); - - auto flow = importFlowFile(rawContentPath()); - trigger(); - - // validate the compress content - std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; - std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords); - REQUIRE(flow1); - REQUIRE(flow1->getSize() > 0); { - REQUIRE(flow1->getSize() != flow->getSize()); - std::string mime; - flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime); - REQUIRE(mime == "application/bzip2"); - ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); - read(flow1, callback); - callback.archive_read(); - std::string contents(reinterpret_cast<char *> (callback.archive_buffer_.data()), callback.archive_buffer_.size()); - REQUIRE(getRawContent() == contents); - // write the compress content for next test - writeCompressed(reinterpret_cast<char *> (callback.buffer_.data()), callback.read_size_); + CompressTestController controller; + + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressMode.name, + std::string{magic_enum::enum_name(CompressionMode::compress)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressFormat.name, + std::string{magic_enum::enum_name(CompressionFormat::BZIP2)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); + + auto flow = controller.importFlowFile(controller.rawContentPath()); + controller.trigger(); + + // validate the compress content + std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; + std::shared_ptr<core::FlowFile> flow1 = controller.output->poll(expiredFlowRecords); + REQUIRE(flow1); + REQUIRE(flow1->getSize() > 0); + { + REQUIRE(flow1->getSize() != flow->getSize()); + std::string mime; + flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime); + REQUIRE(mime == "application/bzip2"); + ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); + controller.read(flow1, callback); + callback.archive_read(); + std::string contents(reinterpret_cast<char*>(callback.archive_buffer_.data()), callback.archive_buffer_.size()); + REQUIRE(controller.getRawContent() == contents); + // write the compress content for next test + controller.writeCompressed(reinterpret_cast<char*>(callback.buffer_.data()), callback.read_size_); + } } -} - - -TEST_CASE_METHOD(DecompressTestController, "DecompressFileBZip", "[compressfiletest4]") { - if (!archive_bzlib_version()) { return; } // minifi was compiled without BZip2 support - - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressMode.name, std::string{magic_enum::enum_name(CompressionMode::decompress)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, std::string{magic_enum::enum_name(CompressionFormat::BZIP2)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); - REQUIRE(context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); - - auto flow = importFlowFile(compressedPath()); - - trigger(); - - // validate the compress content - std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; - std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords); - REQUIRE(flow1); - REQUIRE(flow1->getSize() > 0); { - REQUIRE(flow1->getSize() != flow->getSize()); - std::string mime; - REQUIRE(flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime) == false); - ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); - read(flow1, callback); - std::string contents(reinterpret_cast<char *> (callback.buffer_.data()), callback.read_size_); - REQUIRE(getRawContent() == contents); + DecompressTestController controller; + + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressMode.name, + std::string{magic_enum::enum_name(CompressionMode::decompress)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressFormat.name, + std::string{magic_enum::enum_name(CompressionFormat::BZIP2)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); + + auto flow = controller.importFlowFile(controller.compressedPath()); + + controller.trigger(); + + // validate the compress content + std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; + std::shared_ptr<core::FlowFile> flow1 = controller.output->poll(expiredFlowRecords); + REQUIRE(flow1); + REQUIRE(flow1->getSize() > 0); + { + REQUIRE(flow1->getSize() != flow->getSize()); + std::string mime; + REQUIRE(flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime) == false); + ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); + controller.read(flow1, callback); + std::string contents(reinterpret_cast<char*>(callback.buffer_.data()), callback.read_size_); + REQUIRE(controller.getRawContent() == contents); + } } } -TEST_CASE_METHOD(CompressTestController, "CompressFileLZMA", "[compressfiletest5]") { +TEST_CASE("Compress and decompress LZMA", "[compressfiletest5]") { if (!archive_liblzma_version()) { return; } // minifi was compiled without LZMA support - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressMode.name, std::string{magic_enum::enum_name(CompressionMode::compress)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, std::string{magic_enum::enum_name(CompressionFormat::LZMA)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); - REQUIRE(context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); - - auto flow = importFlowFile(rawContentPath()); - trigger(); - - // validate the compress content - std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; - std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords); - REQUIRE(flow1); - REQUIRE(flow1->getSize() > 0); { - REQUIRE(flow1->getSize() != flow->getSize()); - std::string mime; - flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime); - REQUIRE(mime == "application/x-lzma"); - ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); - read(flow1, callback); - callback.archive_read(); - std::string contents(reinterpret_cast<char *> (callback.archive_buffer_.data()), callback.archive_buffer_.size()); - REQUIRE(getRawContent() == contents); - // write the compress content for next test - writeCompressed(reinterpret_cast<char *> (callback.buffer_.data()), callback.read_size_); + CompressTestController controller; + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressMode.name, + std::string{magic_enum::enum_name(CompressionMode::compress)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressFormat.name, + std::string{magic_enum::enum_name(CompressionFormat::LZMA)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); + + auto flow = controller.importFlowFile(controller.rawContentPath()); + controller.trigger(); + + // validate the compress content + std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; + std::shared_ptr<core::FlowFile> flow1 = controller.output->poll(expiredFlowRecords); + REQUIRE(flow1); + REQUIRE(flow1->getSize() > 0); + { + REQUIRE(flow1->getSize() != flow->getSize()); + std::string mime; + flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime); + REQUIRE(mime == "application/x-lzma"); + ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); + controller.read(flow1, callback); + callback.archive_read(); + std::string contents(reinterpret_cast<char*>(callback.archive_buffer_.data()), callback.archive_buffer_.size()); + REQUIRE(controller.getRawContent() == contents); + // write the compress content for next test + controller.writeCompressed(reinterpret_cast<char*>(callback.buffer_.data()), callback.read_size_); + } } -} - - -TEST_CASE_METHOD(DecompressTestController, "DecompressFileLZMA", "[compressfiletest6]") { - if (!archive_liblzma_version()) { return; } // minifi was compiled without LZMA support - - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressMode.name, std::string{magic_enum::enum_name(CompressionMode::decompress)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, std::string{magic_enum::enum_name(CompressionFormat::USE_MIME_TYPE)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); - REQUIRE(context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); - - auto flow = importFlowFile(compressedPath()); - flow->setAttribute(core::SpecialFlowAttribute::MIME_TYPE, "application/x-lzma"); - trigger(); - - // validate the compress content - std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; - std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords); - REQUIRE(flow1); - REQUIRE(flow1->getSize() > 0); { - REQUIRE(flow1->getSize() != flow->getSize()); - std::string mime; - REQUIRE(flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime) == false); - ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); - read(flow1, callback); - std::string contents(reinterpret_cast<char *> (callback.buffer_.data()), callback.read_size_); - REQUIRE(getRawContent() == contents); + DecompressTestController controller; + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressMode.name, + std::string{magic_enum::enum_name(CompressionMode::decompress)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressFormat.name, + std::string{magic_enum::enum_name(CompressionFormat::USE_MIME_TYPE)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); + + auto flow = controller.importFlowFile(controller.compressedPath()); + flow->setAttribute(core::SpecialFlowAttribute::MIME_TYPE, "application/x-lzma"); + controller.trigger(); + + // validate the compress content + std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; + std::shared_ptr<core::FlowFile> flow1 = controller.output->poll(expiredFlowRecords); + REQUIRE(flow1); + REQUIRE(flow1->getSize() > 0); + { + REQUIRE(flow1->getSize() != flow->getSize()); + std::string mime; + REQUIRE(flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime) == false); + ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); + controller.read(flow1, callback); + std::string contents(reinterpret_cast<char*>(callback.buffer_.data()), callback.read_size_); + REQUIRE(controller.getRawContent() == contents); + } } } TEST_CASE_METHOD(CompressTestController, "CompressFileXYLZMA", "[compressfiletest7]") { if (!archive_liblzma_version()) { return; } // minifi was compiled without LZMA support - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressMode.name, std::string{magic_enum::enum_name(CompressionMode::compress)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, std::string{magic_enum::enum_name(CompressionFormat::XZ_LZMA2)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); - REQUIRE(context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); - - auto flow = importFlowFile(rawContentPath()); - trigger(); - - // validate the compress content - std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; - std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords); - REQUIRE(flow1); - REQUIRE(flow1->getSize() > 0); { - REQUIRE(flow1->getSize() != flow->getSize()); - std::string mime; - flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime); - REQUIRE(mime == "application/x-xz"); - ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); - read(flow1, callback); - callback.archive_read(); - std::string contents(reinterpret_cast<char *> (callback.archive_buffer_.data()), callback.archive_buffer_.size()); - REQUIRE(getRawContent() == contents); - // write the compress content for next test - writeCompressed(reinterpret_cast<char *> (callback.buffer_.data()), callback.read_size_); + CompressTestController controller; + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressMode.name, + std::string{magic_enum::enum_name(CompressionMode::compress)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressFormat.name, + std::string{magic_enum::enum_name(CompressionFormat::XZ_LZMA2)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); + + auto flow = controller.importFlowFile(controller.rawContentPath()); + controller.trigger(); + + // validate the compress content + std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; + std::shared_ptr<core::FlowFile> flow1 = controller.output->poll(expiredFlowRecords); + REQUIRE(flow1); + REQUIRE(flow1->getSize() > 0); + { + REQUIRE(flow1->getSize() != flow->getSize()); + std::string mime; + flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime); + REQUIRE(mime == "application/x-xz"); + ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); + controller.read(flow1, callback); + callback.archive_read(); + std::string contents(reinterpret_cast<char*>(callback.archive_buffer_.data()), callback.archive_buffer_.size()); + REQUIRE(controller.getRawContent() == contents); + // write the compress content for next test + controller.writeCompressed(reinterpret_cast<char*>(callback.buffer_.data()), callback.read_size_); + } } -} - - -TEST_CASE_METHOD(DecompressTestController, "DecompressFileXYLZMA", "[compressfiletest8]") { - if (!archive_liblzma_version()) { return; } // minifi was compiled without LZMA support - - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressMode.name, std::string{magic_enum::enum_name(CompressionMode::decompress)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, std::string{magic_enum::enum_name(CompressionFormat::USE_MIME_TYPE)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); - REQUIRE(context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); - - auto flow = importFlowFile(compressedPath()); - flow->setAttribute(core::SpecialFlowAttribute::MIME_TYPE, "application/x-xz"); - trigger(); - - // validate the compress content - std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; - std::shared_ptr<core::FlowFile> flow1 = output->poll(expiredFlowRecords); - REQUIRE(flow1); - REQUIRE(flow1->getSize() > 0); { - REQUIRE(flow1->getSize() != flow->getSize()); - std::string mime; - REQUIRE(flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime) == false); - ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); - read(flow1, callback); - std::string contents(reinterpret_cast<char *> (callback.buffer_.data()), callback.read_size_); - REQUIRE(getRawContent() == contents); + DecompressTestController controller; + if (!archive_liblzma_version()) { return; } // minifi was compiled without LZMA support + + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressMode.name, + std::string{magic_enum::enum_name(CompressionMode::decompress)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressFormat.name, + std::string{magic_enum::enum_name(CompressionFormat::USE_MIME_TYPE)})); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); + REQUIRE(controller.context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); + + auto flow = controller.importFlowFile(controller.compressedPath()); + flow->setAttribute(core::SpecialFlowAttribute::MIME_TYPE, "application/x-xz"); + controller.trigger(); + + // validate the compress content + std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; + std::shared_ptr<core::FlowFile> flow1 = controller.output->poll(expiredFlowRecords); + REQUIRE(flow1); + REQUIRE(flow1->getSize() > 0); + { + REQUIRE(flow1->getSize() != flow->getSize()); + std::string mime; + REQUIRE(flow1->getAttribute(core::SpecialFlowAttribute::MIME_TYPE, mime) == false); + ReadCallback callback(gsl::narrow<size_t>(flow1->getSize())); + controller.read(flow1, callback); + std::string contents(reinterpret_cast<char*>(callback.buffer_.data()), callback.read_size_); + REQUIRE(controller.getRawContent() == contents); + } } } @@ -541,36 +547,22 @@ TEST_CASE_METHOD(TestController, "RawGzipCompressionDecompression", "[compressfi // Build MiNiFi processing graph auto plan = createPlan(); - auto get_file = plan->addProcessor( - "GetFile", - "GetFile"); - auto compress_content = plan->addProcessor( - "CompressContent", - "CompressContent", - core::Relationship("success", "d"), - true); - auto put_compressed = plan->addProcessor( - "PutFile", - "PutFile", - core::Relationship("success", "d"), - true); - auto decompress_content = plan->addProcessor( - "CompressContent", - "CompressContent", - core::Relationship("success", "d"), - true); - auto put_decompressed = plan->addProcessor( - "PutFile", - "PutFile", - core::Relationship("success", "d"), - true); + auto get_file = plan->addProcessor("GetFile", "GetFile"); + auto compress_content = plan->addProcessor("CompressContent", "CompressContent", core::Relationship("success", "d"), true); + auto put_compressed = plan->addProcessor("PutFile", "PutFile", core::Relationship("success", "d"), true); + auto decompress_content = plan->addProcessor("CompressContent", "CompressContent", core::Relationship("success", "d"), true); + auto put_decompressed = plan->addProcessor("PutFile", "PutFile", core::Relationship("success", "d"), true); // Configure GetFile processor REQUIRE(plan->setProperty(get_file, minifi::processors::GetFile::Directory, src_dir.string())); // Configure CompressContent processor for compression - REQUIRE(plan->setProperty(compress_content, minifi::processors::CompressContent::CompressMode, std::string{magic_enum::enum_name(CompressionMode::compress)})); - REQUIRE(plan->setProperty(compress_content, minifi::processors::CompressContent::CompressFormat, std::string{magic_enum::enum_name(CompressionFormat::GZIP)})); + REQUIRE(plan->setProperty(compress_content, + minifi::processors::CompressContent::CompressMode, + std::string{magic_enum::enum_name(CompressionMode::compress)})); + REQUIRE(plan->setProperty(compress_content, + minifi::processors::CompressContent::CompressFormat, + std::string{magic_enum::enum_name(CompressionFormat::GZIP)})); REQUIRE(plan->setProperty(compress_content, minifi::processors::CompressContent::UpdateFileName, "true")); REQUIRE(plan->setProperty(compress_content, minifi::processors::CompressContent::EncapsulateInTar, "false")); @@ -578,8 +570,12 @@ TEST_CASE_METHOD(TestController, "RawGzipCompressionDecompression", "[compressfi REQUIRE(plan->setProperty(put_compressed, minifi::processors::PutFile::Directory, dst_dir.string())); // Configure CompressContent processor for decompression - REQUIRE(plan->setProperty(decompress_content, minifi::processors::CompressContent::CompressMode, std::string{magic_enum::enum_name(CompressionMode::decompress)})); - REQUIRE(plan->setProperty(decompress_content, minifi::processors::CompressContent::CompressFormat, std::string{magic_enum::enum_name(CompressionFormat::GZIP)})); + REQUIRE(plan->setProperty(decompress_content, + minifi::processors::CompressContent::CompressMode, + std::string{magic_enum::enum_name(CompressionMode::decompress)})); + REQUIRE(plan->setProperty(decompress_content, + minifi::processors::CompressContent::CompressFormat, + std::string{magic_enum::enum_name(CompressionFormat::GZIP)})); REQUIRE(plan->setProperty(decompress_content, minifi::processors::CompressContent::UpdateFileName, "true")); REQUIRE(plan->setProperty(decompress_content, minifi::processors::CompressContent::EncapsulateInTar, "false")); @@ -588,8 +584,7 @@ TEST_CASE_METHOD(TestController, "RawGzipCompressionDecompression", "[compressfi // Create source file std::string content; - SECTION("Empty content") { - } + SECTION("Empty content") {} SECTION("Short content") { content = "Repeated repeated repeated repeated repeated stuff."; } @@ -597,13 +592,11 @@ TEST_CASE_METHOD(TestController, "RawGzipCompressionDecompression", "[compressfi std::stringstream content_ss; // if only this part fails VolatileContentRepository's fixed max size // and some change in the cleanup logic might interfere - for (size_t i = 0U; i < 512 * 1024U; i++) { - content_ss << "foobar"; - } + for (size_t i = 0U; i < 512 * 1024U; i++) { content_ss << "foobar"; } content = content_ss.str(); } - std::ofstream{ src_file } << content; + std::ofstream{src_file} << content; // Run flow runSession(plan, true); @@ -626,20 +619,22 @@ TEST_CASE_METHOD(TestController, "RawGzipCompressionDecompression", "[compressfi TEST_CASE_METHOD(CompressTestController, "Batch CompressFileGZip", "[compressFileBatchTest]") { std::vector<std::string> flowFileContents{ - utils::string::repeat("0", 1000), utils::string::repeat("1", 1000), - utils::string::repeat("2", 1000), utils::string::repeat("3", 1000), + utils::string::repeat("0", 1000), + utils::string::repeat("1", 1000), + utils::string::repeat("2", 1000), + utils::string::repeat("3", 1000), }; constexpr std::size_t batchSize = 3; - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressMode.name, std::string{magic_enum::enum_name(CompressionMode::compress)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, std::string{magic_enum::enum_name(CompressionFormat::GZIP)})); + REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressMode.name, + std::string{magic_enum::enum_name(CompressionMode::compress)})); + REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, + std::string{magic_enum::enum_name(CompressionFormat::GZIP)})); REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); REQUIRE(context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); REQUIRE(context->setProperty(minifi::processors::CompressContent::BatchSize.name, std::to_string(batchSize))); - for (const auto& content : flowFileContents) { - importFlowFileFrom(minifi::io::BufferStream(content)); - } + for (const auto& content: flowFileContents) { importFlowFileFrom(minifi::io::BufferStream(content)); } REQUIRE(processor->getName() == "compresscontent"); auto factory = std::make_shared<core::ProcessSessionFactoryImpl>(context); @@ -655,9 +650,7 @@ TEST_CASE_METHOD(CompressTestController, "Batch CompressFileGZip", "[compressFil // validate the compress content std::set<std::shared_ptr<core::FlowFile>> expiredFlowRecords; std::vector<std::shared_ptr<core::FlowFile>> outFiles; - while (std::shared_ptr<core::FlowFile> file = output->poll(expiredFlowRecords)) { - outFiles.push_back(std::move(file)); - } + while (std::shared_ptr<core::FlowFile> file = output->poll(expiredFlowRecords)) { outFiles.push_back(std::move(file)); } REQUIRE(outFiles.size() == batchSize); // Trigger a second time to process the remaining files @@ -667,9 +660,7 @@ TEST_CASE_METHOD(CompressTestController, "Batch CompressFileGZip", "[compressFil session->commit(); } - while (std::shared_ptr<core::FlowFile> file = output->poll(expiredFlowRecords)) { - outFiles.push_back(std::move(file)); - } + while (std::shared_ptr<core::FlowFile> file = output->poll(expiredFlowRecords)) { outFiles.push_back(std::move(file)); } REQUIRE(outFiles.size() == flowFileContents.size()); for (std::size_t idx = 0; idx < outFiles.size(); ++idx) { @@ -680,21 +671,25 @@ TEST_CASE_METHOD(CompressTestController, "Batch CompressFileGZip", "[compressFil ReadCallback callback(gsl::narrow<size_t>(file->getSize())); read(file, callback); callback.archive_read(); - std::string content(reinterpret_cast<char *> (callback.archive_buffer_.data()), callback.archive_buffer_.size()); + std::string content(reinterpret_cast<char*>(callback.archive_buffer_.data()), callback.archive_buffer_.size()); REQUIRE(flowFileContents[idx] == content); } } TEST_CASE_METHOD(DecompressTestController, "Invalid archive decompression", "[compressfiletest9]") { const auto compression_format = GENERATE(CompressionFormat::GZIP, CompressionFormat::LZMA, CompressionFormat::XZ_LZMA2, CompressionFormat::BZIP2); - if (((compression_format == CompressionFormat::LZMA || compression_format == CompressionFormat::XZ_LZMA2) && !archive_liblzma_version()) || - (compression_format == CompressionFormat::BZIP2 && !archive_bzlib_version())) { + if (compression_format == CompressionFormat::BZIP2 && !archive_bzlib_version()) { return; } - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, std::string{magic_enum::enum_name(compression_format)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressMode.name, std::string{magic_enum::enum_name(CompressionMode::decompress)})); - REQUIRE(context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); - REQUIRE(context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); + + if ((compression_format == CompressionFormat::LZMA || compression_format == CompressionFormat::XZ_LZMA2) && !archive_liblzma_version()) { + return; + } + + CHECK(context->setProperty(minifi::processors::CompressContent::CompressFormat.name, std::string{magic_enum::enum_name(compression_format)})); + CHECK(context->setProperty(minifi::processors::CompressContent::CompressMode.name, std::string{magic_enum::enum_name(CompressionMode::decompress)})); + CHECK(context->setProperty(minifi::processors::CompressContent::CompressLevel.name, "9")); + CHECK(context->setProperty(minifi::processors::CompressContent::UpdateFileName.name, "true")); importFlowFileFrom(minifi::io::BufferStream(std::string{"banana bread"})); trigger(); @@ -710,7 +705,7 @@ TEST_CASE_METHOD(DecompressTestController, "Invalid archive decompression", "[co { ReadCallback callback(gsl::narrow<size_t>(invalid_flow->getSize())); read(invalid_flow, callback); - std::string contents(reinterpret_cast<char *> (callback.buffer_.data()), callback.read_size_); + std::string contents(reinterpret_cast<char*>(callback.buffer_.data()), callback.read_size_); REQUIRE(contents == "banana bread"); } } diff --git a/extensions/llamacpp/tests/RunLlamaCppInferenceTests.cpp b/extensions/llamacpp/tests/RunLlamaCppInferenceTests.cpp index cd57f574d..29deb5b6b 100644 --- a/extensions/llamacpp/tests/RunLlamaCppInferenceTests.cpp +++ b/extensions/llamacpp/tests/RunLlamaCppInferenceTests.cpp @@ -225,7 +225,7 @@ TEST_CASE("Invalid values for optional double type properties throw exception") } REQUIRE_THROWS_WITH(controller.trigger(minifi::test::InputFlowFileData{.content = "42", .attributes = {}}), - fmt::format("Expected parsable float from RunLlamaCppInference::{}, but got GeneralParsingError (Parsing Error:0)", property_name)); + fmt::format("Expected parsable float from RunLlamaCppInference::{}, but got GeneralParsingError (Parsing Error:0)", property_name)); } TEST_CASE("Top K property empty and invalid values are handled properly") { diff --git a/extensions/opc/include/putopc.h b/extensions/opc/include/putopc.h index db76d4329..5f4c11506 100644 --- a/extensions/opc/include/putopc.h +++ b/extensions/opc/include/putopc.h @@ -61,9 +61,8 @@ class PutOPCProcessor final : public BaseOPCProcessor { .withAllowedValues(magic_enum::enum_names<opc::OPCNodeDataType>()) .isRequired(true) .build(); - EXTENSIONAPI static constexpr auto TargetNodeIDType = core::PropertyDefinitionBuilder<2>::createProperty("Target node ID type") + EXTENSIONAPI static constexpr auto TargetNodeIDType = core::PropertyDefinitionBuilder<>::createProperty("Target node ID type") .withDescription("ID type of target node. Allowed values are: Int, String.") - .withAllowedValues({"Int", "String"}) .supportsExpressionLanguage(true) .isRequired(true) .build(); diff --git a/extensions/opc/tests/PutOpcProcessorTests.cpp b/extensions/opc/tests/PutOpcProcessorTests.cpp index dbba5c7a7..e031fe736 100644 --- a/extensions/opc/tests/PutOpcProcessorTests.cpp +++ b/extensions/opc/tests/PutOpcProcessorTests.cpp @@ -379,7 +379,7 @@ TEST_CASE("Test missing target node type", "[putopcprocessor]") { REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::ParentNodeID.name, "Simulator/Default/Device1")); REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::ParentNameSpaceIndex.name, std::to_string(server.getNamespaceIndex()))); REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::ValueType.name, "Int32")); - REQUIRE_FALSE(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeIDType.name, "${invalid_type}")); + REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeIDType.name, "${invalid_type}")); REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeID.name, "9999")); REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeNameSpaceIndex.name, std::to_string(server.getNamespaceIndex()))); REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeBrowseName.name, "everything")); @@ -389,7 +389,7 @@ TEST_CASE("Test missing target node type", "[putopcprocessor]") { REQUIRE(results.at(processors::PutOPCProcessor::Failure).size() == 1); auto flow_file = results.at(processors::PutOPCProcessor::Failure)[0]; CHECK(controller.plan->getContent(flow_file) == "42"); - REQUIRE(LogTestController::getInstance().contains("has invalid target node id type, routing to failure")); + REQUIRE(LogTestController::getInstance().contains("target node ID type is invalid: invalid. Routing to failure!")); } TEST_CASE("Test value type mismatch", "[putopcprocessor]") { @@ -397,15 +397,15 @@ TEST_CASE("Test value type mismatch", "[putopcprocessor]") { server.start(); SingleProcessorTestController controller{minifi::test::utils::make_processor<processors::PutOPCProcessor>("PutOPCProcessor")}; auto put_opc_processor = controller.getProcessor(); - REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::OPCServerEndPoint.name, "opc.tcp://127.0.0.1:4840/")); - REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::ParentNodeIDType.name, "Path")); - REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::ParentNodeID.name, "Simulator/Default/Device1")); - REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::ParentNameSpaceIndex.name, std::to_string(server.getNamespaceIndex()))); - REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::ValueType.name, "Boolean")); - REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeIDType.name, "Int")); - REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeID.name, "9999")); - REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeNameSpaceIndex.name, std::to_string(server.getNamespaceIndex()))); - REQUIRE(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeBrowseName.name, "everything")); + CHECK(put_opc_processor->setProperty(processors::PutOPCProcessor::OPCServerEndPoint.name, "opc.tcp://127.0.0.1:4840/")); + CHECK(put_opc_processor->setProperty(processors::PutOPCProcessor::ParentNodeIDType.name, "Path")); + CHECK(put_opc_processor->setProperty(processors::PutOPCProcessor::ParentNodeID.name, "Simulator/Default/Device1")); + CHECK(put_opc_processor->setProperty(processors::PutOPCProcessor::ParentNameSpaceIndex.name, std::to_string(server.getNamespaceIndex()))); + CHECK(put_opc_processor->setProperty(processors::PutOPCProcessor::ValueType.name, "Boolean")); + CHECK(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeIDType.name, "Int")); + CHECK(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeID.name, "9999")); + CHECK(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeNameSpaceIndex.name, std::to_string(server.getNamespaceIndex()))); + CHECK(put_opc_processor->setProperty(processors::PutOPCProcessor::TargetNodeBrowseName.name, "everything")); const auto results = controller.trigger("42"); REQUIRE(results.at(processors::PutOPCProcessor::Success).empty()); diff --git a/extensions/sql/processors/FlowFileSource.h b/extensions/sql/processors/FlowFileSource.h index 108c63cb8..bb24a77e3 100644 --- a/extensions/sql/processors/FlowFileSource.h +++ b/extensions/sql/processors/FlowFileSource.h @@ -62,7 +62,6 @@ class FlowFileSource { EXTENSIONAPI static constexpr auto OutputFormat = core::PropertyDefinitionBuilder<magic_enum::enum_count<flow_file_source::OutputType>()>::createProperty("Output Format") .withDescription("Set the output format type.") .isRequired(true) - .supportsExpressionLanguage(true) .withDefaultValue(magic_enum::enum_name(flow_file_source::OutputType::JSONPretty)) .withAllowedValues(magic_enum::enum_names<flow_file_source::OutputType>()) .build(); @@ -71,7 +70,6 @@ class FlowFileSource { "The maximum number of result rows that will be included in a single FlowFile. This will allow you to break up very large result sets into multiple FlowFiles. " "If the value specified is zero, then all rows are returned in a single FlowFile.") .isRequired(true) - .supportsExpressionLanguage(true) .withValidator(core::StandardPropertyValidators::UNSIGNED_INTEGER_VALIDATOR) .withDefaultValue("0") .build(); diff --git a/extensions/standard-processors/processors/GetTCP.h b/extensions/standard-processors/processors/GetTCP.h index dc4e9827f..65cf67f02 100644 --- a/extensions/standard-processors/processors/GetTCP.h +++ b/extensions/standard-processors/processors/GetTCP.h @@ -93,14 +93,12 @@ class GetTCP : public core::ProcessorImpl { .withValidator(core::StandardPropertyValidators::TIME_PERIOD_VALIDATOR) .withDefaultValue("1s") .isRequired(true) - .supportsExpressionLanguage(true) .build(); EXTENSIONAPI static constexpr auto ReconnectInterval = core::PropertyDefinitionBuilder<>::createProperty("Reconnection Interval") .withDescription("The duration to wait before attempting to reconnect to the endpoints.") .withValidator(core::StandardPropertyValidators::TIME_PERIOD_VALIDATOR) .withDefaultValue("1 min") .isRequired(true) - .supportsExpressionLanguage(true) .build(); EXTENSIONAPI static constexpr auto Properties = std::to_array<core::PropertyReference>({ EndpointList, diff --git a/extensions/standard-processors/processors/PutTCP.h b/extensions/standard-processors/processors/PutTCP.h index 9881ae02b..69768bb72 100644 --- a/extensions/standard-processors/processors/PutTCP.h +++ b/extensions/standard-processors/processors/PutTCP.h @@ -71,14 +71,12 @@ class PutTCP final : public core::ProcessorImpl { .withValidator(core::StandardPropertyValidators::TIME_PERIOD_VALIDATOR) .withDefaultValue("15 seconds") .isRequired(true) - .supportsExpressionLanguage(true) .build(); EXTENSIONAPI static constexpr auto Timeout = core::PropertyDefinitionBuilder<>::createProperty("Timeout") .withDescription("The timeout for connecting to and communicating with the destination.") .withValidator(core::StandardPropertyValidators::TIME_PERIOD_VALIDATOR) .withDefaultValue("15 seconds") .isRequired(true) - .supportsExpressionLanguage(true) .build(); EXTENSIONAPI static constexpr auto ConnectionPerFlowFile = core::PropertyDefinitionBuilder<>::createProperty("Connection Per FlowFile") .withDescription("Specifies whether to send each FlowFile's content on an individual connection.") diff --git a/extensions/standard-processors/processors/RetryFlowFile.h b/extensions/standard-processors/processors/RetryFlowFile.h index 8322f82c0..197ecbb13 100644 --- a/extensions/standard-processors/processors/RetryFlowFile.h +++ b/extensions/standard-processors/processors/RetryFlowFile.h @@ -72,7 +72,6 @@ class RetryFlowFile : public core::ProcessorImpl { .withDescription("The maximum number of times a FlowFile can be retried before being passed to the 'retries_exceeded' relationship.") .withValidator(core::StandardPropertyValidators::UNSIGNED_INTEGER_VALIDATOR) .withDefaultValue("3") - .supportsExpressionLanguage(true) .isRequired(true) .build(); EXTENSIONAPI static constexpr auto PenalizeRetries = core::PropertyDefinitionBuilder<>::createProperty("Penalize Retries") diff --git a/extensions/standard-processors/tests/unit/GetTCPTests.cpp b/extensions/standard-processors/tests/unit/GetTCPTests.cpp index 6dfc56e90..5274b3f84 100644 --- a/extensions/standard-processors/tests/unit/GetTCPTests.cpp +++ b/extensions/standard-processors/tests/unit/GetTCPTests.cpp @@ -120,7 +120,7 @@ class TcpTestServer { } co_await sendMessages(ssl_socket); asio::error_code ec; - ssl_socket.lowest_layer().cancel(ec); + [[maybe_unused]] auto e = ssl_socket.lowest_layer().cancel(ec); co_await ssl_socket.async_shutdown(minifi::utils::net::use_nothrow_awaitable); } diff --git a/libminifi/include/core/logging/LoggerConfiguration.h b/libminifi/include/core/logging/LoggerConfiguration.h index 284eb4e92..ffe5b64ea 100644 --- a/libminifi/include/core/logging/LoggerConfiguration.h +++ b/libminifi/include/core/logging/LoggerConfiguration.h @@ -77,7 +77,7 @@ class LoggerConfiguration { static LoggerConfiguration& getConfiguration(); static std::unique_ptr<LoggerConfiguration> newInstance() { - return std::unique_ptr<LoggerConfiguration>(new LoggerConfiguration()); + return std::unique_ptr<LoggerConfiguration>(new LoggerConfiguration()); // NOLINT(modernize-make-unique, cppcoreguidelines-owning-memory } void disableLogging() { diff --git a/libminifi/test/unit/LogMetricsPublisherTests.cpp b/libminifi/test/unit/LogMetricsPublisherTests.cpp index d48897fa5..6a75f9c30 100644 --- a/libminifi/test/unit/LogMetricsPublisherTests.cpp +++ b/libminifi/test/unit/LogMetricsPublisherTests.cpp @@ -52,6 +52,7 @@ class LogPublisherTestFixture { ~LogPublisherTestFixture() { minifi::utils::file::delete_dir(provenance_repo_->getDirectory()); minifi::utils::file::delete_dir(flow_file_repo_->getDirectory()); + LogTestController::getInstance().reset(); } protected: @@ -220,7 +221,7 @@ TEST_CASE_METHOD(LogPublisherTestFixture, "Verify changing log level property fo publisher_.initialize(configuration_, response_node_loader_); publisher_.loadMetricNodes(); using org::apache::nifi::minifi::test::utils::verifyLogLinePresenceInPollTime; - std::string expected_log = R"([info] { + std::string expected_log = R"([debug] { "LogMetrics": { "RepositoryMetrics": { "provenancerepository": { diff --git a/libminifi/test/unit/LoggerTests.cpp b/libminifi/test/unit/LoggerTests.cpp index 64071818b..05aa1e8f7 100644 --- a/libminifi/test/unit/LoggerTests.cpp +++ b/libminifi/test/unit/LoggerTests.cpp @@ -33,68 +33,68 @@ using namespace std::literals::chrono_literals; TEST_CASE("Test log Levels", "[ttl1]") { - LogTestController::getInstance().clear(); + LogTestController::getInstance().reset(); LogTestController::getInstance().setTrace<logging::Logger>(); std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); logger->log_info("hello {}", "world"); - REQUIRE(true == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [info] hello world")); + REQUIRE(true == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [info] hello world", 0s, 0ms)); LogTestController::getInstance().reset(); } TEST_CASE("Test log Levels debug", "[ttl2]") { - LogTestController::getInstance().clear(); + LogTestController::getInstance().reset(); LogTestController::getInstance().setTrace<logging::Logger>(); std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); logger->log_debug("hello {}", "world"); - REQUIRE(true == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [debug] hello world")); + REQUIRE(true == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [debug] hello world", 0s, 0ms)); LogTestController::getInstance().reset(); } TEST_CASE("Test log Levels trace", "[ttl3]") { - LogTestController::getInstance().clear(); + LogTestController::getInstance().reset(); LogTestController::getInstance().setTrace<logging::Logger>(); std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); logger->log_trace("hello {}", "world"); - REQUIRE(true == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [trace] hello world")); + REQUIRE(true == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [trace] hello world", 0s, 0ms)); LogTestController::getInstance().reset(); } TEST_CASE("Test log Levels error", "[ttl4]") { - LogTestController::getInstance().clear(); + LogTestController::getInstance().reset(); LogTestController::getInstance().setTrace<logging::Logger>(); std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); logger->log_error("hello {}", "world"); - REQUIRE(true == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [error] hello world")); + REQUIRE(true == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [error] hello world", 0s, 0ms)); LogTestController::getInstance().reset(); } TEST_CASE("Test log Levels change", "[ttl5]") { - LogTestController::getInstance().clear(); + LogTestController::getInstance().reset(); LogTestController::getInstance().setTrace<logging::Logger>(); std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); logger->log_error("hello {}", "world"); - REQUIRE(true == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [error] hello world")); + REQUIRE(true == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [error] hello world", 0s, 0ms)); LogTestController::getInstance().reset(); LogTestController::getInstance().setOff<logging::Logger>(); logger->log_error("hello {}", "world"); - REQUIRE(false == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [error] hello world", std::chrono::seconds(0))); + REQUIRE(false == LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [error] hello world", 0s, 0ms)); LogTestController::getInstance().reset(); } TEST_CASE("Logger configured with an ID prints this ID in every log line", "[logger][id]") { - LogTestController::getInstance().clear(); + LogTestController::getInstance().reset(); LogTestController::getInstance().setTrace<logging::Logger>(); const auto uuid = utils::IdGenerator::getIdGenerator()->generate(); std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(uuid); logger->log_error("hello {}", "world"); - CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [error] hello world (" + uuid.to_string() + ")")); + CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [error] hello world (" + uuid.to_string() + ")", 0s, 0ms)); LogTestController::getInstance().reset(); } @@ -117,8 +117,8 @@ TEST_CASE("Printing of the ID can be disabled in the config", "[logger][id][conf const auto uuid = utils::IdGenerator::getIdGenerator()->generate(); std::shared_ptr<logging::Logger> logger = LogTestController::getInstance(properties)->getLogger<logging::Logger>(uuid); logger->log_error("hello {}", "world"); - CHECK(LogTestController::getInstance(properties)->contains("[org::apache::nifi::minifi::core::logging::Logger] [error] hello world")); - CHECK(id_is_present == LogTestController::getInstance(properties)->contains(uuid.to_string())); + CHECK(LogTestController::getInstance(properties)->contains("[org::apache::nifi::minifi::core::logging::Logger] [error] hello world", 0s, 0ms)); + CHECK(id_is_present == LogTestController::getInstance(properties)->contains(uuid.to_string(), 0s, 0ms)); } struct CStringConvertible { @@ -136,7 +136,7 @@ TEST_CASE("Test log custom string formatting", "[ttl6]") { std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); logger->log_trace("{} {} {}", "one", std::string{"two"}, CStringConvertible{"three"}.c_str()); - REQUIRE(LogTestController::getInstance().contains("[trace] one two three", 0s)); + REQUIRE(LogTestController::getInstance().contains("[trace] one two three", 0s, 0ms)); LogTestController::getInstance().reset(); } @@ -157,7 +157,7 @@ TEST_CASE("Test log lazy string generation", "[ttl7]") { return std::string{"hello debug"}; }); - REQUIRE(LogTestController::getInstance().contains("[debug] hello debug", 0s)); + REQUIRE(LogTestController::getInstance().contains("[debug] hello debug", 0s, 0ms)); REQUIRE(call_count == 1); LogTestController::getInstance().reset(); } @@ -171,7 +171,7 @@ class TestClass2 { }; TEST_CASE("Test ShortenNames", "[ttl8]") { - LogTestController::getInstance().clear(); + LogTestController::getInstance().reset(); std::shared_ptr<logging::LoggerProperties> props = std::make_shared<logging::LoggerProperties>(); props->set("spdlog.shorten_names", "true"); @@ -179,17 +179,17 @@ TEST_CASE("Test ShortenNames", "[ttl8]") { std::shared_ptr<logging::Logger> logger = LogTestController::getInstance(props)->getLogger<logging::Logger>(); logger->log_error("hello {}", "world"); - REQUIRE(true == LogTestController::getInstance(props)->contains("[o::a::n::m::c::l::Logger] [error] hello world")); + REQUIRE(true == LogTestController::getInstance(props)->contains("[o::a::n::m::c::l::Logger] [error] hello world", 0s, 0ms)); logger = LogTestController::getInstance(props)->getLogger<single::TestClass>(); logger->log_error("hello {}", "world"); - REQUIRE(true == LogTestController::getInstance(props)->contains("[s::TestClass] [error] hello world")); + REQUIRE(true == LogTestController::getInstance(props)->contains("[s::TestClass] [error] hello world", 0s, 0ms)); logger = LogTestController::getInstance(props)->getLogger<TestClass2>(); logger->log_error("hello {}", "world"); - REQUIRE(true == LogTestController::getInstance(props)->contains("[TestClass2] [error] hello world")); + REQUIRE(true == LogTestController::getInstance(props)->contains("[TestClass2] [error] hello world", 0s, 0ms)); LogTestController::getInstance(props)->reset(); LogTestController::getInstance().reset(); @@ -215,10 +215,10 @@ class LoggerTestAccessor { static void setCompressionCompressedSegmentSize(logging::LoggerConfiguration& log_config, size_t value) { log_config.compression_manager_.compressed_segment_size = value; } - static size_t getUncompressedSize(logging::LoggerConfiguration& log_config) { + static size_t getUncompressedSize(const logging::LoggerConfiguration& log_config) { return log_config.compression_manager_.getSink()->cached_logs_.size(); } - static bool waitForCompressionToHappen(logging::LoggerConfiguration& log_config) { + static bool waitForCompressionToHappen(const logging::LoggerConfiguration& log_config) { auto sink = log_config.compression_manager_.getSink(); return !sink || minifi::test::utils::verifyEventHappenedInPollTime(1s, [&]{ return sink->cached_logs_.itemCount() == 0; }); } @@ -378,6 +378,7 @@ TEST_CASE("Setting max log entry length to unlimited results in unlimited log en } TEST_CASE("fmt formatting works with the logger") { + LogTestController::getInstance().reset(); LogTestController::getInstance().setTrace<logging::Logger>(); std::shared_ptr<logging::Logger> logger = logging::LoggerFactory<logging::Logger>::getLogger(); std::chrono::minutes duration{1}; @@ -386,10 +387,10 @@ TEST_CASE("fmt formatting works with the logger") { logger->log_critical("{} in hex is {:#x}", 13, 13); logger->log_critical("Unix epoch: {}", std::chrono::system_clock::time_point()); logger->log_critical("{:%Q %q} equals to {:%Q %q}", 2h, std::chrono::duration_cast<std::chrono::seconds>(2h)); - CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [critical] 1m equals to 60s")); - CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [critical] 13 in hex is 0xd")); - CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [critical] Unix epoch: 1970-01-01 00:00:00.00")); - CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [critical] 2 h equals to 7200 s")); + CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [critical] 1m equals to 60s", 0s, 0ms)); + CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [critical] 13 in hex is 0xd", 0s, 0ms)); + CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [critical] Unix epoch: 1970-01-01 00:00:00.00", 0s, 0ms)); + CHECK(LogTestController::getInstance().contains("[org::apache::nifi::minifi::core::logging::Logger] [critical] 2 h equals to 7200 s", 0s, 0ms)); LogTestController::getInstance().reset(); } @@ -407,7 +408,7 @@ std::vector<std::string> generateRandomStrings() { const int index_of_last_char = gsl::narrow<int>(strlen(TEXT_CHARS)) - 1; std::uniform_int_distribution<> distr(0, index_of_last_char); std::vector<char> data(100); - const size_t SEGMENT_COUNT = 5; + constexpr size_t SEGMENT_COUNT = 5; for (size_t idx = 0; idx < SEGMENT_COUNT; ++idx) { std::generate_n(data.begin(), data.size(), [&] { return TEXT_CHARS[static_cast<uint8_t>(distr(eng))]; }); random_strings.push_back(std::string{data.begin(), data.end()} + "." + std::to_string(idx)); diff --git a/libminifi/test/unit/PropertyValidationTests.cpp b/libminifi/test/unit/PropertyValidationTests.cpp index 5a26f77b8..62770fa9b 100644 --- a/libminifi/test/unit/PropertyValidationTests.cpp +++ b/libminifi/test/unit/PropertyValidationTests.cpp @@ -30,10 +30,21 @@ TEST_CASE("Converting invalid PropertyValue") { .withDefaultValue("0") .build(); Property property{property_definition}; - CHECK_FALSE(property.setValue("not int").has_value()); + CHECK_FALSE(property.setValue("not int")); CHECK(property.getValue() == "0"); } +TEST_CASE("Allowed values") { + static constexpr auto abc_without_el = PropertyDefinitionBuilder<3>::createProperty("prop") + .supportsExpressionLanguage(false) + .withAllowedValues({"a", "b", "c"}) + .build(); + + Property property{abc_without_el}; + CHECK_FALSE(property.setValue("d")); + CHECK_FALSE(property.getValue()); +} + TEST_CASE("Parsing int has baggage after") { static constexpr auto property_definition = PropertyDefinitionBuilder<>::createProperty("prop") .withValidator(core::StandardPropertyValidators::INTEGER_VALIDATOR) @@ -50,7 +61,7 @@ TEST_CASE("Parsing int has spaces") { .withDefaultValue("0") .build(); Property property{property_definition}; - CHECK(property.setValue(" 55 ").has_value()); + CHECK(property.setValue(" 55 ")); CHECK(property.getValue() == " 55 "); CHECK_FALSE(property.setValue(" 10000000000000000000 ")); } @@ -61,7 +72,7 @@ TEST_CASE("Parsing bool has baggage after") { .withDefaultValue("true") .build(); Property property{property_definition}; - CHECK_FALSE(property.setValue("false almost bool").has_value()); + CHECK_FALSE(property.setValue("false almost bool")); CHECK(property.getValue() == "true"); } @@ -162,7 +173,6 @@ TEST_CASE("Valid Optional Without Default") { TestConfigurableComponent component; component.setSupportedProperties(std::array<PropertyReference, 1>{property_definition}); CHECK(component.setProperty(property.getName(), "some data")); - std::string value; CHECK(component.getProperty(property.getName()) == "some data"); }
