This is an automated email from the ASF dual-hosted git repository. szaszm pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git
commit ba1188d49f6fd75cb9423b8fdf1e2889530aa45b Author: Ferenc Gerlits <[email protected]> AuthorDate: Fri Oct 6 14:18:47 2023 +0200 MINIFICPP-2185 Upgrade to Visual Studio 2022 Closes #1635 Signed-off-by: Marton Szasz <[email protected]> --- .github/workflows/ci.yml | 69 +++++++++++++++++++--- CMakeLists.txt | 2 +- cmake/BundledOSSPUUID.cmake | 8 ++- cmake/BundledOpenSSL.cmake | 2 +- extensions/aws/processors/S3Processor.cpp | 2 +- extensions/aws/processors/S3Processor.h | 1 + extensions/aws/s3/S3Wrapper.cpp | 4 +- .../azure/storage/AzureDataLakeStorageClient.cpp | 4 +- extensions/elasticsearch/PostElasticsearch.cpp | 8 +-- extensions/expression-language/common/Value.h | 4 +- extensions/libarchive/WriteArchiveStream.cpp | 6 +- extensions/libarchive/tests/MergeFileTests.cpp | 9 +-- extensions/librdkafka/ConsumeKafka.cpp | 12 ++-- extensions/librdkafka/PublishKafka.cpp | 2 +- extensions/mqtt/processors/PublishMQTT.cpp | 2 +- extensions/pdh/PDHCounters.cpp | 4 +- extensions/python/tests/PythonManifestTests.cpp | 3 +- .../tests/SmbConnectionControllerServiceTests.cpp | 3 +- extensions/sql/data/JSONSQLWriter.cpp | 14 +---- extensions/sql/data/JSONSQLWriter.h | 14 +---- .../standard-processors/processors/PutTCP.cpp | 2 +- extensions/windows-event-log/Bookmark.cpp | 6 +- .../CollectorInitiatedSubscription.cpp | 2 +- .../windows-event-log/ConsumeWindowsEventLog.cpp | 8 +-- extensions/windows-event-log/tests/CWELTestUtils.h | 5 +- extensions/windows-event-log/wel/EventPath.cpp | 3 +- extensions/windows-event-log/wel/EventPath.h | 14 +++-- .../windows-event-log/wel/WindowsEventLog.cpp | 13 ++-- libminifi/include/core/PropertyType.h | 4 +- .../include/utils/OpenTelemetryLogDataModelUtils.h | 10 ++-- libminifi/include/utils/OsUtils.h | 4 -- libminifi/include/utils/TestUtils.h | 5 ++ .../include/utils}/UnicodeConversion.h | 27 ++++----- libminifi/src/core/logging/LoggerConfiguration.cpp | 2 +- libminifi/src/core/logging/alert/AlertSink.cpp | 4 +- libminifi/src/io/InputStream.cpp | 2 +- libminifi/src/utils/BaseHTTPClient.cpp | 8 +-- libminifi/src/utils/Cron.cpp | 8 +-- libminifi/src/utils/FileMutex.cpp | 6 +- libminifi/src/utils/NetworkInterfaceInfo.cpp | 3 +- libminifi/src/utils/OsUtils.cpp | 30 ---------- libminifi/src/utils/ProcessCpuUsageTracker.cpp | 1 - libminifi/src/utils/TestUtils.cpp | 62 +++++++++++++++++++ libminifi/src/utils/crypto/ciphers/Aes256Ecb.cpp | 8 +-- libminifi/test/unit/FileSystemRepositoryTests.cpp | 29 ++------- libminifi/test/unit/OsUtilTests.cpp | 20 ------- libminifi/test/unit/StringUtilsTests.cpp | 44 +++++++++++--- 47 files changed, 284 insertions(+), 219 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e891a6aa5..5b39dba81 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,10 +67,10 @@ jobs: with: name: macos-binaries path: build/bin - windows_VS2019: - name: "windows-2019" - runs-on: windows-2019 - timeout-minutes: 180 + windows_VS2022: + name: "windows-2022" + runs-on: windows-2022 + timeout-minutes: 240 steps: - name: Support longpaths run: git config --system core.longpaths true @@ -80,11 +80,11 @@ jobs: uses: actions/cache/restore@v3 with: path: ~/AppData/Local/Mozilla/sccache/cache - key: ${{ runner.os }}-sccache-${{ github.ref }}-${{ github.sha }} + key: ${{ runner.os }}-2022-sccache-${{ github.ref }}-${{ github.sha }} restore-keys: | - ${{ runner.os }}-sccache-${{ github.ref }} - ${{ runner.os }}-sccache-refs/heads/main - ${{ runner.os }}-sccache + ${{ runner.os }}-2022-sccache-${{ github.ref }} + ${{ runner.os }}-2022-sccache-refs/heads/main + ${{ runner.os }}-2022-sccache - name: Run sccache-cache uses: mozilla-actions/[email protected] - name: Install ninja-build tool @@ -114,13 +114,64 @@ jobs: if: always() with: path: ~/AppData/Local/Mozilla/sccache/cache - key: ${{ runner.os }}-sccache-${{ github.ref }}-${{ github.sha }} + key: ${{ runner.os }}-2022-sccache-${{ github.ref }}-${{ github.sha }} - name: test run: cd ..\b && ctest --timeout 300 --parallel %NUMBER_OF_PROCESSORS% -C Release --output-on-failure shell: cmd - name: linter run: cd ..\b && cmake --build . --target linter --config Release -j 8 shell: cmd + windows_VS2019: + name: "windows-2019" + runs-on: windows-2019 + timeout-minutes: 240 + steps: + - name: Support longpaths + run: git config --system core.longpaths true + - id: checkout + uses: actions/checkout@v3 + - name: sccache cache restore + uses: actions/cache/restore@v3 + with: + path: ~/AppData/Local/Mozilla/sccache/cache + key: ${{ runner.os }}-2019-sccache-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-2019-sccache-${{ github.ref }} + ${{ runner.os }}-2019-sccache-refs/heads/main + ${{ runner.os }}-2019-sccache + - name: Run sccache-cache + uses: mozilla-actions/[email protected] + - name: Install ninja-build tool + uses: seanmiddleditch/gha-setup-ninja@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Set up Lua + uses: xpol/[email protected] + - name: Set up NASM for OpenSSL + uses: ilammy/setup-nasm@v1 + - id: install-sqliteodbc-driver + run: | + Invoke-WebRequest -Uri "http://www.ch-werner.de/sqliteodbc/sqliteodbc_w64.exe" -OutFile "sqliteodbc_w64.exe" + if ((Get-FileHash 'sqliteodbc_w64.exe').Hash -ne "0df79be4a4412542839ebf405b20d95a7dfc803da0b0b6b0dc653d30dc82ee84") {Write "Hash mismatch"; Exit 1} + ./sqliteodbc_w64.exe /S + shell: powershell + - name: build + run: | + for /f "usebackq delims=" %%i in (`vswhere.exe -latest -property installationPath`) do if exist "%%i\Common7\Tools\vsdevcmd.bat" call "%%i\Common7\Tools\vsdevcmd.bat" -arch=x64 -host_arch=x64 + win_build_vs.bat ..\b /64 /CI /S /A /PDH /SPLUNK /GCP /ELASTIC /K /L /R /Z /N /RO /PR /PYTHON_SCRIPTING /LUA_SCRIPTING /MQTT /SCCACHE /NINJA + sccache --show-stats + shell: cmd + - name: sccache cache save + uses: actions/cache/save@v3 + if: always() + with: + path: ~/AppData/Local/Mozilla/sccache/cache + key: ${{ runner.os }}-2019-sccache-${{ github.ref }}-${{ github.sha }} + - name: test + run: cd ..\b && ctest --timeout 300 --parallel %NUMBER_OF_PROCESSORS% -C Release --output-on-failure + shell: cmd ubuntu_20_04: name: "ubuntu-20.04" runs-on: ubuntu-20.04 diff --git a/CMakeLists.txt b/CMakeLists.txt index 511aa0434..5ed19b7a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,7 +106,7 @@ endif() # Enable usage of the VERSION specifier if (WIN32) add_compile_definitions(WIN32_LEAN_AND_MEAN _CRT_SECURE_NO_WARNINGS NOMINMAX) - add_compile_options(/W3 /utf-8 /bigobj) + add_compile_options(/W3 /utf-8 /bigobj /MP) endif() if (NOT PORTABLE) diff --git a/cmake/BundledOSSPUUID.cmake b/cmake/BundledOSSPUUID.cmake index c4fa1523b..de9e99e98 100644 --- a/cmake/BundledOSSPUUID.cmake +++ b/cmake/BundledOSSPUUID.cmake @@ -39,7 +39,13 @@ function(use_bundled_osspuuid SOURCE_DIR BINARY_DIR) ENDFOREACH(BYPRODUCT) # Build project - set(CONFIGURE_COMMAND ./configure "CC=${CMAKE_C_COMPILER}" "CXX=${CMAKE_CXX_COMPILER}" "CFLAGS=${PASSTHROUGH_CMAKE_C_FLAGS} -fPIC" "CXXFLAGS=${PASSTHROUGH_CMAKE_CXX_FLAGS} -fPIC" --enable-shared=no --with-cxx --without-perl --without-php --without-pgsql "--prefix=${BINARY_DIR}/thirdparty/ossp-uuid-install") + if(WIN32) + set(ADDITIONAL_COMPILER_FLAGS "") + else() + set(ADDITIONAL_COMPILER_FLAGS "-fPIC") + endif() + set(CONFIGURE_COMMAND ./configure "CC=${CMAKE_C_COMPILER}" "CXX=${CMAKE_CXX_COMPILER}" "CFLAGS=${PASSTHROUGH_CMAKE_C_FLAGS} ${ADDITIONAL_COMPILER_FLAGS}" "CXXFLAGS=${PASSTHROUGH_CMAKE_CXX_FLAGS} ${ADDITIONAL_COMPILER_FLAGS}" --enable-shared=no --with-cxx --without-perl --without-php --without-pgsql "--prefix=${BINARY_DIR}/thirdparty/ossp-uuid-install") + string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type) if(NOT build_type MATCHES debug) list(APPEND CONFIGURE_COMMAND --enable-debug=yes) diff --git a/cmake/BundledOpenSSL.cmake b/cmake/BundledOpenSSL.cmake index 35e26d2f6..9ec3ddee5 100644 --- a/cmake/BundledOpenSSL.cmake +++ b/cmake/BundledOpenSSL.cmake @@ -75,7 +75,7 @@ function(use_openssl SOURCE_DIR BINARY_DIR) URL_HASH "SHA256=b3aa61334233b852b63ddb048df181177c2c659eb9d4376008118f9c08d07674" SOURCE_DIR "${BINARY_DIR}/thirdparty/openssl-src" BUILD_IN_SOURCE true - CONFIGURE_COMMAND perl Configure "CFLAGS=${PASSTHROUGH_CMAKE_C_FLAGS} -fPIC" "CXXFLAGS=${PASSTHROUGH_CMAKE_CXX_FLAGS} -fPIC" ${OPENSSL_SHARED_FLAG} no-tests "--prefix=${OPENSSL_BIN_DIR}" "--openssldir=${OPENSSL_BIN_DIR}" + CONFIGURE_COMMAND perl Configure "CFLAGS=${PASSTHROUGH_CMAKE_C_FLAGS}" "CXXFLAGS=${PASSTHROUGH_CMAKE_CXX_FLAGS}" ${OPENSSL_SHARED_FLAG} no-tests "--prefix=${OPENSSL_BIN_DIR}" "--openssldir=${OPENSSL_BIN_DIR}" BUILD_BYPRODUCTS ${OPENSSL_LIBRARIES_LIST} PATCH_COMMAND ${PC} EXCLUDE_FROM_ALL TRUE diff --git a/extensions/aws/processors/S3Processor.cpp b/extensions/aws/processors/S3Processor.cpp index 960b4de17..ee2aa2e05 100644 --- a/extensions/aws/processors/S3Processor.cpp +++ b/extensions/aws/processors/S3Processor.cpp @@ -121,7 +121,7 @@ void S3Processor::onSchedule(const std::shared_ptr<core::ProcessContext>& contex if (auto communications_timeout = context->getProperty<core::TimePeriodValue>(CommunicationsTimeout)) { logger_->log_debug("S3Processor: Communications Timeout %" PRId64 " ms", communications_timeout->getMilliseconds().count()); - client_config_->connectTimeoutMs = gsl::narrow<int64_t>(communications_timeout->getMilliseconds().count()); + client_config_->connectTimeoutMs = gsl::narrow<long>(communications_timeout->getMilliseconds().count()); // NOLINT(runtime/int) } else { throw Exception(PROCESS_SCHEDULE_EXCEPTION, "Communications Timeout missing or invalid"); } diff --git a/extensions/aws/processors/S3Processor.h b/extensions/aws/processors/S3Processor.h index 86cd84fea..d6ce8f848 100644 --- a/extensions/aws/processors/S3Processor.h +++ b/extensions/aws/processors/S3Processor.h @@ -25,6 +25,7 @@ #include <optional> #include <set> #include <string> +#include <string_view> #include <utility> #include "aws/core/auth/AWSCredentialsProvider.h" diff --git a/extensions/aws/s3/S3Wrapper.cpp b/extensions/aws/s3/S3Wrapper.cpp index 059332233..2e9e27ace 100644 --- a/extensions/aws/s3/S3Wrapper.cpp +++ b/extensions/aws/s3/S3Wrapper.cpp @@ -129,7 +129,7 @@ std::optional<S3Wrapper::UploadPartsResult> S3Wrapper::uploadParts(const PutObje auto upload_part_request = Aws::S3::Model::UploadPartRequest{} .WithBucket(put_object_params.bucket) .WithKey(put_object_params.object_key) - .WithPartNumber(part_number) + .WithPartNumber(gsl::narrow<int>(part_number)) .WithUploadId(upload_state.upload_id); upload_part_request.SetBody(stream_ptr); @@ -164,7 +164,7 @@ std::optional<Aws::S3::Model::CompleteMultipartUploadResult> S3Wrapper::complete for (size_t i = 0; i < upload_parts_result.part_etags.size(); ++i) { auto part = Aws::S3::Model::CompletedPart{} .WithETag(upload_parts_result.part_etags[i]) - .WithPartNumber(i + 1); + .WithPartNumber(gsl::narrow<int>(i + 1)); completed_multipart_upload.AddParts(part); } diff --git a/extensions/azure/storage/AzureDataLakeStorageClient.cpp b/extensions/azure/storage/AzureDataLakeStorageClient.cpp index 0b5e97079..7f588139f 100644 --- a/extensions/azure/storage/AzureDataLakeStorageClient.cpp +++ b/extensions/azure/storage/AzureDataLakeStorageClient.cpp @@ -39,7 +39,7 @@ std::unique_ptr<Azure::Storage::Files::DataLake::DataLakeFileSystemClient> Azure const AzureStorageCredentials& credentials, const std::string& file_system_name, std::optional<uint64_t> number_of_retries) { Azure::Storage::Files::DataLake::DataLakeClientOptions options; if (number_of_retries) { - options.Retry.MaxRetries = *number_of_retries; + options.Retry.MaxRetries = gsl::narrow<int32_t>(*number_of_retries); } if (credentials.getUseManagedIdentityCredentials()) { @@ -89,7 +89,7 @@ std::unique_ptr<io::InputStream> AzureDataLakeStorageClient::fetchFile(const Fet if (params.range_start || params.range_length) { Azure::Core::Http::HttpRange range; if (params.range_start) { - range.Offset = *params.range_start; + range.Offset = gsl::narrow<int64_t>(*params.range_start); } if (params.range_length) { diff --git a/extensions/elasticsearch/PostElasticsearch.cpp b/extensions/elasticsearch/PostElasticsearch.cpp index a0f0f3740..62202b974 100644 --- a/extensions/elasticsearch/PostElasticsearch.cpp +++ b/extensions/elasticsearch/PostElasticsearch.cpp @@ -142,15 +142,15 @@ class ElasticPayload { [[nodiscard]] std::string headerString() const { rapidjson::Document first_line = rapidjson::Document(rapidjson::kObjectType); - auto operation_index_key = rapidjson::Value(operation_.data(), operation_.size()); + auto operation_index_key = rapidjson::Value(operation_.data(), gsl::narrow<rapidjson::SizeType>(operation_.size())); first_line.AddMember(operation_index_key, rapidjson::Value{rapidjson::kObjectType}, first_line.GetAllocator()); auto& operation_request = first_line[operation_.c_str()]; - auto index_json = rapidjson::Value(index_.data(), index_.size()); + auto index_json = rapidjson::Value(index_.data(), gsl::narrow<rapidjson::SizeType>(index_.size())); operation_request.AddMember("_index", index_json, first_line.GetAllocator()); if (id_) { - auto id_json = rapidjson::Value(id_->data(), id_->size()); + auto id_json = rapidjson::Value(id_->data(), gsl::narrow<rapidjson::SizeType>(id_->size())); operation_request.AddMember("_id", id_json, first_line.GetAllocator()); } @@ -211,7 +211,7 @@ void processResponseFromElastic(const rapidjson::Document& response, core::Proce auto& items = response["items"]; gsl_Expects(items.IsArray()); gsl_Expects(items.Size() == flowfiles_sent.size()); - for (size_t i = 0; i < items.Size(); ++i) { + for (rapidjson::SizeType i = 0; i < items.Size(); ++i) { gsl_Expects(items[i].IsObject()); for (auto it = items[i].MemberBegin(); it != items[i].MemberEnd(); ++it) { addAttributesFromResponse("elasticsearch", it, *flowfiles_sent[i]); diff --git a/extensions/expression-language/common/Value.h b/extensions/expression-language/common/Value.h index ea524b77c..69b232fd4 100644 --- a/extensions/expression-language/common/Value.h +++ b/extensions/expression-language/common/Value.h @@ -142,9 +142,9 @@ class Value { if (value.empty()) return default_value; try { return std::invoke(conversion_function, value); - } catch (const std::invalid_argument& ex) { + } catch (const std::invalid_argument&) { throw std::invalid_argument{utils::StringUtils::join_pack(context, " failed to parse \"", value, "\": invalid argument")}; - } catch (const std::out_of_range& ex) { + } catch (const std::out_of_range&) { throw std::out_of_range{utils::StringUtils::join_pack(context, " failed to parse \"", value, "\": out of range")}; } } diff --git a/extensions/libarchive/WriteArchiveStream.cpp b/extensions/libarchive/WriteArchiveStream.cpp index 4c60233d8..98b9122d1 100644 --- a/extensions/libarchive/WriteArchiveStream.cpp +++ b/extensions/libarchive/WriteArchiveStream.cpp @@ -30,7 +30,7 @@ WriteArchiveStreamImpl::archive_ptr WriteArchiveStreamImpl::createWriteArchive() return nullptr; } - int result; + int result = 0; result = archive_write_set_format_ustar(arch.get()); if (result != ARCHIVE_OK) { @@ -94,7 +94,7 @@ bool WriteArchiveStreamImpl::newEntry(const EntryInfo& info) { return false; } archive_entry_set_pathname(arch_entry_.get(), info.filename.c_str()); - archive_entry_set_size(arch_entry_.get(), info.size); + archive_entry_set_size(arch_entry_.get(), gsl::narrow<la_int64_t>(info.size)); archive_entry_set_mode(arch_entry_.get(), S_IFREG | 0755); int result = archive_write_header(arch_.get(), arch_entry_.get()); @@ -115,7 +115,7 @@ size_t WriteArchiveStreamImpl::write(const uint8_t* data, size_t len) { } gsl_Expects(data); - int result = archive_write_data(arch_.get(), data, len); + int result = gsl::narrow<int>(archive_write_data(arch_.get(), data, len)); if (result < 0) { logger_->log_error("Archive write data error %s", archive_error_string(arch_.get())); arch_entry_.reset(); diff --git a/extensions/libarchive/tests/MergeFileTests.cpp b/extensions/libarchive/tests/MergeFileTests.cpp index af43a801b..d2699799e 100644 --- a/extensions/libarchive/tests/MergeFileTests.cpp +++ b/extensions/libarchive/tests/MergeFileTests.cpp @@ -90,9 +90,9 @@ class FixedBuffer { } template<class Input> - int write(Input& input, std::size_t len) { + int64_t write(Input& input, std::size_t len) { REQUIRE(size_ + len <= capacity_); - int total_read = 0; + size_t total_read = 0; do { const size_t ret{input.read(as_writable_bytes(std::span(end(), len)))}; if (ret == 0) break; @@ -101,8 +101,9 @@ class FixedBuffer { len -= ret; total_read += ret; } while (size_ != capacity_); - return total_read; + return gsl::narrow<int64_t>(total_read); } + int64_t operator()(const std::shared_ptr<minifi::io::InputStream>& stream) { return write(*stream, capacity_); } @@ -132,7 +133,7 @@ std::vector<FixedBuffer> read_archives(const FixedBuffer& input) { struct archive_entry *ae = nullptr; while (archive_read_next_header(a, &ae) == ARCHIVE_OK) { - int size = gsl::narrow<int>(archive_entry_size(ae)); + int64_t size{archive_entry_size(ae)}; FixedBuffer buf(size); ArchiveEntryReader reader(a); auto ret = buf.write(reader, buf.capacity()); diff --git a/extensions/librdkafka/ConsumeKafka.cpp b/extensions/librdkafka/ConsumeKafka.cpp index dfab503a3..a2823488f 100644 --- a/extensions/librdkafka/ConsumeKafka.cpp +++ b/extensions/librdkafka/ConsumeKafka.cpp @@ -113,7 +113,7 @@ void rebalance_cb(rd_kafka_t* rk, rd_kafka_resp_err_t trigger, rd_kafka_topic_pa } // namespace void ConsumeKafka::create_topic_partition_list() { - kf_topic_partition_list_ = { rd_kafka_topic_partition_list_new(topic_names_.size()), utils::rd_kafka_topic_partition_list_deleter() }; + kf_topic_partition_list_ = { rd_kafka_topic_partition_list_new(gsl::narrow<int>(topic_names_.size())), utils::rd_kafka_topic_partition_list_deleter() }; // On subscriptions any topics prefixed with ^ will be regex matched if (utils::StringUtils::equalsIgnoreCase(TOPIC_FORMAT_PATTERNS, topic_name_format_)) { @@ -229,8 +229,8 @@ std::vector<std::unique_ptr<rd_kafka_message_t, utils::rd_kafka_message_deleter> auto elapsed = std::chrono::steady_clock::now() - start; while (messages.size() < max_poll_records_ && elapsed < max_poll_time_milliseconds_) { logger_->log_debug("Polling for new messages for %d milliseconds...", max_poll_time_milliseconds_.count()); - std::unique_ptr<rd_kafka_message_t, utils::rd_kafka_message_deleter> - message { rd_kafka_consumer_poll(consumer_.get(), std::chrono::duration_cast<std::chrono::milliseconds>(max_poll_time_milliseconds_ - elapsed).count()), utils::rd_kafka_message_deleter() }; + const auto timeout_ms = gsl::narrow<int>(std::chrono::duration_cast<std::chrono::milliseconds>(max_poll_time_milliseconds_ - elapsed).count()); + std::unique_ptr<rd_kafka_message_t, utils::rd_kafka_message_deleter> message{rd_kafka_consumer_poll(consumer_.get(), timeout_ms)}; if (!message) { break; } @@ -281,7 +281,7 @@ std::string ConsumeKafka::resolve_duplicate_headers(const std::vector<std::strin std::vector<std::string> ConsumeKafka::get_matching_headers(const rd_kafka_message_t& message, const std::string& header_name) const { // Headers fetched this way are freed when rd_kafka_message_destroy is called // Detaching them using rd_kafka_message_detach_headers does not seem to work - rd_kafka_headers_t* headers_raw; + rd_kafka_headers_t* headers_raw = nullptr; const rd_kafka_resp_err_t get_header_response = rd_kafka_message_headers(&message, &headers_raw); if (RD_KAFKA_RESP_ERR__NOENT == get_header_response) { return {}; @@ -291,8 +291,8 @@ std::vector<std::string> ConsumeKafka::get_matching_headers(const rd_kafka_messa } std::vector<std::string> matching_headers; for (std::size_t header_idx = 0;; ++header_idx) { - const char* value; // Not to be freed - std::size_t size; + const char* value = nullptr; // Not to be freed + std::size_t size = 0; if (RD_KAFKA_RESP_ERR_NO_ERROR != rd_kafka_header_get(headers_raw, header_idx, header_name.c_str(), (const void**)(&value), &size)) { break; } diff --git a/extensions/librdkafka/PublishKafka.cpp b/extensions/librdkafka/PublishKafka.cpp index 626feb784..d5dd5b758 100644 --- a/extensions/librdkafka/PublishKafka.cpp +++ b/extensions/librdkafka/PublishKafka.cpp @@ -306,7 +306,7 @@ class ReadCallback { error_ = rd_kafka_err2str(err); return read_size_; } - read_size_ += readRet; + read_size_ += gsl::narrow<uint32_t>(readRet); } return read_size_; } diff --git a/extensions/mqtt/processors/PublishMQTT.cpp b/extensions/mqtt/processors/PublishMQTT.cpp index 03fe3ab95..9ede561fa 100644 --- a/extensions/mqtt/processors/PublishMQTT.cpp +++ b/extensions/mqtt/processors/PublishMQTT.cpp @@ -216,7 +216,7 @@ void PublishMQTT::setMqtt5Properties(MQTTAsync_message& message, const std::stri if (message_expiry_interval_.has_value()) { MQTTProperty property; property.identifier = MQTTPROPERTY_CODE_MESSAGE_EXPIRY_INTERVAL; - property.value.integer4 = message_expiry_interval_->count(); // NOLINT(cppcoreguidelines-pro-type-union-access) + property.value.integer4 = gsl::narrow<int>(message_expiry_interval_->count()); // NOLINT(cppcoreguidelines-pro-type-union-access) MQTTProperties_add(&message.properties, &property); } diff --git a/extensions/pdh/PDHCounters.cpp b/extensions/pdh/PDHCounters.cpp index 1b880a091..d9a003b25 100644 --- a/extensions/pdh/PDHCounters.cpp +++ b/extensions/pdh/PDHCounters.cpp @@ -55,7 +55,7 @@ std::string PDHCounter::getCounterName() const { } void SinglePDHCounter::addToJson(rapidjson::Value& body, rapidjson::Document::AllocatorType& alloc) const { - rapidjson::Value key(getCounterName().c_str(), getCounterName().length(), alloc); + rapidjson::Value key(getCounterName().c_str(), gsl::narrow<rapidjson::SizeType>(getCounterName().length()), alloc); rapidjson::Value& group_node = acquireNode(getObjectName(), body, alloc); group_node.AddMember(key, getValue(), alloc); } @@ -91,7 +91,7 @@ void PDHCounterArray::addToJson(rapidjson::Value& body, rapidjson::Document::All rapidjson::Value& counter_node = acquireNode(node_name, group_node, alloc); rapidjson::Value value = getValue(i); rapidjson::Value key; - key.SetString(getCounterName().c_str(), getCounterName().length(), alloc); + key.SetString(getCounterName().c_str(), gsl::narrow<rapidjson::SizeType>(getCounterName().length()), alloc); counter_node.AddMember(key, value, alloc); } } diff --git a/extensions/python/tests/PythonManifestTests.cpp b/extensions/python/tests/PythonManifestTests.cpp index 2867f125b..5ec989ae9 100644 --- a/extensions/python/tests/PythonManifestTests.cpp +++ b/extensions/python/tests/PythonManifestTests.cpp @@ -25,6 +25,7 @@ #include "flow-tests/TestControllerWithFlow.h" #include "EmptyFlow.h" #include "c2/C2MetricsPublisher.h" +#include "utils/gsl.h" using minifi::state::response::SerializedResponseNode; @@ -40,7 +41,7 @@ const SerializedResponseNode& getNode(const std::vector<SerializedResponseNode>& for (auto& node : nodes) { if (node.name == name) return node; } - assert(false); + gsl_FailFast(); } TEST_CASE("Python processor's description is part of the manifest") { diff --git a/extensions/smb/tests/SmbConnectionControllerServiceTests.cpp b/extensions/smb/tests/SmbConnectionControllerServiceTests.cpp index d0aadd451..3ac0b4f63 100644 --- a/extensions/smb/tests/SmbConnectionControllerServiceTests.cpp +++ b/extensions/smb/tests/SmbConnectionControllerServiceTests.cpp @@ -20,6 +20,7 @@ #include "Catch.h" #include "SmbConnectionControllerService.h" #include "utils/TempSmbShare.h" +#include "utils/UnicodeConversion.h" namespace org::apache::nifi::minifi::extensions::smb::test { @@ -49,7 +50,7 @@ TEST_CASE_METHOD(SmbConnectionControllerServiceFixture, "SmbConnectionController SECTION("Valid share") { plan_->setProperty(smb_connection_node_, SmbConnectionControllerService::Hostname, "localhost"); - plan_->setProperty(smb_connection_node_, SmbConnectionControllerService::Share, minifi::utils::OsUtils::wideStringToString(share_local_name)); + plan_->setProperty(smb_connection_node_, SmbConnectionControllerService::Share, minifi::utils::to_string(share_local_name)); REQUIRE_NOTHROW(plan_->finalize()); diff --git a/extensions/sql/data/JSONSQLWriter.cpp b/extensions/sql/data/JSONSQLWriter.cpp index 1c61a7b83..d77ff2741 100644 --- a/extensions/sql/data/JSONSQLWriter.cpp +++ b/extensions/sql/data/JSONSQLWriter.cpp @@ -22,11 +22,7 @@ #include "rapidjson/prettywriter.h" #include "Exception.h" -namespace org { -namespace apache { -namespace nifi { -namespace minifi { -namespace sql { +namespace org::apache::nifi::minifi::sql { JSONSQLWriter::JSONSQLWriter(bool pretty, ColumnFilter column_filter) : pretty_(pretty), current_batch_(rapidjson::kArrayType), column_filter_(std::move(column_filter)) { @@ -83,7 +79,7 @@ void JSONSQLWriter::addToJSONRow(const std::string& column_name, rapidjson::Valu rapidjson::Value JSONSQLWriter::toJSONString(const std::string& s) { rapidjson::Value jsonValue; - jsonValue.SetString(s.c_str(), s.size(), current_batch_.GetAllocator()); + jsonValue.SetString(s.c_str(), gsl::narrow<rapidjson::SizeType>(s.size()), current_batch_.GetAllocator()); return jsonValue; } @@ -102,8 +98,4 @@ std::string JSONSQLWriter::toString() { return {buffer.GetString(), buffer.GetSize()}; } -} // namespace sql -} // namespace minifi -} // namespace nifi -} // namespace apache -} // namespace org +} // namespace org::apache::nifi::minifi::sql diff --git a/extensions/sql/data/JSONSQLWriter.h b/extensions/sql/data/JSONSQLWriter.h index e4e9af433..966c1b8f7 100644 --- a/extensions/sql/data/JSONSQLWriter.h +++ b/extensions/sql/data/JSONSQLWriter.h @@ -24,11 +24,7 @@ #include "SQLWriter.h" -namespace org { -namespace apache { -namespace nifi { -namespace minifi { -namespace sql { +namespace org::apache::nifi::minifi::sql { class JSONSQLWriter: public SQLWriter { public: @@ -63,10 +59,4 @@ private: ColumnFilter column_filter_; }; -} /* namespace sql */ -} /* namespace minifi */ -} /* namespace nifi */ -} /* namespace apache */ -} /* namespace org */ - - +} // namespace org::apache::nifi::minifi::sql diff --git a/extensions/standard-processors/processors/PutTCP.cpp b/extensions/standard-processors/processors/PutTCP.cpp index 4c80721c5..8bef0e0ac 100644 --- a/extensions/standard-processors/processors/PutTCP.cpp +++ b/extensions/standard-processors/processors/PutTCP.cpp @@ -215,7 +215,7 @@ asio::awaitable<std::error_code> ConnectionHandler<SocketType>::establishNewConn continue; } if (max_size_of_socket_send_buffer_) - socket.lowest_layer().set_option(TcpSocket::send_buffer_size(*max_size_of_socket_send_buffer_)); + socket.lowest_layer().set_option(TcpSocket::send_buffer_size(gsl::narrow<int>(*max_size_of_socket_send_buffer_))); socket_.emplace(std::move(socket)); co_return std::error_code(); } diff --git a/extensions/windows-event-log/Bookmark.cpp b/extensions/windows-event-log/Bookmark.cpp index dcdaadde5..dc75fac65 100644 --- a/extensions/windows-event-log/Bookmark.cpp +++ b/extensions/windows-event-log/Bookmark.cpp @@ -23,9 +23,9 @@ #include <utility> #include <fstream> -#include "wel/UnicodeConversion.h" #include "utils/file/FileUtils.h" #include "utils/OsUtils.h" +#include "utils/UnicodeConversion.h" namespace org::apache::nifi::minifi::processors { static const std::string BOOKMARK_KEY = "bookmark"; @@ -41,7 +41,7 @@ Bookmark::Bookmark(const wel::EventPath& path, state_manager_(state_manager) { std::unordered_map<std::string, std::string> state_map; if (state_manager_->get(state_map) && state_map.count(BOOKMARK_KEY) == 1U) { - bookmarkXml_ = wel::to_wstring(state_map[BOOKMARK_KEY].c_str()); + bookmarkXml_ = utils::to_wstring(state_map[BOOKMARK_KEY]); } else if (!bookmarkRootDir.empty()) { filePath_ = bookmarkRootDir / "uuid" / uuid.to_string().view() / "Bookmark.txt"; @@ -122,7 +122,7 @@ bool Bookmark::saveBookmarkXml(const std::wstring& bookmarkXml) { bookmarkXml_ = bookmarkXml; std::unordered_map<std::string, std::string> state_map; - state_map[BOOKMARK_KEY] = wel::to_string(bookmarkXml_.c_str()); + state_map[BOOKMARK_KEY] = utils::to_string(bookmarkXml_); return state_manager_->set(state_map); } diff --git a/extensions/windows-event-log/CollectorInitiatedSubscription.cpp b/extensions/windows-event-log/CollectorInitiatedSubscription.cpp index 036fbcb8b..6088332d8 100644 --- a/extensions/windows-event-log/CollectorInitiatedSubscription.cpp +++ b/extensions/windows-event-log/CollectorInitiatedSubscription.cpp @@ -112,7 +112,7 @@ void CollectorInitiatedSubscription::onTrigger(const std::shared_ptr<core::Proce } else if (auto inactive_duration_to_reconnect_ms = context->getProperty<core::TimePeriodValue>(InactiveDurationToReconnect) | utils::transform([](const auto& time_period_value) { return time_period_value.getMilliseconds().count(); }); inactive_duration_to_reconnect_ms && *inactive_duration_to_reconnect_ms > 0) { - if ((now - lastActivityTimestamp_) > *inactive_duration_to_reconnect_ms) { + if ((now - lastActivityTimestamp_) > gsl::narrow<uint64_t>(*inactive_duration_to_reconnect_ms)) { logger_->log_info("Exceeds configured 'inactive duration to reconnect' %lld ms. Unsubscribe to reconnect..", *inactive_duration_to_reconnect_ms); unsubscribe(); } diff --git a/extensions/windows-event-log/ConsumeWindowsEventLog.cpp b/extensions/windows-event-log/ConsumeWindowsEventLog.cpp index 927c72542..6fc0c5ff5 100644 --- a/extensions/windows-event-log/ConsumeWindowsEventLog.cpp +++ b/extensions/windows-event-log/ConsumeWindowsEventLog.cpp @@ -36,16 +36,16 @@ #include "wel/LookupCacher.h" #include "wel/MetadataWalker.h" #include "wel/XMLString.h" -#include "wel/UnicodeConversion.h" #include "wel/JSONUtils.h" +#include "wel/UniqueEvtHandle.h" #include "io/BufferStream.h" #include "core/ProcessContext.h" #include "core/ProcessSession.h" #include "core/Resource.h" #include "Bookmark.h" -#include "wel/UniqueEvtHandle.h" #include "utils/Deleters.h" +#include "utils/UnicodeConversion.h" #include "logging/LoggerConfiguration.h" #include "utils/gsl.h" @@ -445,7 +445,7 @@ nonstd::expected<std::string, std::string> ConsumeWindowsEventLog::renderEventAs } } logger_->log_trace("Event rendered with size %" PRIu32, used); - return wel::to_string(buf.get()); + return utils::to_string(std::wstring{buf.get()}); } nonstd::expected<cwel::EventRender, std::string> ConsumeWindowsEventLog::createEventRender(EVT_HANDLE hEvent) { @@ -573,7 +573,7 @@ void ConsumeWindowsEventLog::refreshTimeZoneData() { tzoffset << (tzbias >= 0 ? '+' : '-') << std::setfill('0') << std::setw(2) << std::abs(tzbias) / 60 << ":" << std::setfill('0') << std::setw(2) << std::abs(tzbias) % 60; - timezone_name_ = wel::to_string(tzstr.c_str()); + timezone_name_ = utils::to_string(tzstr); timezone_offset_ = tzoffset.str(); logger_->log_trace("Timezone name: %s, offset: %s", timezone_name_, timezone_offset_); diff --git a/extensions/windows-event-log/tests/CWELTestUtils.h b/extensions/windows-event-log/tests/CWELTestUtils.h index 01d3effad..d3aa867af 100644 --- a/extensions/windows-event-log/tests/CWELTestUtils.h +++ b/extensions/windows-event-log/tests/CWELTestUtils.h @@ -28,7 +28,9 @@ #include "processors/PutFile.h" #include "TestBase.h" #include "Catch.h" +#include "utils/StringUtils.h" #include "utils/TestUtils.h" +#include "utils/UnicodeConversion.h" #include "utils/file/FileUtils.h" #include "utils/gsl.h" @@ -97,7 +99,8 @@ class OutputFormatTestController : public TestController { }; void generateLogFile(const std::wstring& channel, const std::filesystem::path& path) { - HANDLE event_log = OpenEventLog(NULL, std::string(channel.begin(), channel.end()).c_str()); + const auto channel_as_string = utils::to_string(channel); + HANDLE event_log = OpenEventLog(NULL, channel_as_string.c_str()); auto guard = gsl::finally([&] {CloseEventLog(event_log);}); if (!EvtExportLog(NULL, channel.c_str(), L"*", path.wstring().c_str(), EvtExportLogChannelPath)) { diff --git a/extensions/windows-event-log/wel/EventPath.cpp b/extensions/windows-event-log/wel/EventPath.cpp index adc4d9ad1..b190b20f5 100644 --- a/extensions/windows-event-log/wel/EventPath.cpp +++ b/extensions/windows-event-log/wel/EventPath.cpp @@ -19,10 +19,11 @@ #include "EventPath.h" #include <utility> #include "utils/StringUtils.h" +#include "utils/UnicodeConversion.h" namespace org::apache::nifi::minifi::wel { -EventPath::EventPath(std::wstring wstr) : EventPath(std::string(wstr.begin(), wstr.end())) {} +EventPath::EventPath(const std::wstring& wstr) : EventPath(utils::to_string(wstr)) {} EventPath::EventPath(std::string str) { constexpr std::string_view saved_log_prefix = "SavedLog:"; diff --git a/extensions/windows-event-log/wel/EventPath.h b/extensions/windows-event-log/wel/EventPath.h index 5b4c295d6..dea8d60dc 100644 --- a/extensions/windows-event-log/wel/EventPath.h +++ b/extensions/windows-event-log/wel/EventPath.h @@ -20,8 +20,11 @@ #include <windows.h> #include <winevt.h> + #include <string> +#include "utils/gsl.h" + namespace org::apache::nifi::minifi::wel { class EventPath { @@ -32,26 +35,27 @@ class EventPath { }; EventPath() = default; - explicit EventPath(std::wstring wstr); + explicit EventPath(const std::wstring& wstr); explicit EventPath(std::string str); - constexpr const std::wstring& wstr() const noexcept { + [[nodiscard]] constexpr const std::wstring& wstr() const noexcept { return wstr_; } - constexpr const std::string& str() const noexcept { + [[nodiscard]] constexpr const std::string& str() const noexcept { return str_; } - constexpr EventPath::Kind kind() const noexcept { + [[nodiscard]] constexpr EventPath::Kind kind() const noexcept { return kind_; } - constexpr EVT_QUERY_FLAGS getQueryFlags() const noexcept { + [[nodiscard]] constexpr EVT_QUERY_FLAGS getQueryFlags() const noexcept { switch (kind_) { case Kind::CHANNEL: return EvtQueryChannelPath; case Kind::FILE: return EvtQueryFilePath; } + gsl_FailFast(); } private: diff --git a/extensions/windows-event-log/wel/WindowsEventLog.cpp b/extensions/windows-event-log/wel/WindowsEventLog.cpp index ce10b91d0..0140ee707 100644 --- a/extensions/windows-event-log/wel/WindowsEventLog.cpp +++ b/extensions/windows-event-log/wel/WindowsEventLog.cpp @@ -15,6 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "WindowsEventLog.h" + #include <winmeta.h> #include <algorithm> @@ -22,10 +24,9 @@ #include <memory> #include <string> -#include "WindowsEventLog.h" -#include "UnicodeConversion.h" #include "utils/Deleters.h" #include "utils/gsl.h" +#include "utils/UnicodeConversion.h" #include "UniqueEvtHandle.h" namespace org::apache::nifi::minifi::wel { @@ -141,9 +142,7 @@ std::string WindowsEventLogMetadataImpl::getEventData(EVT_FORMAT_MESSAGE_FLAGS f if (EvtFormatMessageKeyword == flags) { buffer.get()[num_chars_used - 1] = L'\0'; } - std::wstring str(buffer.get()); - event_data = std::string(str.begin(), str.end()); - return event_data; + return utils::to_string(std::wstring{buffer.get()}); } nonstd::expected<std::string, std::error_code> WindowsEventLogHandler::getEventMessage(EVT_HANDLE eventHandle) const { @@ -156,7 +155,7 @@ nonstd::expected<std::string, std::error_code> WindowsEventLogHandler::getEventM bool evt_format_succeeded = EvtFormatMessage(metadata_provider_.get(), eventHandle, 0, 0, nullptr, EvtFormatMessageEvent, num_chars_in_buffer, buffer.get(), &num_chars_used); if (evt_format_succeeded) - return to_string(buffer.get()); + return utils::to_string(std::wstring{buffer.get()}); DWORD status = GetLastError(); @@ -170,7 +169,7 @@ nonstd::expected<std::string, std::error_code> WindowsEventLogHandler::getEventM if (EvtFormatMessage(metadata_provider_.get(), eventHandle, 0, 0, nullptr, EvtFormatMessageEvent, num_chars_in_buffer, buffer.get(), &num_chars_used)) - return to_string(buffer.get()); + return utils::to_string(std::wstring{buffer.get()}); return nonstd::make_unexpected(utils::OsUtils::windowsErrorToErrorCode(GetLastError())); } diff --git a/libminifi/include/core/PropertyType.h b/libminifi/include/core/PropertyType.h index 880e35fdf..e7c86f222 100644 --- a/libminifi/include/core/PropertyType.h +++ b/libminifi/include/core/PropertyType.h @@ -138,7 +138,7 @@ class IntegerPropertyType : public PropertyType { [[nodiscard]] ValidationResult validate(const std::string &subject, const std::string &input) const override { try { - std::stoi(input); + (void) std::stoi(input); return ValidationResult{.valid = true, .subject = subject, .input = input}; } catch (...) { } @@ -164,7 +164,7 @@ class UnsignedIntPropertyType : public PropertyType { if (negative) { throw std::out_of_range("non negative expected"); } - std::stoul(input); + (void) std::stoul(input); return ValidationResult{.valid = true, .subject = subject, .input = input}; } catch (...) { } diff --git a/libminifi/include/utils/OpenTelemetryLogDataModelUtils.h b/libminifi/include/utils/OpenTelemetryLogDataModelUtils.h index 5385e9e6f..c9c639116 100644 --- a/libminifi/include/utils/OpenTelemetryLogDataModelUtils.h +++ b/libminifi/include/utils/OpenTelemetryLogDataModelUtils.h @@ -29,7 +29,7 @@ class OpenTelemetryLogDataModel { public: static void appendEventInformation(rapidjson::Document& root, const std::string& event_identifier) { rapidjson::Value name; - name.SetString(event_identifier.c_str(), event_identifier.length(), root.GetAllocator()); + name.SetString(event_identifier.c_str(), gsl::narrow<rapidjson::SizeType>(event_identifier.length()), root.GetAllocator()); root.AddMember("Name", name, root.GetAllocator()); root.AddMember("Timestamp", rapidjson::Value().SetInt64(std::time(0)), root.GetAllocator()); } @@ -48,7 +48,7 @@ class OpenTelemetryLogDataModel { static void appendHostName(rapidjson::Value& resource, rapidjson::Document::AllocatorType& allocator) { std::string hostname = utils::net::getMyHostName(); rapidjson::Value hostname_value; - hostname_value.SetString(hostname.c_str(), hostname.length(), allocator); + hostname_value.SetString(hostname.c_str(), gsl::narrow<rapidjson::SizeType>(hostname.length()), allocator); resource.AddMember("host.hostname", hostname_value, allocator); } @@ -57,14 +57,14 @@ class OpenTelemetryLogDataModel { rapidjson::Value& ip = resource["host.ip"]; auto network_interface_infos = utils::NetworkInterfaceInfo::getNetworkInterfaceInfos(); for (const auto& network_interface_info : network_interface_infos) { - rapidjson::Value interface_name(network_interface_info.getName().c_str(), network_interface_info.getName().length(), alloc); + rapidjson::Value interface_name(network_interface_info.getName().c_str(), gsl::narrow<rapidjson::SizeType>(network_interface_info.getName().length()), alloc); rapidjson::Value interface_address_array(rapidjson::kArrayType); for (auto& ip_v4_address : network_interface_info.getIpV4Addresses()) { - rapidjson::Value address_value(ip_v4_address.c_str(), ip_v4_address.length(), alloc); + rapidjson::Value address_value(ip_v4_address.c_str(), gsl::narrow<rapidjson::SizeType>(ip_v4_address.length()), alloc); interface_address_array.PushBack(address_value.Move(), alloc); } for (auto& ip_v6_address : network_interface_info.getIpV6Addresses()) { - rapidjson::Value address_value(ip_v6_address.c_str(), ip_v6_address.length(), alloc); + rapidjson::Value address_value(ip_v6_address.c_str(), gsl::narrow<rapidjson::SizeType>(ip_v6_address.length()), alloc); interface_address_array.PushBack(address_value.Move(), alloc); } ip.AddMember(interface_name, interface_address_array, alloc); diff --git a/libminifi/include/utils/OsUtils.h b/libminifi/include/utils/OsUtils.h index 0f7305279..837806749 100644 --- a/libminifi/include/utils/OsUtils.h +++ b/libminifi/include/utils/OsUtils.h @@ -51,10 +51,6 @@ std::string getMachineArchitecture(); #ifdef WIN32 /// Resolves common identifiers extern std::string resolve_common_identifiers(const std::string &id); - -std::wstring stringToWideString(const std::string& string); - -std::string wideStringToString(const std::wstring& wide_string); #endif std::optional<std::string> getHostName(); diff --git a/libminifi/include/utils/TestUtils.h b/libminifi/include/utils/TestUtils.h index 367bdf2da..35431164e 100644 --- a/libminifi/include/utils/TestUtils.h +++ b/libminifi/include/utils/TestUtils.h @@ -19,6 +19,7 @@ #pragma once #include <chrono> +#include <filesystem> #include <fstream> #include <memory> #include <string> @@ -51,6 +52,10 @@ std::string getFileContent(const std::filesystem::path& file_name) { return file_content; } +void makeFileOrDirectoryNotWritable(const std::filesystem::path& file_name); + +void makeFileOrDirectoryWritable(const std::filesystem::path& file_name); + Identifier generateUUID() { // TODO(hunyadi): Will make the Id generator manage lifetime using a unique_ptr and return a raw ptr on access static std::shared_ptr<utils::IdGenerator> id_generator = utils::IdGenerator::getIdGenerator(); diff --git a/extensions/windows-event-log/wel/UnicodeConversion.h b/libminifi/include/utils/UnicodeConversion.h similarity index 68% rename from extensions/windows-event-log/wel/UnicodeConversion.h rename to libminifi/include/utils/UnicodeConversion.h index b382774fc..dfd0e26ef 100644 --- a/extensions/windows-event-log/wel/UnicodeConversion.h +++ b/libminifi/include/utils/UnicodeConversion.h @@ -22,25 +22,18 @@ #include <atlbase.h> #include <atlconv.h> - #include <string> -namespace org { -namespace apache { -namespace nifi { -namespace minifi { -namespace wel { -inline std::string to_string(const wchar_t* pChar) { - ATL::CW2A aString(pChar, CP_UTF8); - return std::string(aString); +namespace org::apache::nifi::minifi::utils { + +inline std::string to_string(const std::wstring& utf16_string) { + ATL::CW2A utf8_string(utf16_string.c_str(), CP_UTF8); + return {LPSTR{utf8_string}}; } -inline std::wstring to_wstring(const char* pChar) { - ATL::CA2W wString(pChar, CP_UTF8); - return std::wstring(wString); +inline std::wstring to_wstring(const std::string& utf8_string) { + ATL::CA2W utf16_string(utf8_string.c_str(), CP_UTF8); + return {LPWSTR{utf16_string}}; } -} /* namespace wel */ -} /* namespace minifi */ -} /* namespace nifi */ -} /* namespace apache */ -} /* namespace org */ + +} // namespace org::apache::nifi::minifi::utils diff --git a/libminifi/src/core/logging/LoggerConfiguration.cpp b/libminifi/src/core/logging/LoggerConfiguration.cpp index 87d74ff58..1dac379b5 100644 --- a/libminifi/src/core/logging/LoggerConfiguration.cpp +++ b/libminifi/src/core/logging/LoggerConfiguration.cpp @@ -391,7 +391,7 @@ std::shared_ptr<spdlog::sinks::rotating_file_sink_mt> LoggerConfiguration::getRo } } - int max_file_size = 5_MiB; + size_t max_file_size = 5_MiB; std::string max_file_size_str; if (properties->getString(appender_key + ".max_file_size", max_file_size_str)) { core::DataSizeValue::StringToInt(max_file_size_str, max_file_size); diff --git a/libminifi/src/core/logging/alert/AlertSink.cpp b/libminifi/src/core/logging/alert/AlertSink.cpp index 130ec15da..eb97dcaec 100644 --- a/libminifi/src/core/logging/alert/AlertSink.cpp +++ b/libminifi/src/core/logging/alert/AlertSink.cpp @@ -203,10 +203,10 @@ void AlertSink::send(Services& services) { rapidjson::Document doc(rapidjson::kObjectType); std::string agent_id = services.agent_id->getAgentIdentifier(); - doc.AddMember("agentId", rapidjson::Value(agent_id.data(), agent_id.length()), doc.GetAllocator()); + doc.AddMember("agentId", rapidjson::Value(agent_id.data(), gsl::narrow<rapidjson::SizeType>(agent_id.length())), doc.GetAllocator()); doc.AddMember("alerts", rapidjson::Value(rapidjson::kArrayType), doc.GetAllocator()); for (const auto& [log, _] : logs.data_) { - doc["alerts"].PushBack(rapidjson::Value(log.data(), log.size()), doc.GetAllocator()); + doc["alerts"].PushBack(rapidjson::Value(log.data(), gsl::narrow<rapidjson::SizeType>(log.size())), doc.GetAllocator()); } rapidjson::StringBuffer buffer; rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); diff --git a/libminifi/src/io/InputStream.cpp b/libminifi/src/io/InputStream.cpp index 03aacc389..accb58009 100644 --- a/libminifi/src/io/InputStream.cpp +++ b/libminifi/src/io/InputStream.cpp @@ -70,7 +70,7 @@ size_t InputStream::read(std::string &str, bool widen) { str.clear(); str.reserve(string_length); - auto bytes_to_read = string_length; + size_t bytes_to_read{string_length}; auto zero_return_retry_count = 0; while (bytes_to_read > 0) { std::vector<std::byte> buffer(bytes_to_read); diff --git a/libminifi/src/utils/BaseHTTPClient.cpp b/libminifi/src/utils/BaseHTTPClient.cpp index ab2f9eb8c..f53470e35 100644 --- a/libminifi/src/utils/BaseHTTPClient.cpp +++ b/libminifi/src/utils/BaseHTTPClient.cpp @@ -41,7 +41,7 @@ std::optional<std::string> parseProtocol(const std::string& url_input) { std::optional<int> parsePortNumber(const std::string& port_string) { try { - size_t pos; + size_t pos = 0; int port = std::stoi(port_string, &pos); if (pos == port_string.size()) { return port; @@ -94,7 +94,7 @@ URL::URL(const std::string& url_input) { std::string::const_iterator current_pos = url_input.begin(); std::advance(current_pos, protocol_.size()); - constexpr const char HOST_TERMINATORS[] = ":/?#"; + static constexpr std::string_view HOST_TERMINATORS = ":/?#"; std::string::const_iterator end_of_host = std::find_first_of(current_pos, url_input.end(), std::begin(HOST_TERMINATORS), std::end(HOST_TERMINATORS)); host_ = std::string{current_pos, end_of_host}; if (host_.empty()) { @@ -104,7 +104,7 @@ URL::URL(const std::string& url_input) { current_pos = end_of_host; if (current_pos != url_input.end() && *current_pos == ':') { - constexpr const char PORT_TERMINATORS[] = "/?#"; + static constexpr std::string_view PORT_TERMINATORS = "/?#"; ++current_pos; std::string::const_iterator end_of_port = std::find_first_of(current_pos, url_input.end(), std::begin(PORT_TERMINATORS), std::end(PORT_TERMINATORS)); const auto port_number = parsePortNumber(std::string{current_pos, end_of_port}); @@ -204,7 +204,7 @@ int HTTPRequestResponse::seek_callback(void *p, int64_t offset, int) { return SEEKFUNC_FAIL; } auto *callback = reinterpret_cast<HTTPUploadCallback *>(p); - return callback->setPosition(offset); + return gsl::narrow<int>(callback->setPosition(offset)); } catch (...) { return SEEKFUNC_FAIL; } diff --git a/libminifi/src/utils/Cron.cpp b/libminifi/src/utils/Cron.cpp index 677423a00..5fa8d9ecd 100644 --- a/libminifi/src/utils/Cron.cpp +++ b/libminifi/src/utils/Cron.cpp @@ -109,7 +109,7 @@ days parse<days>(const std::string& days_str) { template <> day parse<day>(const std::string& day_str) { - if (auto day_int = fromChars<uint64_t>(day_str); day_int && day_int >= 1 && day_int <= 31) + if (auto day_int = fromChars<unsigned int>(day_str); day_int && day_int >= 1 && day_int <= 31) return day(*day_int); throw BadCronExpression("Invalid day " + day_str); } @@ -142,7 +142,7 @@ weekday parse<weekday>(const std::string& weekday_str) { if (!stream.fail() && parsed_weekday.ok() && stream.peek() == EOF) return parsed_weekday; } else { - unsigned weekday_num; + unsigned weekday_num = 0; stream >> weekday_num; if (!stream.fail() && weekday_num < 7 && stream.peek() == EOF) return weekday(weekday_num-1); @@ -152,7 +152,7 @@ weekday parse<weekday>(const std::string& weekday_str) { template <> year parse<year>(const std::string& year_str) { - if (auto year_int = fromChars<uint64_t>(year_str); year_int && *year_int >= 1970 && *year_int <= 2999) + if (auto year_int = fromChars<int>(year_str); year_int && *year_int >= 1970 && *year_int <= 2999) return year(*year_int); throw BadCronExpression("Invalid year: " + year_str); } @@ -394,7 +394,7 @@ std::unique_ptr<CronField> parseCronField(const std::string& field_str) { if (operands.size() != 2) throw BadCronExpression("Invalid field " + field_str); - if (auto second_operand = fromChars<uint64_t>(operands[1])) + if (auto second_operand = fromChars<uint8_t>(operands[1])) return std::make_unique<NthWeekdayField>(parse<weekday>(operands[0]), *second_operand); } diff --git a/libminifi/src/utils/FileMutex.cpp b/libminifi/src/utils/FileMutex.cpp index 8d357243d..758f1d248 100644 --- a/libminifi/src/utils/FileMutex.cpp +++ b/libminifi/src/utils/FileMutex.cpp @@ -43,10 +43,10 @@ void FileMutex::lock() { if (handle == INVALID_HANDLE_VALUE) { std::cerr << "Failed to open file to read pid: " << utils::getLastError().message() << std::endl; } else { - std::array<char, 16> buffer; + std::array<char, 16> buffer = {}; size_t pid_str_size = 0; DWORD read_size; - while (ReadFile(handle, buffer.data() + pid_str_size, buffer.size() - pid_str_size, &read_size, NULL) && read_size != 0) { + while (ReadFile(handle, buffer.data() + pid_str_size, gsl::narrow<DWORD>(buffer.size() - pid_str_size), &read_size, NULL) && read_size != 0) { pid_str_size += read_size; } pid_str = "'" + std::string(buffer.data(), pid_str_size) + "'"; @@ -62,7 +62,7 @@ void FileMutex::lock() { std::span<const char> buffer = pidstr; while (!buffer.empty()) { DWORD written; - if (!WriteFile(handle, buffer.data(), buffer.size(), &written, NULL)) { + if (!WriteFile(handle, buffer.data(), gsl::narrow<DWORD>(buffer.size()), &written, NULL)) { const auto err = utils::getLastError(); if (!CloseHandle(file_handle_.value())) { std::cerr << "Failed to close file: " << utils::getLastError().message() << std::endl; diff --git a/libminifi/src/utils/NetworkInterfaceInfo.cpp b/libminifi/src/utils/NetworkInterfaceInfo.cpp index 60e96db66..9db31bfc6 100644 --- a/libminifi/src/utils/NetworkInterfaceInfo.cpp +++ b/libminifi/src/utils/NetworkInterfaceInfo.cpp @@ -21,6 +21,7 @@ #include <iphlpapi.h> #pragma comment(lib, "IPHLPAPI.lib") #include "utils/OsUtils.h" +#include "utils/UnicodeConversion.h" #else #include <unistd.h> #include <netinet/in.h> @@ -37,7 +38,7 @@ std::shared_ptr<core::logging::Logger> NetworkInterfaceInfo::logger_ = core::log #ifdef WIN32 NetworkInterfaceInfo::NetworkInterfaceInfo(const IP_ADAPTER_ADDRESSES* adapter) - : name_(OsUtils::wideStringToString(adapter->FriendlyName)), + : name_(to_string(adapter->FriendlyName)), running_(adapter->OperStatus == IfOperStatusUp), loopback_(adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) { for (auto unicast_address = adapter->FirstUnicastAddress; unicast_address != nullptr; unicast_address = unicast_address->Next) { diff --git a/libminifi/src/utils/OsUtils.cpp b/libminifi/src/utils/OsUtils.cpp index 3abe4f2a7..f1ac8b67c 100644 --- a/libminifi/src/utils/OsUtils.cpp +++ b/libminifi/src/utils/OsUtils.cpp @@ -338,36 +338,6 @@ std::optional<std::string> OsUtils::getHostName() { return {hostname.data()}; } -#ifdef WIN32 -std::wstring OsUtils::stringToWideString(const std::string& string) { - if (string.empty()) - return {}; - - const auto size_needed = MultiByteToWideChar(CP_UTF8, 0, &string.at(0), gsl::narrow<int>(string.size()), nullptr, 0); - if (size_needed <= 0) { - throw std::runtime_error(fmt::format("MultiByteToWideChar() returned: {}, due to {}", std::to_string(size_needed), utils::OsUtils::windowsErrorToErrorCode(GetLastError()).message())); - } - - std::wstring result(size_needed, L'\0'); - MultiByteToWideChar(CP_UTF8, 0, &string.at(0), gsl::narrow<int>(string.size()), &result.at(0), size_needed); - return result; -} - -std::string OsUtils::wideStringToString(const std::wstring& wide_string) { - if (wide_string.empty()) - return {}; - - const auto size_needed = WideCharToMultiByte(CP_UTF8, 0, &wide_string.at(0), gsl::narrow<int>(wide_string.size()), nullptr, 0, nullptr, nullptr); - if (size_needed <= 0) { - throw std::runtime_error(fmt::format("WideCharToMultiByte() returned: {}, due to {}", std::to_string(size_needed), utils::OsUtils::windowsErrorToErrorCode(GetLastError()).message())); - } - - std::string result(size_needed, 0); - WideCharToMultiByte(CP_UTF8, 0, &wide_string.at(0), gsl::narrow<int>(wide_string.size()), &result.at(0), size_needed, nullptr, nullptr); - return result; -} -#endif - std::optional<double> OsUtils::getSystemLoadAverage() { #ifndef WIN32 std::array<double, 1> load_avg{}; diff --git a/libminifi/src/utils/ProcessCpuUsageTracker.cpp b/libminifi/src/utils/ProcessCpuUsageTracker.cpp index f738f17b3..7a2e360fc 100644 --- a/libminifi/src/utils/ProcessCpuUsageTracker.cpp +++ b/libminifi/src/utils/ProcessCpuUsageTracker.cpp @@ -115,7 +115,6 @@ void ProcessCpuUsageTracker::queryCpuTimes() { previous_cpu_times_ = cpu_times_; previous_sys_cpu_times_ = sys_cpu_times_; previous_user_cpu_times_ = user_cpu_times_; - SYSTEM_INFO sysInfo; FILETIME ftime, fsys, fuser; GetSystemTimeAsFileTime(&ftime); diff --git a/libminifi/src/utils/TestUtils.cpp b/libminifi/src/utils/TestUtils.cpp index 6d3021be7..ebf63d1d9 100644 --- a/libminifi/src/utils/TestUtils.cpp +++ b/libminifi/src/utils/TestUtils.cpp @@ -17,7 +17,52 @@ #include "utils/TestUtils.h" +#include <type_traits> + +#ifdef WIN32 +#include <windows.h> +#include <aclapi.h> +#endif + +#include "utils/gsl.h" + +#ifdef WIN32 +namespace { + +void setAclOnFileOrDirectory(std::string file_name, DWORD perms, ACCESS_MODE perm_options) { + PSECURITY_DESCRIPTOR security_descriptor = nullptr; + const auto security_descriptor_deleter = gsl::finally([&security_descriptor] { if (security_descriptor) { LocalFree((HLOCAL) security_descriptor); } }); + + PACL old_acl = nullptr; // GetNamedSecurityInfo will set this to a non-owning pointer to a field inside security_descriptor: no need to free it + if (GetNamedSecurityInfo(file_name.c_str(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &old_acl, NULL, &security_descriptor) != ERROR_SUCCESS) { + throw std::runtime_error("Could not get security info for file: " + file_name); + } + + char trustee_name[] = "Everyone"; + EXPLICIT_ACCESS explicit_access = { + .grfAccessPermissions = perms, + .grfAccessMode = perm_options, + .grfInheritance = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, + .Trustee = { .TrusteeForm = TRUSTEE_IS_NAME, .ptstrName = trustee_name } + }; + + PACL new_acl = nullptr; + const auto new_acl_deleter = gsl::finally([&new_acl] { if (new_acl) { LocalFree((HLOCAL) new_acl); } }); + + if (SetEntriesInAcl(1, &explicit_access, old_acl, &new_acl) != ERROR_SUCCESS) { + throw std::runtime_error("Could not create new ACL for file: " + file_name); + } + + if (SetNamedSecurityInfo(file_name.data(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, new_acl, NULL) != ERROR_SUCCESS) { + throw std::runtime_error("Could not set the new ACL for file: " + file_name); + } +} + +} // namespace +#endif + namespace org::apache::nifi::minifi::utils { + #ifdef WIN32 // If minifi is not installed through the MSI installer, then TZDATA might be missing // date::set_install can point to the TZDATA location, but it has to be called from each library/executable that wants to use timezones @@ -25,4 +70,21 @@ void dateSetInstall(const std::string& install) { date::set_install(install); } #endif + +void makeFileOrDirectoryNotWritable(const std::filesystem::path& file_name) { +#ifdef WIN32 + setAclOnFileOrDirectory(file_name.string(), FILE_GENERIC_WRITE, DENY_ACCESS); +#else + std::filesystem::permissions(file_name, std::filesystem::perms::owner_write, std::filesystem::perm_options::remove); +#endif +} + +void makeFileOrDirectoryWritable(const std::filesystem::path& file_name) { +#ifdef WIN32 + setAclOnFileOrDirectory(file_name.string(), FILE_GENERIC_WRITE, GRANT_ACCESS); +#else + std::filesystem::permissions(file_name, std::filesystem::perms::owner_write, std::filesystem::perm_options::add); +#endif +} + } // namespace org::apache::nifi::minifi::utils diff --git a/libminifi/src/utils/crypto/ciphers/Aes256Ecb.cpp b/libminifi/src/utils/crypto/ciphers/Aes256Ecb.cpp index ccc8571b4..482719342 100644 --- a/libminifi/src/utils/crypto/ciphers/Aes256Ecb.cpp +++ b/libminifi/src/utils/crypto/ciphers/Aes256Ecb.cpp @@ -67,9 +67,9 @@ void Aes256EcbCipher::encrypt(std::span<unsigned char, BLOCK_SIZE> data) const { } int ciphertext_len = 0; - int len; + int len = 0; - if (1 != EVP_EncryptUpdate(ctx.get(), data.data(), &len, data.data(), data.size())) { + if (1 != EVP_EncryptUpdate(ctx.get(), data.data(), &len, data.data(), gsl::narrow<int>(data.size()))) { handleOpenSSLError("Could not update cipher content"); } ciphertext_len += len; @@ -99,9 +99,9 @@ void Aes256EcbCipher::decrypt(std::span<unsigned char, BLOCK_SIZE> data) const { } int plaintext_len = 0; - int len; + int len = 0; - if (1 != EVP_DecryptUpdate(ctx.get(), data.data(), &len, data.data(), data.size())) { + if (1 != EVP_DecryptUpdate(ctx.get(), data.data(), &len, data.data(), gsl::narrow<int>(data.size()))) { handleOpenSSLError("Could not update cipher content"); } plaintext_len += len; diff --git a/libminifi/test/unit/FileSystemRepositoryTests.cpp b/libminifi/test/unit/FileSystemRepositoryTests.cpp index 6613e977d..94b0a5c21 100644 --- a/libminifi/test/unit/FileSystemRepositoryTests.cpp +++ b/libminifi/test/unit/FileSystemRepositoryTests.cpp @@ -20,14 +20,11 @@ // as we measure the absolute memory usage that would fail this test #define EXTENSION_LIST "" // NOLINT(cppcoreguidelines-macro-usage) -#ifdef WIN32 -#include <Windows.h> -#endif -#include <cstring> #include <list> #include "utils/gsl.h" #include "utils/OsUtils.h" +#include "utils/TestUtils.h" #include "../TestBase.h" #include "../Catch.h" #include "utils/Literals.h" @@ -114,18 +111,10 @@ TEST_CASE("FileSystemRepository can retry removing entry that previously failed REQUIRE(files.size() == 1); // ensure that the content is not deleted during resource claim destruction filename = (files[0].first / files[0].second).string(); -#ifdef WIN32 - REQUIRE(SetFileAttributes(filename.c_str(), FILE_ATTRIBUTE_READONLY)); -#else - minifi::utils::file::set_permissions(dir, 0555); -#endif + utils::makeFileOrDirectoryNotWritable(dir); } -#ifdef WIN32 - REQUIRE(SetFileAttributes(filename.c_str(), GetFileAttributes(filename.c_str()) & ~FILE_ATTRIBUTE_READONLY)); -#else - minifi::utils::file::set_permissions(dir, 0777); -#endif + utils::makeFileOrDirectoryWritable(dir); REQUIRE(minifi::utils::file::list_dir_all(dir, testController.getLogger()).size() == 1); { minifi::ResourceClaim claim(content_repo); @@ -153,18 +142,10 @@ TEST_CASE("FileSystemRepository removes non-existing resource file from purge li REQUIRE(files.size() == 1); // ensure that the content is not deleted during resource claim destruction filename = (files[0].first / files[0].second).string(); -#ifdef WIN32 - REQUIRE(SetFileAttributes(filename.c_str(), FILE_ATTRIBUTE_READONLY)); -#else - minifi::utils::file::set_permissions(dir, 0555); -#endif + utils::makeFileOrDirectoryNotWritable(dir); } -#ifdef WIN32 - REQUIRE(SetFileAttributes(filename.c_str(), GetFileAttributes(filename.c_str()) & ~FILE_ATTRIBUTE_READONLY)); -#else - minifi::utils::file::set_permissions(dir, 0777); -#endif + utils::makeFileOrDirectoryWritable(dir); REQUIRE(std::filesystem::remove(filename)); REQUIRE(minifi::utils::file::list_dir_all(dir, testController.getLogger()).empty()); { diff --git a/libminifi/test/unit/OsUtilTests.cpp b/libminifi/test/unit/OsUtilTests.cpp index 15c4628cc..a7777d177 100644 --- a/libminifi/test/unit/OsUtilTests.cpp +++ b/libminifi/test/unit/OsUtilTests.cpp @@ -39,26 +39,6 @@ TEST_CASE("Test userIdToUsername for well-known SIDs", "[OsUtils]") { CHECK_FALSE(minifi::utils::OsUtils::userIdToUsername("S-1-3-4").empty()); CHECK_FALSE(minifi::utils::OsUtils::userIdToUsername("S-1-5-80-0").empty()); } - -TEST_CASE("OsUtils::stringToWideString tests") { - using org::apache::nifi::minifi::utils::OsUtils::stringToWideString; - - CHECK(stringToWideString("árvíztűrő tükörfúrógép") == L"árvíztűrő tükörfúrógép"); - CHECK(stringToWideString("Falsches Üben von Xylophonmusik quält jeden größeren Zwerg.") == L"Falsches Üben von Xylophonmusik quält jeden größeren Zwerg."); - CHECK(stringToWideString("가나다라마바사아자차카타파하") == L"가나다라마바사아자차카타파하"); - CHECK(stringToWideString("العربية تجربة") == L"العربية تجربة"); - CHECK(stringToWideString("פטכןצימסעואבגדהוזחטייכלמנסעפצקרשת") == L"פטכןצימסעואבגדהוזחטייכלמנסעפצקרשת"); -} - -TEST_CASE("OsUtils::wideStringToString tests") { - using org::apache::nifi::minifi::utils::OsUtils::wideStringToString; - - CHECK(wideStringToString(L"árvíztűrő tükörfúrógép") == "árvíztűrő tükörfúrógép"); - CHECK(wideStringToString(L"Falsches Üben von Xylophonmusik quält jeden größeren Zwerg.") == "Falsches Üben von Xylophonmusik quält jeden größeren Zwerg."); - CHECK(wideStringToString(L"가나다라마바사아자차카타파하") == "가나다라마바사아자차카타파하"); - CHECK(wideStringToString(L"العربية تجربة") == "العربية تجربة"); - CHECK(wideStringToString(L"פטכןצימסעואבגדהוזחטייכלמנסעפצקרשת") == "פטכןצימסעואבגדהוזחטייכלמנסעפצקרשת"); -} #endif TEST_CASE("Machine architecture is supported") { diff --git a/libminifi/test/unit/StringUtilsTests.cpp b/libminifi/test/unit/StringUtilsTests.cpp index 11b44d7cd..a7a3b9b7f 100644 --- a/libminifi/test/unit/StringUtilsTests.cpp +++ b/libminifi/test/unit/StringUtilsTests.cpp @@ -28,6 +28,10 @@ #include "utils/StringUtils.h" #include "utils/Environment.h" +#ifdef WIN32 +#include "utils/UnicodeConversion.h" +#endif + namespace org::apache::nifi::minifi::utils { // NOLINTBEGIN(readability-container-size-empty) @@ -449,18 +453,20 @@ TEST_CASE("test string::testBase64EncodeDecode", "[test base64 encode decode]") TEST_CASE("test string::testJoinPack", "[test join_pack]") { std::string stdstr = "std::string"; + std::string_view strview = "std::string_view"; const char* cstr = "c string"; - const char carr[] = "char array"; - REQUIRE(string::join_pack("rvalue c string, ", cstr, std::string{", rval std::string, "}, stdstr, ", ", carr) - == "rvalue c string, c string, rval std::string, std::string, char array"); + const char carr[] = "char array"; // NOLINT(cppcoreguidelines-avoid-c-arrays): testing const char[] on purpose + REQUIRE(string::join_pack("rvalue c string, ", cstr, std::string{", rval std::string, "}, stdstr, ", ", strview, ", ", carr) + == "rvalue c string, c string, rval std::string, std::string, std::string_view, char array"); } TEST_CASE("test string::testJoinPackWstring", "[test join_pack wstring]") { std::wstring stdstr = L"std::string"; + std::wstring_view strview = L"std::string_view"; const wchar_t* cstr = L"c string"; - const wchar_t carr[] = L"char array"; - REQUIRE(string::join_pack(L"rvalue c string, ", cstr, std::wstring{L", rval std::string, "}, stdstr, L", ", carr) - == L"rvalue c string, c string, rval std::string, std::string, char array"); + const wchar_t carr[] = L"char array"; // NOLINT(cppcoreguidelines-avoid-c-arrays): testing const wchar_t[] on purpose + REQUIRE(string::join_pack(L"rvalue c string, ", cstr, std::wstring{L", rval std::string, "}, stdstr, L", ", strview, L", ", carr) + == L"rvalue c string, c string, rval std::string, std::string, std::string_view, char array"); } /* doesn't and shouldn't compile @@ -525,7 +531,7 @@ TEST_CASE("string::removeFramingCharacters works correctly", "[removeFramingChar // ignore terminating \0 character template<size_t N> -std::span<const std::byte> from_cstring(const char (& str)[N]) { +std::span<const std::byte> from_cstring(const char (& str)[N]) { // NOLINT(cppcoreguidelines-avoid-c-arrays) return as_bytes(std::span<const char>(str, N - 1)); } @@ -554,7 +560,7 @@ TEST_CASE("string::toLower and toUpper tests") { } TEST_CASE("string::splitToValueAndUnit tests") { - int64_t value; + int64_t value = 0; std::string unit_str; SECTION("Simple case") { CHECK(string::splitToValueAndUnit("1 horse", value, unit_str)); @@ -598,6 +604,28 @@ TEST_CASE("string::parseCharacter tests") { CHECK(string::parseCharacter("") == std::nullopt); } +#ifdef WIN32 +TEST_CASE("Conversion from UTF-8 strings to UTF-16 strings works") { + using org::apache::nifi::minifi::utils::to_wstring; + + CHECK(to_wstring("árvíztűrő tükörfúrógép") == L"árvíztűrő tükörfúrógép"); + CHECK(to_wstring("Falsches Üben von Xylophonmusik quält jeden größeren Zwerg.") == L"Falsches Üben von Xylophonmusik quält jeden größeren Zwerg."); + CHECK(to_wstring("가나다라마바사아자차카타파하") == L"가나다라마바사아자차카타파하"); + CHECK(to_wstring("العربية تجربة") == L"العربية تجربة"); + CHECK(to_wstring("פטכןצימסעואבגדהוזחטייכלמנסעפצקרשת") == L"פטכןצימסעואבגדהוזחטייכלמנסעפצקרשת"); +} + +TEST_CASE("Conversion from UTF-16 strings to UTF-8 strings works") { + using org::apache::nifi::minifi::utils::to_string; + + CHECK(to_string(L"árvíztűrő tükörfúrógép") == "árvíztűrő tükörfúrógép"); + CHECK(to_string(L"Falsches Üben von Xylophonmusik quält jeden größeren Zwerg.") == "Falsches Üben von Xylophonmusik quält jeden größeren Zwerg."); + CHECK(to_string(L"가나다라마바사아자차카타파하") == "가나다라마바사아자차카타파하"); + CHECK(to_string(L"العربية تجربة") == "العربية تجربة"); + CHECK(to_string(L"פטכןצימסעואבגדהוזחטייכלמנסעפצקרשת") == "פטכןצימסעואבגדהוזחטייכלמנסעפצקרשת"); +} +#endif + } // namespace org::apache::nifi::minifi::utils // NOLINTEND(readability-container-size-empty)
