From eddc6bb67cf1f1337ebbe7aa764b711534292c6c Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Wed, 7 Aug 2024 10:38:34 -0500 Subject: [PATCH] updated build system --- cmake/libraries/spdlog.cmake | 10 +- .../comm/curl/requests/http_request_base.hpp | 10 +- repertory/librepertory/include/common.hpp | 5 +- .../include/file_manager/file_manager.hpp | 4 +- .../librepertory/include/types/repertory.hpp | 2 - .../librepertory/include/utils/file_utils.hpp | 1 - .../src/comm/curl/requests/http_put_file.cpp | 15 +- .../file_manager/file_manager_open_file.cpp | 47 +- .../file_manager_ring_buffer_open_file.cpp | 27 +- .../librepertory/src/utils/file_utils.cpp | 9 +- repertory/librepertory/src/utils/utils.cpp | 1 - .../include/fixtures/winfsp_fixture.hpp | 36 +- .../include/mocks/mock_fuse_drive.hpp | 6 +- .../include/mocks/mock_open_file.hpp | 6 +- .../include/mocks/mock_provider.hpp | 6 +- .../include/mocks/mock_upload_manager.hpp | 6 +- .../include/mocks/mock_winfsp_drive.hpp | 6 +- .../repertory_test/include/test_common.hpp | 40 +- .../include/utils/event_capture.hpp | 6 +- repertory/repertory_test/src/config_test.cpp | 10 +- .../repertory_test/src/database_test.cpp | 10 +- .../src/encrypting_reader_test.cpp | 236 +----- .../src/file_manager_open_file_test.cpp | 46 +- ...ile_manager_ring_buffer_open_file_test.cpp | 120 ++- .../repertory_test/src/file_manager_test.cpp | 34 +- .../src/file_manager_upload_test.cpp | 9 +- .../repertory_test/src/fuse_drive_test.cpp | 12 +- .../repertory_test/src/providers_test.cpp | 23 +- .../repertory_test/src/remote_fuse_test.cpp | 4 +- .../repertory_test/src/remote_winfsp_test.cpp | 11 +- repertory/repertory_test/src/test_common.cpp | 73 -- support/include/utils/all.hpp | 8 +- support/include/utils/config.hpp | 12 + .../include/utils/encrypting_reader.hpp | 286 ++++--- support/include/utils/encryption.hpp | 182 ++-- support/include/utils/file.hpp | 86 +- support/include/utils/hash.hpp | 237 ++---- support/src/utils/common.cpp | 1 - .../src/utils/encrypting_reader.cpp | 802 +++++++++--------- support/src/utils/file.cpp | 236 +----- support/src/utils/file_file.cpp | 353 ++++++++ support/src/utils/hash.cpp | 117 ++- .../encryption.cpp => test/include/test.hpp} | 56 +- support/test/src/test.cpp | 120 +++ support/test/src/utils/common_test.cpp | 9 +- .../test/src/utils/encrypting_reader_test.cpp | 224 +++++ support/test/src/utils/encryption_test.cpp | 69 +- support/test/src/utils/file_test.cpp | 65 ++ support/test/src/utils/hash_test.cpp | 186 ++++ support/test/src/utils/path_test.cpp | 6 +- support/test/src/utils/string_test.cpp | 4 +- 51 files changed, 2142 insertions(+), 1748 deletions(-) delete mode 100644 repertory/repertory_test/src/test_common.cpp rename {repertory/librepertory => support}/include/utils/encrypting_reader.hpp (90%) rename {repertory/librepertory => support}/src/utils/encrypting_reader.cpp (83%) create mode 100644 support/src/utils/file_file.cpp rename support/{src/utils/encryption.cpp => test/include/test.hpp} (53%) create mode 100644 support/test/src/test.cpp create mode 100644 support/test/src/utils/encrypting_reader_test.cpp create mode 100644 support/test/src/utils/file_test.cpp create mode 100644 support/test/src/utils/hash_test.cpp diff --git a/cmake/libraries/spdlog.cmake b/cmake/libraries/spdlog.cmake index 430b0964..b9450d03 100644 --- a/cmake/libraries/spdlog.cmake +++ b/cmake/libraries/spdlog.cmake @@ -6,7 +6,15 @@ if(PROJECT_ENABLE_SPDLOG) include_directories(BEFORE SYSTEM ${SPDLOG_INCLUDE_DIRS}) - link_libraries(spdlog::spdlog) + if(PROJECT_IS_MINGW_UNIX) + if(PROJECT_STATIC_LINK) + link_libraries(/mingw64/lib/libspdlog.a) + else() + link_libraries(/mingw64/lib/libspdlog.dll.a) + endif() + else() + link_libraries(spdlog::spdlog) + endif() elseif(NOT PROJECT_IS_MINGW OR CMAKE_HOST_WIN32) ExternalProject_Add(spdlog_project PREFIX external diff --git a/repertory/librepertory/include/comm/curl/requests/http_request_base.hpp b/repertory/librepertory/include/comm/curl/requests/http_request_base.hpp index f2e44adb..44a983c3 100644 --- a/repertory/librepertory/include/comm/curl/requests/http_request_base.hpp +++ b/repertory/librepertory/include/comm/curl/requests/http_request_base.hpp @@ -23,7 +23,7 @@ #define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_REQUEST_BASE_HPP_ #include "types/repertory.hpp" -#include "utils/native_file.hpp" +#include "utils/file.hpp" namespace repertory::curl::requests { using read_callback = size_t (*)(char *, size_t, size_t, void *); @@ -33,7 +33,7 @@ using response_callback = struct read_file_info final { stop_type &stop_requested; - native_file::native_file_ptr nf{}; + utils::file::file file{}; std::uint64_t offset{}; }; @@ -41,9 +41,9 @@ inline const auto read_file_data = static_cast( [](char *buffer, size_t size, size_t nitems, void *instream) -> size_t { auto *read_info = reinterpret_cast(instream); std::size_t bytes_read{}; - auto ret = read_info->nf->read_bytes( - reinterpret_cast(buffer), size * nitems, - read_info->offset, bytes_read); + auto ret = + read_info->file.read(reinterpret_cast(buffer), + size * nitems, read_info->offset, &bytes_read); if (ret) { read_info->offset += bytes_read; } diff --git a/repertory/librepertory/include/common.hpp b/repertory/librepertory/include/common.hpp index 0d45f556..876bde6e 100644 --- a/repertory/librepertory/include/common.hpp +++ b/repertory/librepertory/include/common.hpp @@ -61,14 +61,11 @@ inline constexpr const std::uint64_t REPERTORY_CONFIG_VERSION = 0ULL; inline constexpr const std::string_view REPERTORY_DATA_NAME = "repertory2"; inline constexpr const std::string_view REPERTORY_MIN_REMOTE_VERSION = "2.0.0"; -#if defined(_WIN32) #define REPERTORY_INVALID_HANDLE INVALID_HANDLE_VALUE +#if defined(_WIN32) #define REPERTORY_API_INVALID_HANDLE static_cast(-1) -using native_handle = HANDLE; #else -#define REPERTORY_INVALID_HANDLE (-1) #define REPERTORY_API_INVALID_HANDLE REPERTORY_INVALID_HANDLE -using native_handle = int; #endif inline constexpr const auto NANOS_PER_SECOND = 1000000000L; diff --git a/repertory/librepertory/include/file_manager/file_manager.hpp b/repertory/librepertory/include/file_manager/file_manager.hpp index 2a4e8647..ee5e5779 100644 --- a/repertory/librepertory/include/file_manager/file_manager.hpp +++ b/repertory/librepertory/include/file_manager/file_manager.hpp @@ -30,7 +30,7 @@ #include "file_manager/i_upload_manager.hpp" #include "platform/platform.hpp" #include "types/repertory.hpp" -#include "utils/native_file.hpp" +#include "utils/file.hpp" namespace repertory { class app_config; @@ -131,7 +131,7 @@ public: std::atomic last_access_{ std::chrono::system_clock::now()}; bool modified_{false}; - native_file_ptr nf_; + utils::file::file nf_; mutable std::mutex io_thread_mtx_; std::condition_variable io_thread_notify_; std::deque> io_thread_queue_; diff --git a/repertory/librepertory/include/types/repertory.hpp b/repertory/librepertory/include/types/repertory.hpp index 80822f06..f07d91d4 100644 --- a/repertory/librepertory/include/types/repertory.hpp +++ b/repertory/librepertory/include/types/repertory.hpp @@ -51,8 +51,6 @@ const std::vector META_USED_NAMES = { using api_meta_map = std::map; -using stop_type = std::atomic; - enum class api_error { success = 0, access_denied, diff --git a/repertory/librepertory/include/utils/file_utils.hpp b/repertory/librepertory/include/utils/file_utils.hpp index aa80fefa..83e9b52d 100644 --- a/repertory/librepertory/include/utils/file_utils.hpp +++ b/repertory/librepertory/include/utils/file_utils.hpp @@ -24,7 +24,6 @@ #include "types/repertory.hpp" #include "utils/file.hpp" -#include "utils/native_file.hpp" namespace repertory::utils::file { // Prototypes diff --git a/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp b/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp index 94010077..3c2a5b3c 100644 --- a/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp +++ b/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp @@ -24,8 +24,8 @@ #include "utils/string.hpp" namespace repertory::curl::requests { -auto http_put_file::set_method(CURL *curl, stop_type &stop_requested) const - -> bool { +auto http_put_file::set_method(CURL *curl, + stop_type &stop_requested) const -> bool { curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); @@ -46,19 +46,14 @@ auto http_put_file::set_method(CURL *curl, stop_type &stop_requested) const read_info = std::make_shared(read_file_info{ stop_requested, + utils::file::file::open_or_create_file(source_path), }); - if (native_file::create_or_open(source_path, read_info->nf) != - api_error::success) { + if (not read_info->file) { return false; } - read_info->nf->set_auto_close(true); - - std::uint64_t file_size{}; - if (not read_info->nf->get_file_size(file_size)) { - return false; - } + auto file_size = read_info->file.size(); curl_easy_setopt(curl, CURLOPT_READDATA, read_info.get()); curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_file_data); diff --git a/repertory/librepertory/src/file_manager/file_manager_open_file.cpp b/repertory/librepertory/src/file_manager/file_manager_open_file.cpp index 973c6248..ac01b292 100644 --- a/repertory/librepertory/src/file_manager/file_manager_open_file.cpp +++ b/repertory/librepertory/src/file_manager/file_manager_open_file.cpp @@ -66,8 +66,9 @@ file_manager::open_file::open_file( } if (not fsi.directory) { - set_api_error(native_file::create_or_open(fsi.source_path, - provider_.is_direct_only(), nf_)); + nf_ = utils::file::file::open_or_create_file(fsi.source_path, + provider_.is_direct_only()); + set_api_error(nf_ ? api_error::success : api_error::os_error); if (get_api_error() == api_error::success) { if (read_state.has_value()) { read_state_ = read_state.value(); @@ -77,20 +78,16 @@ file_manager::open_file::open_file( fsi_.size, chunk_size)), false); - std::uint64_t file_size{}; - if (nf_->get_file_size(file_size)) { - if (provider_.is_direct_only() || file_size == fsi.size) { - read_state_.set(0U, read_state_.size(), true); - } else if (not nf_->truncate(fsi.size)) { - set_api_error(api_error::os_error); - } - } else { + auto file_size = nf_.size(); + if (provider_.is_direct_only() || file_size == fsi.size) { + read_state_.set(0U, read_state_.size(), true); + } else if (not nf_.truncate(fsi.size)) { set_api_error(api_error::os_error); } } if (get_api_error() != api_error::success && nf_) { - nf_->close(); + nf_.close(); } } } @@ -185,8 +182,7 @@ void file_manager::open_file::download_chunk(std::size_t chunk, res = do_io([&]() -> api_error { std::size_t bytes_written{}; - if (not nf_->write_bytes(data.data(), data.size(), data_offset, - bytes_written)) { + if (not nf_.write(data, data_offset, &bytes_written)) { return api_error::os_error; } @@ -246,7 +242,7 @@ auto file_manager::open_file::native_operation( } file_lock.unlock(); - return do_io([&]() -> api_error { return callback(nf_->get_handle()); }); + return do_io([&]() -> api_error { return callback(nf_.get_handle()); }); } auto file_manager::open_file::native_operation( @@ -287,7 +283,7 @@ auto file_manager::open_file::native_operation( const auto original_file_size = get_file_size(); - auto res = do_io([&]() -> api_error { return callback(nf_->get_handle()); }); + auto res = do_io([&]() -> api_error { return callback(nf_.get_handle()); }); if (res != api_error::success) { utils::error::raise_api_path_error(function_name, get_api_path(), utils::get_last_error_code(), @@ -296,14 +292,7 @@ auto file_manager::open_file::native_operation( } { - std::uint64_t file_size{}; - if (not nf_->get_file_size(file_size)) { - utils::error::raise_api_path_error(function_name, get_api_path(), - utils::get_last_error_code(), - "failed to get file size"); - return set_api_error(api_error::os_error); - } - + auto file_size = nf_.size(); if (file_size != new_file_size) { utils::error::raise_api_path_error( function_name, get_api_path(), api_error::file_size_mismatch, @@ -372,7 +361,7 @@ auto file_manager::open_file::read(std::size_t read_size, data.resize(read_size); std::size_t bytes_read{}; - return nf_->read_bytes(data.data(), read_size, read_offset, bytes_read) + return nf_.read(data.data(), read_size, read_offset, &bytes_read) ? api_error::success : api_error::os_error; }); @@ -423,8 +412,8 @@ auto file_manager::open_file::resize(std::uint64_t new_file_size) -> api_error { return native_operation( new_file_size, [this, &new_file_size](native_handle) -> api_error { - return nf_->truncate(new_file_size) ? api_error::success - : api_error::os_error; + return nf_.truncate(new_file_size) ? api_error::success + : api_error::os_error; }); } @@ -460,8 +449,7 @@ auto file_manager::open_file::close() -> bool { } } - nf_->close(); - nf_.reset(); + nf_.close(); if (modified_ && (get_api_error() == api_error::success)) { mgr_.queue_upload(*this); @@ -587,8 +575,7 @@ auto file_manager::open_file::write(std::uint64_t write_offset, } auto res = do_io([&]() -> api_error { - if (not nf_->write_bytes(data.data(), data.size(), write_offset, - bytes_written)) { + if (not nf_.write(data.data(), data.size(), write_offset, &bytes_written)) { return api_error::os_error; } diff --git a/repertory/librepertory/src/file_manager/file_manager_ring_buffer_open_file.cpp b/repertory/librepertory/src/file_manager/file_manager_ring_buffer_open_file.cpp index f488f4dd..17949cf9 100644 --- a/repertory/librepertory/src/file_manager/file_manager_ring_buffer_open_file.cpp +++ b/repertory/librepertory/src/file_manager/file_manager_ring_buffer_open_file.cpp @@ -72,14 +72,14 @@ file_manager::ring_buffer_open_file::ring_buffer_open_file( fsi_.source_path = utils::path::combine(buffer_directory, {utils::create_uuid_string()}); - auto res = native_file::create_or_open(fsi_.source_path, nf_); - if (res != api_error::success) { + nf_ = utils::file::file::open_or_create_file(fsi_.source_path); + if (not nf_) { throw std::runtime_error("failed to create buffer file|err|" + std::to_string(utils::get_last_error_code())); } - if (not nf_->truncate(ring_state_.size() * chunk_size)) { - nf_->close(); + if (not nf_.truncate(ring_state_.size() * chunk_size)) { + nf_.close(); throw std::runtime_error("failed to resize buffer file|err|" + std::to_string(utils::get_last_error_code())); } @@ -92,7 +92,7 @@ file_manager::ring_buffer_open_file::~ring_buffer_open_file() { close(); - nf_->close(); + nf_.close(); if (not utils::file::retry_delete_file(fsi_.source_path)) { utils::error::raise_api_path_error( function_name, fsi_.api_path, fsi_.source_path, @@ -128,9 +128,8 @@ auto file_manager::file_manager::ring_buffer_open_file::download_chunk( if (res == api_error::success) { res = do_io([&]() -> api_error { std::size_t bytes_written{}; - if (not nf_->write_bytes(buffer.data(), buffer.size(), - (chunk % ring_state_.size()) * chunk_size_, - bytes_written)) { + if (not nf_.write(buffer, (chunk % ring_state_.size()) * chunk_size_, + &bytes_written)) { return api_error::os_error; } @@ -201,7 +200,7 @@ auto file_manager::ring_buffer_open_file::is_download_complete() const -> bool { auto file_manager::ring_buffer_open_file::native_operation( i_open_file::native_operation_callback callback) -> api_error { - return do_io([&]() -> api_error { return callback(nf_->get_handle()); }); + return do_io([&]() -> api_error { return callback(nf_.get_handle()); }); } void file_manager::ring_buffer_open_file::reverse(std::size_t count) { @@ -270,11 +269,11 @@ auto file_manager::ring_buffer_open_file::read(std::size_t read_size, res = do_io([this, &buffer, &chunk, &data, read_offset, &to_read]() -> api_error { std::size_t bytes_read{}; - auto ret = nf_->read_bytes(buffer.data(), buffer.size(), - ((chunk % ring_state_.size()) * chunk_size_), - bytes_read) - ? api_error::success - : api_error::os_error; + auto ret = + nf_.read(buffer, ((chunk % ring_state_.size()) * chunk_size_), + &bytes_read) + ? api_error::success + : api_error::os_error; if (ret == api_error::success) { data.insert(data.end(), buffer.begin() + static_cast(read_offset), diff --git a/repertory/librepertory/src/utils/file_utils.cpp b/repertory/librepertory/src/utils/file_utils.cpp index 5ef9e1d6..61be5449 100644 --- a/repertory/librepertory/src/utils/file_utils.cpp +++ b/repertory/librepertory/src/utils/file_utils.cpp @@ -277,8 +277,8 @@ auto generate_sha256(const std::string &file_path) -> std::string { std::to_string(res)); } - native_file_ptr nf; - if (native_file::open(file_path, nf) != api_error::success) { + auto nf = util::file::file::open_file(file_path); + if (not nf) { throw std::runtime_error("failed to open file|" + file_path); } @@ -286,8 +286,7 @@ auto generate_sha256(const std::string &file_path) -> std::string { data_buffer buffer(1048576u); std::uint64_t read_offset = 0U; std::size_t bytes_read = 0U; - while ( - nf->read_bytes(buffer.data(), buffer.size(), read_offset, bytes_read)) { + while (nf.read(buffer, read_offset, &bytes_read)) { if (not bytes_read) { break; } @@ -297,12 +296,10 @@ auto generate_sha256(const std::string &file_path) -> std::string { &state, reinterpret_cast(buffer.data()), bytes_read); if (res != 0) { - nf->close(); throw std::runtime_error("failed to update sha256|" + std::to_string(res)); } } - nf->close(); } std::array out{}; diff --git a/repertory/librepertory/src/utils/utils.cpp b/repertory/librepertory/src/utils/utils.cpp index 4c5e9cb0..1aa9cd9e 100644 --- a/repertory/librepertory/src/utils/utils.cpp +++ b/repertory/librepertory/src/utils/utils.cpp @@ -28,7 +28,6 @@ #include "types/startup_exception.hpp" #include "utils/com_init_wrapper.hpp" #include "utils/common.hpp" -#include "utils/native_file.hpp" #include "utils/path.hpp" #include "utils/string.hpp" #include "utils/time.hpp" diff --git a/repertory/repertory_test/include/fixtures/winfsp_fixture.hpp b/repertory/repertory_test/include/fixtures/winfsp_fixture.hpp index 3984453a..cc4899ae 100644 --- a/repertory/repertory_test/include/fixtures/winfsp_fixture.hpp +++ b/repertory/repertory_test/include/fixtures/winfsp_fixture.hpp @@ -19,8 +19,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef REPERTORY_WINFSP_FIXTURE_HPP -#define REPERTORY_WINFSP_FIXTURE_HPP +#ifndef REPERTORY_TEST_INCLUDE_FIXTURES_WINFSP_FIXTURE_HPP +#define REPERTORY_TEST_INCLUDE_FIXTURES_WINFSP_FIXTURE_HPP #if defined(_WIN32) #include "test_common.hpp" @@ -48,13 +48,14 @@ protected: if (PROVIDER_INDEX != 0) { if (PROVIDER_INDEX == 1) { EXPECT_TRUE(utils::file::delete_directory_recursively( - "./test_config/winfsp_test" + std::to_string(PROVIDER_INDEX))); + utils::path::combine(test::get_test_output_dir(), {"winfsp_test" + std::to_string(PROVIDER_INDEX)})); - app_config src_cfg(provider_type::s3, - utils::path::combine(get_test_dir(), {"storj"})); + app_config src_cfg( + provider_type::s3, + utils::path::combine(test::get_test_input_dir(), {"storj"})); config = std::make_unique( provider_type::s3, - "./test_config/winfsp_test" + std::to_string(PROVIDER_INDEX)); + utils::path::combine(test::get_test_output_dir(), {"winfsp_test" + std::to_string(PROVIDER_INDEX)})); EXPECT_FALSE(config ->set_value_by_name("S3Config.AccessKey", src_cfg.get_s3_config().access_key) @@ -89,14 +90,19 @@ protected: } if (PROVIDER_INDEX == 2) { - EXPECT_TRUE(utils::file::delete_directory_recursively( - "./test_config/winfsp_test" + std::to_string(PROVIDER_INDEX))); + EXPECT_TRUE( + utils::file::delete_directory_recursively(utils::path::combine( + test::get_test_output_dir(), + {"winfsp_test" + std::to_string(PROVIDER_INDEX)}))); - app_config src_cfg(provider_type::sia, - utils::path::combine(get_test_dir(), {"sia"})); + app_config src_cfg( + provider_type::sia, + utils::path::combine(test::get_test_input_dir(), {"sia"})); config = std::make_unique( provider_type::sia, - "./test_config/winfsp_test" + std::to_string(PROVIDER_INDEX)); + utils::path::combine( + test::get_test_output_dir(), + {"winfsp_test" + std::to_string(PROVIDER_INDEX)})); [[maybe_unused]] auto val = config->set_value_by_name( "HostConfig.AgentString", src_cfg.get_host_config().agent_string); EXPECT_FALSE( @@ -135,12 +141,14 @@ protected: config.reset(); event_system::instance().stop(); - EXPECT_TRUE(utils::file::delete_directory_recursively( - "./test_config/winfsp_test" + std::to_string(PROVIDER_INDEX))); + EXPECT_TRUE( + utils::file::delete_directory_recursively(utils::path::combine( + test::get_test_output_dir(), + {"winfsp_test" + std::to_string(PROVIDER_INDEX)}))); } } }; } // namespace repertory #endif -#endif // REPERTORY_WINFSP_FIXTURE_HPP +#endif // REPERTORY_TEST_INCLUDE_FIXTURES_WINFSP_FIXTURE_HPP diff --git a/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp b/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp index efbcca76..089db907 100644 --- a/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp +++ b/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp @@ -19,8 +19,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef TESTS_MOCKS_MOCK_FUSE_DRIVE_HPP_ -#define TESTS_MOCKS_MOCK_FUSE_DRIVE_HPP_ +#ifndef REPERTORY_TEST_INCLUDE_FIXTURES_MOCKS_MOCK_FUSE_DRIVE_HPP_ +#define REPERTORY_TEST_INCLUDE_FIXTURES_MOCKS_MOCK_FUSE_DRIVE_HPP_ #if !defined(_WIN32) #include "test_common.hpp" @@ -156,4 +156,4 @@ public: } // namespace repertory #endif // _WIN32 -#endif // TESTS_MOCKS_MOCK_FUSE_DRIVE_HPP_ +#endif // REPERTORY_TEST_INCLUDE_FIXTURES_MOCKS_MOCK_FUSE_DRIVE_HPP_ diff --git a/repertory/repertory_test/include/mocks/mock_open_file.hpp b/repertory/repertory_test/include/mocks/mock_open_file.hpp index 1de5bf44..e56786a4 100644 --- a/repertory/repertory_test/include/mocks/mock_open_file.hpp +++ b/repertory/repertory_test/include/mocks/mock_open_file.hpp @@ -19,8 +19,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef TESTS_MOCKS_MOCK_OPEN_FILE_HPP_ -#define TESTS_MOCKS_MOCK_OPEN_FILE_HPP_ +#ifndef REPERTORY_TEST_INCLUDE_MOCKS_MOCK_OPEN_FILE_HPP_ +#define REPERTORY_TEST_INCLUDE_MOCKS_MOCK_OPEN_FILE_HPP_ #include "test_common.hpp" @@ -95,4 +95,4 @@ public: }; } // namespace repertory -#endif // TESTS_MOCKS_MOCK_OPEN_FILE_HPP_ +#endif // REPERTORY_TEST_INCLUDE_MOCKS_MOCK_OPEN_FILE_HPP_ diff --git a/repertory/repertory_test/include/mocks/mock_provider.hpp b/repertory/repertory_test/include/mocks/mock_provider.hpp index 5c0c33a0..d8bcb978 100644 --- a/repertory/repertory_test/include/mocks/mock_provider.hpp +++ b/repertory/repertory_test/include/mocks/mock_provider.hpp @@ -19,8 +19,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef TESTS_MOCKS_MOCK_PROVIDER_HPP_ -#define TESTS_MOCKS_MOCK_PROVIDER_HPP_ +#ifndef REPERTORY_TEST_INCLUDE_MOCKS_MOCK_PROVIDER_HPP_ +#define REPERTORY_TEST_INCLUDE_MOCKS_MOCK_PROVIDER_HPP_ #include "test_common.hpp" @@ -159,4 +159,4 @@ public: }; } // namespace repertory -#endif // TESTS_MOCKS_MOCK_PROVIDER_HPP_ +#endif // REPERTORY_TEST_INCLUDE_MOCKS_MOCK_PROVIDER_HPP_ diff --git a/repertory/repertory_test/include/mocks/mock_upload_manager.hpp b/repertory/repertory_test/include/mocks/mock_upload_manager.hpp index f842a29d..5c02a58b 100644 --- a/repertory/repertory_test/include/mocks/mock_upload_manager.hpp +++ b/repertory/repertory_test/include/mocks/mock_upload_manager.hpp @@ -19,8 +19,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef TESTS_MOCKS_MOCK_UPLOAD_MANAGER_HPP_ -#define TESTS_MOCKS_MOCK_UPLOAD_MANAGER_HPP_ +#ifndef REPERTORY_TEST_INCLUDE_MOCKS_MOCK_UPLOAD_MANAGER_HPP_ +#define REPERTORY_TEST_INCLUDE_MOCKS_MOCK_UPLOAD_MANAGER_HPP_ #include "test_common.hpp" @@ -41,4 +41,4 @@ public: }; } // namespace repertory -#endif // TESTS_MOCKS_MOCK_UPLOAD_MANAGER_HPP_ +#endif // REPERTORY_TEST_INCLUDE_MOCKS_MOCK_UPLOAD_MANAGER_HPP_ diff --git a/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp b/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp index 50063dd7..cfb635a8 100644 --- a/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp +++ b/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp @@ -19,8 +19,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef TESTS_MOCKS_MOCK_WINFSP_DRIVE_HPP_ -#define TESTS_MOCKS_MOCK_WINFSP_DRIVE_HPP_ +#ifndef REPERTORY_TEST_INCLUDE_MOCKS_MOCK_WINFSP_DRIVE_HPP_ +#define REPERTORY_TEST_INCLUDE_MOCKS_MOCK_WINFSP_DRIVE_HPP_ #if defined(_WIN32) #include "test_common.hpp" @@ -167,4 +167,4 @@ public: } // namespace repertory #endif // _WIN32 -#endif // TESTS_MOCKS_MOCK_WINFSP_DRIVE_HPP_ +#endif // REPERTORY_TEST_INCLUDE_MOCKS_MOCK_WINFSP_DRIVE_HPP_ diff --git a/repertory/repertory_test/include/test_common.hpp b/repertory/repertory_test/include/test_common.hpp index 9bce4959..d6b5d584 100644 --- a/repertory/repertory_test/include/test_common.hpp +++ b/repertory/repertory_test/include/test_common.hpp @@ -19,47 +19,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef TESTS_TEST_COMMON_HPP_ -#define TESTS_TEST_COMMON_HPP_ - -#if defined(U) -#undef U -#endif +#ifndef REPERTORY_TEST_INCLUDE_TEST_COMMON_HPP_ +#define REPERTORY_TEST_INCLUDE_TEST_COMMON_HPP_ REPERTORY_IGNORE_WARNINGS_ENABLE() -#include -#include +#include "test.hpp" REPERTORY_IGNORE_WARNINGS_DISABLE() #include "events/consumers/console_consumer.hpp" #include "events/event_system.hpp" #include "events/events.hpp" -#include "utils/encrypt.hpp" -#include "utils/file_utils.hpp" -#include "utils/native_file.hpp" -#define COMMA , - -using ::testing::_; -using namespace ::testing; - -namespace repertory { -[[nodiscard]] auto create_random_file(std::string path, - std::size_t size) -> native_file_ptr; - -void delete_generated_files(); - -[[nodiscard]] auto generate_test_file_name( - const std::string &directory, - const std::string &file_name_no_extension) -> std::string; - -template -static void decrypt_and_verify(const T &buffer, const std::string &token, - T2 &result) { - EXPECT_TRUE(utils::encryption::decrypt_data(token, buffer, result)); -} - -[[nodiscard]] auto get_test_dir() -> std::string; -} // namespace repertory - -#endif // TESTS_TEST_COMMON_HPP_ +#endif // REPERTORY_TEST_INCLUDE_TEST_COMMON_HPP_ diff --git a/repertory/repertory_test/include/utils/event_capture.hpp b/repertory/repertory_test/include/utils/event_capture.hpp index 2a25eb46..42d4d55b 100644 --- a/repertory/repertory_test/include/utils/event_capture.hpp +++ b/repertory/repertory_test/include/utils/event_capture.hpp @@ -19,8 +19,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef TESTS_UTILS_EVENT_CAPTURE_HPP_ -#define TESTS_UTILS_EVENT_CAPTURE_HPP_ +#ifndef REPERTORY_TEST_INCLUDE_UTILS_EVENT_CAPTURE_HPP_ +#define REPERTORY_TEST_INCLUDE_UTILS_EVENT_CAPTURE_HPP_ #include "test_common.hpp" @@ -106,4 +106,4 @@ public: }; } // namespace repertory -#endif // TESTS_UTILS_EVENT_CAPTURE_HPP_ +#endif // REPERTORY_TEST_INCLUDE_UTILS_EVENT_CAPTURE_HPP_ diff --git a/repertory/repertory_test/src/config_test.cpp b/repertory/repertory_test/src/config_test.cpp index f9a38a5a..3e166eb4 100644 --- a/repertory/repertory_test/src/config_test.cpp +++ b/repertory/repertory_test/src/config_test.cpp @@ -33,20 +33,20 @@ public: static console_consumer cs; std::string s3_directory{ - utils::path::combine("./test_config", {"config_test", "s3"})}; + utils::path::combine(test::get_test_output_dir(), {"config_test", "s3"})}; - std::string sia_directory{ - utils::path::combine("./test_config", {"config_test", "sia"})}; + std::string sia_directory{utils::path::combine(test::get_test_output_dir(), + {"config_test", "sia"})}; void SetUp() override { event_system::instance().start(); ASSERT_TRUE(utils::file::delete_directory_recursively( - utils::path::combine("./test_config", {"config_test"}))); + utils::path::combine(test::get_test_output_dir(), {"config_test"}))); } void TearDown() override { ASSERT_TRUE(utils::file::delete_directory_recursively( - utils::path::combine("./test_config", {"config_test"}))); + utils::path::combine(test::get_test_output_dir(), {"config_test"}))); event_system::instance().stop(); } }; diff --git a/repertory/repertory_test/src/database_test.cpp b/repertory/repertory_test/src/database_test.cpp index f00c8dc3..447f1725 100644 --- a/repertory/repertory_test/src/database_test.cpp +++ b/repertory/repertory_test/src/database_test.cpp @@ -35,8 +35,9 @@ TEST(database, db_insert) { { sqlite3 *db3_ptr{nullptr}; auto res = sqlite3_open_v2( - utils::path::combine(get_test_dir(), {"test.db3"}).c_str(), &db3_ptr, - SQLITE_OPEN_READWRITE, nullptr); + utils::path::combine(test::get_test_input_dir(), {"test.db3"}) + .c_str(), + &db3_ptr, SQLITE_OPEN_READWRITE, nullptr); ASSERT_EQ(SQLITE_OK, res); ASSERT_TRUE(db3_ptr != nullptr); @@ -78,8 +79,9 @@ TEST(database, db_select) { { sqlite3 *db3_ptr{nullptr}; auto res = sqlite3_open_v2( - utils::path::combine(get_test_dir(), {"test.db3"}).c_str(), &db3_ptr, - SQLITE_OPEN_READWRITE, nullptr); + utils::path::combine(test::get_test_input_dir(), {"test.db3"}) + .c_str(), + &db3_ptr, SQLITE_OPEN_READWRITE, nullptr); ASSERT_EQ(SQLITE_OK, res); ASSERT_TRUE(db3_ptr != nullptr); diff --git a/repertory/repertory_test/src/encrypting_reader_test.cpp b/repertory/repertory_test/src/encrypting_reader_test.cpp index 31f4c27e..52d491ae 100644 --- a/repertory/repertory_test/src/encrypting_reader_test.cpp +++ b/repertory/repertory_test/src/encrypting_reader_test.cpp @@ -27,11 +27,7 @@ #include "utils/path.hpp" namespace repertory { -static auto get_source_file_name() -> std::string { - return generate_test_file_name("./test_data", "encrypting_reader"); -} - -TEST(encrypting_reader, get_encrypted_file_name) { +/* TEST(encrypting_reader, get_encrypted_file_name) { const auto source_file_name = get_source_file_name(); ASSERT_TRUE(utils::file::retry_delete_file(source_file_name)); @@ -41,7 +37,7 @@ TEST(encrypting_reader, get_encrypted_file_name) { if (source_file) { stop_type stop_requested = false; utils::encryption::encrypting_reader reader( - "test.dat", source_file_name, stop_requested, token, std::nullopt); + "test.dat", source_file_name, stop_requested, token, std::nullopt); auto file_name = reader.get_encrypted_file_name(); @@ -53,231 +49,5 @@ TEST(encrypting_reader, get_encrypted_file_name) { } EXPECT_TRUE(utils::file::retry_delete_file(source_file_name)); -} - -TEST(encrypting_reader, file_data) { - const auto source_file_name = get_source_file_name(); - EXPECT_TRUE(utils::file::retry_delete_file(source_file_name)); - - const auto token = std::string("moose"); - auto source_file = create_random_file( - source_file_name, - 8U * utils::encryption::encrypting_reader::get_data_chunk_size()); - EXPECT_TRUE(source_file != nullptr); - if (source_file) { - stop_type stop_requested = false; - utils::encryption::encrypting_reader reader("test.dat", source_file_name, - stop_requested, token); - - for (std::uint8_t i = 0U; i < 8U; i++) { - data_buffer buffer( - utils::encryption::encrypting_reader::get_encrypted_chunk_size()); - for (std::uint8_t j = 0U; j < 2U; j++) { - EXPECT_EQ( - buffer.size() / 2U, - utils::encryption::encrypting_reader::reader_function( - reinterpret_cast(&buffer[(buffer.size() / 2U) * j]), - buffer.size() / 2U, 1U, &reader)); - } - - data_buffer decrypted_data; - EXPECT_TRUE( - utils::encryption::decrypt_data(token, buffer, decrypted_data)); - - EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(), - decrypted_data.size()); - - std::size_t bytes_read{}; - data_buffer file_data(decrypted_data.size()); - EXPECT_TRUE(source_file->read_bytes( - file_data.data(), file_data.size(), - utils::encryption::encrypting_reader::get_data_chunk_size() * i, - bytes_read)); - EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(), - file_data.size())); - } - - source_file->close(); - } - EXPECT_TRUE(utils::file::retry_delete_file(source_file_name)); -} - -TEST(encrypting_reader, file_data_in_multiple_chunks) { - const auto source_file_name = get_source_file_name(); - ASSERT_TRUE(utils::file::retry_delete_file(source_file_name)); - - const auto token = std::string("moose"); - auto source_file = create_random_file( - source_file_name, - 8U * utils::encryption::encrypting_reader::get_data_chunk_size()); - EXPECT_TRUE(source_file != nullptr); - if (source_file) { - stop_type stop_requested = false; - utils::encryption::encrypting_reader reader("test.dat", source_file_name, - stop_requested, token); - - for (std::uint8_t i = 0U; i < 8U; i += 2U) { - data_buffer buffer( - utils::encryption::encrypting_reader::get_encrypted_chunk_size() * - 2U); - EXPECT_EQ(buffer.size(), - utils::encryption::encrypting_reader::reader_function( - reinterpret_cast(buffer.data()), buffer.size(), 1U, - &reader)); - - for (std::uint8_t j = 0U; j < 2U; j++) { - data_buffer decrypted_data; - const auto offset = (j * (buffer.size() / 2U)); - EXPECT_TRUE(utils::encryption::decrypt_data( - token, - data_buffer( - std::next(buffer.begin(), static_cast(offset)), - std::next(buffer.begin(), static_cast( - offset + (buffer.size() / 2U)))), - decrypted_data)); - - EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(), - decrypted_data.size()); - - std::size_t bytes_read{}; - data_buffer file_data(decrypted_data.size()); - EXPECT_TRUE(source_file->read_bytes( - file_data.data(), file_data.size(), - (utils::encryption::encrypting_reader::get_data_chunk_size() * i) + - (j * - utils::encryption::encrypting_reader::get_data_chunk_size()), - bytes_read)); - EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(), - file_data.size())); - } - } - - source_file->close(); - } - - EXPECT_TRUE(utils::file::retry_delete_file(source_file_name)); -} - -TEST(encrypting_reader, file_data_as_stream) { - const auto source_file_name = get_source_file_name(); - ASSERT_TRUE(utils::file::retry_delete_file(source_file_name)); - - const auto token = std::string("moose"); - auto source_file = create_random_file( - source_file_name, - 8U * utils::encryption::encrypting_reader::get_data_chunk_size()); - EXPECT_TRUE(source_file != nullptr); - if (source_file) { - stop_type stop_requested = false; - utils::encryption::encrypting_reader reader("test.dat", source_file_name, - stop_requested, token); - auto io_stream = reader.create_iostream(); - EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail()); - EXPECT_TRUE(io_stream->good()); - EXPECT_EQ(reader.get_total_size(), - static_cast(io_stream->tellg())); - EXPECT_FALSE(io_stream->seekg(0, std::ios_base::beg).fail()); - EXPECT_TRUE(io_stream->good()); - - for (std::uint8_t i = 0U; i < 8U; i++) { - data_buffer buffer( - utils::encryption::encrypting_reader::get_encrypted_chunk_size()); - EXPECT_FALSE( - io_stream->seekg(static_cast(i * buffer.size())) - .fail()); - EXPECT_TRUE(io_stream->good()); - for (std::uint8_t j = 0U; j < 2U; j++) { - EXPECT_FALSE( - io_stream - ->read( - reinterpret_cast(&buffer[(buffer.size() / 2U) * j]), - static_cast(buffer.size()) / 2U) - .fail()); - EXPECT_TRUE(io_stream->good()); - } - - data_buffer decrypted_data; - EXPECT_TRUE( - utils::encryption::decrypt_data(token, buffer, decrypted_data)); - - EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(), - decrypted_data.size()); - - std::size_t bytes_read{}; - data_buffer file_data(decrypted_data.size()); - EXPECT_TRUE(source_file->read_bytes( - file_data.data(), file_data.size(), - utils::encryption::encrypting_reader::get_data_chunk_size() * i, - bytes_read)); - EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(), - file_data.size())); - } - - source_file->close(); - } - EXPECT_TRUE(utils::file::retry_delete_file(source_file_name)); -} - -TEST(encrypting_reader, file_data_in_multiple_chunks_as_stream) { - const auto source_file_name = get_source_file_name(); - ASSERT_TRUE(utils::file::retry_delete_file(source_file_name)); - - const auto token = std::string("moose"); - auto source_file = create_random_file( - source_file_name, - 8u * utils::encryption::encrypting_reader::get_data_chunk_size()); - EXPECT_TRUE(source_file != nullptr); - if (source_file) { - stop_type stop_requested = false; - utils::encryption::encrypting_reader reader("test.dat", source_file_name, - stop_requested, token); - auto io_stream = reader.create_iostream(); - EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail()); - EXPECT_TRUE(io_stream->good()); - EXPECT_EQ(reader.get_total_size(), - static_cast(io_stream->tellg())); - EXPECT_FALSE(io_stream->seekg(0, std::ios_base::beg).fail()); - EXPECT_TRUE(io_stream->good()); - - for (std::uint8_t i = 0U; i < 8U; i += 2U) { - data_buffer buffer( - utils::encryption::encrypting_reader::get_encrypted_chunk_size() * - 2U); - EXPECT_FALSE(io_stream - ->read(reinterpret_cast(buffer.data()), - static_cast(buffer.size())) - .fail()); - EXPECT_TRUE(io_stream->good()); - - for (std::uint8_t j = 0U; j < 2U; j++) { - data_buffer decrypted_data; - const auto offset = (j * (buffer.size() / 2U)); - EXPECT_TRUE(utils::encryption::decrypt_data( - token, - data_buffer( - std::next(buffer.begin(), static_cast(offset)), - std::next(buffer.begin(), static_cast( - offset + (buffer.size() / 2U)))), - decrypted_data)); - - EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(), - decrypted_data.size()); - - std::size_t bytes_read{}; - data_buffer file_data(decrypted_data.size()); - EXPECT_TRUE(source_file->read_bytes( - file_data.data(), file_data.size(), - (utils::encryption::encrypting_reader::get_data_chunk_size() * i) + - (j * - utils::encryption::encrypting_reader::get_data_chunk_size()), - bytes_read)); - EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(), - file_data.size())); - } - } - - source_file->close(); - } - EXPECT_TRUE(utils::file::retry_delete_file(source_file_name)); -} +} */ } // namespace repertory diff --git a/repertory/repertory_test/src/file_manager_open_file_test.cpp b/repertory/repertory_test/src/file_manager_open_file_test.cpp index 94e9d9f3..f4338ce6 100644 --- a/repertory/repertory_test/src/file_manager_open_file_test.cpp +++ b/repertory/repertory_test/src/file_manager_open_file_test.cpp @@ -55,7 +55,7 @@ static void validate_write(file_manager::open_file &o, std::size_t offset, TEST(open_file, properly_initializes_state_for_0_byte_file) { const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); + test::generate_test_file_name("file_manager_open_file_test"); mock_provider mp; mock_upload_manager um; @@ -76,7 +76,7 @@ TEST(open_file, properly_initializes_state_for_0_byte_file) { TEST(open_file, properly_initializes_state_based_on_chunk_size) { const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); + test::generate_test_file_name("file_manager_open_file_test"); mock_provider mp; mock_upload_manager um; @@ -109,7 +109,7 @@ TEST(open_file, properly_initializes_state_based_on_chunk_size) { TEST(open_file, will_not_change_source_path_for_0_byte_file) { const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); + test::generate_test_file_name("file_manager_open_file_test"); mock_provider mp; mock_upload_manager um; @@ -133,7 +133,7 @@ TEST(open_file, will_not_change_source_path_for_0_byte_file) { TEST(open_file, will_change_source_path_if_file_size_is_greater_than_0) { const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); + test::generate_test_file_name("file_manager_open_file_test"); mock_provider mp; mock_upload_manager um; @@ -171,9 +171,9 @@ TEST(open_file, will_change_source_path_if_file_size_is_greater_than_0) { TEST(open_file, will_not_change_source_path_if_file_size_matches_existing_source) { - const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); - create_random_file(source_path, test_chunk_size)->close(); + auto rf = test::create_random_file(test_chunk_size); + const auto source_path = rf.get_path().string(); + rf.close(); mock_provider mp; mock_upload_manager um; @@ -196,11 +196,8 @@ TEST(open_file, } TEST(open_file, write_with_incomplete_download) { - const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); - auto nf = create_random_file( - generate_test_file_name("./test_config", "file_manager_open_file_test"), - test_chunk_size * 2u); + auto nf = test::create_random_file(test_chunk_size * 2u); + const auto source_path = nf.get_path().string(); mock_provider mp; mock_upload_manager um; @@ -236,9 +233,8 @@ TEST(open_file, write_with_incomplete_download) { if (offset == 0u) { std::size_t bytes_read{}; data.resize(size); - auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read) - ? api_error::success - : api_error::os_error; + auto ret = nf.read(data, offset, &bytes_read) ? api_error::success + : api_error::os_error; EXPECT_EQ(bytes_read, data.size()); return ret; } @@ -289,7 +285,7 @@ TEST(open_file, write_with_incomplete_download) { TEST(open_file, write_new_file) { const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); + test::generate_test_file_name("file_manager_open_file_test"); mock_provider mp; mock_upload_manager um; @@ -362,7 +358,7 @@ TEST(open_file, write_new_file) { TEST(open_file, write_new_file_multiple_chunks) { const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); + test::generate_test_file_name("file_manager_open_file_test"); mock_provider mp; mock_upload_manager um; @@ -453,9 +449,9 @@ TEST(open_file, write_new_file_multiple_chunks) { } TEST(open_file, resize_file_to_0_bytes) { - const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); - create_random_file(source_path, test_chunk_size * 4u)->close(); + auto rf = test::create_random_file(test_chunk_size * 4u); + const auto source_path = rf.get_path().string(); + rf.close(); mock_provider mp; mock_upload_manager um; @@ -503,9 +499,9 @@ TEST(open_file, resize_file_to_0_bytes) { } TEST(open_file, resize_file_by_full_chunk) { - const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); - create_random_file(source_path, test_chunk_size * 4u)->close(); + auto rf = test::create_random_file(test_chunk_size * 4u); + const auto source_path = rf.get_path().string(); + rf.close(); mock_provider mp; mock_upload_manager um; @@ -556,7 +552,7 @@ TEST(open_file, can_add_handle) { event_system::instance().start(); console_consumer c; const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); + test::generate_test_file_name("file_manager_open_file_test"); mock_provider mp; mock_upload_manager um; @@ -618,7 +614,7 @@ TEST(open_file, can_remove_handle) { console_consumer c; const auto source_path = - generate_test_file_name("./test_config", "file_manager_open_file_test"); + test::generate_test_file_name("file_manager_open_file_test"); mock_provider mp; mock_upload_manager um; diff --git a/repertory/repertory_test/src/file_manager_ring_buffer_open_file_test.cpp b/repertory/repertory_test/src/file_manager_ring_buffer_open_file_test.cpp index 509cf37b..c9112e23 100644 --- a/repertory/repertory_test/src/file_manager_ring_buffer_open_file_test.cpp +++ b/repertory/repertory_test/src/file_manager_ring_buffer_open_file_test.cpp @@ -31,11 +31,11 @@ namespace repertory { static constexpr const std::size_t test_chunk_size = 1024u; static std::string ring_buffer_dir = utils::path::combine( - "./test_config", {"file_manager_ring_buffer_open_file_test"}); + test::get_test_output_dir(), {"file_manager_ring_buffer_open_file_test"}); TEST(ring_buffer_open_file, can_forward_to_last_chunk) { const auto source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -67,7 +67,7 @@ TEST(ring_buffer_open_file, can_forward_to_last_chunk) { TEST(ring_buffer_open_file, can_forward_to_last_chunk_if_count_is_greater_than_remaining) { const auto source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -98,7 +98,7 @@ TEST(ring_buffer_open_file, TEST(ring_buffer_open_file, can_forward_after_last_chunk) { const auto source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -130,7 +130,7 @@ TEST(ring_buffer_open_file, can_forward_after_last_chunk) { TEST(ring_buffer_open_file, can_forward_and_rollover_after_last_chunk) { const auto source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -158,7 +158,7 @@ TEST(ring_buffer_open_file, can_forward_and_rollover_after_last_chunk) { TEST(ring_buffer_open_file, can_reverse_to_first_chunk) { const auto source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -190,7 +190,7 @@ TEST(ring_buffer_open_file, can_reverse_to_first_chunk) { TEST(ring_buffer_open_file, can_reverse_to_first_chunk_if_count_is_greater_than_remaining) { const auto source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -221,7 +221,7 @@ TEST(ring_buffer_open_file, TEST(ring_buffer_open_file, can_reverse_before_first_chunk) { const auto source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -253,7 +253,7 @@ TEST(ring_buffer_open_file, can_reverse_before_first_chunk) { TEST(ring_buffer_open_file, can_reverse_and_rollover_before_first_chunk) { const auto source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -289,7 +289,7 @@ TEST(ring_buffer_open_file, can_reverse_and_rollover_before_first_chunk) { TEST(ring_buffer_open_file, can_reverse_full_ring) { const auto source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -320,12 +320,10 @@ TEST(ring_buffer_open_file, can_reverse_full_ring) { } TEST(ring_buffer_open_file, read_full_file) { - const auto download_source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); - auto nf = create_random_file(download_source_path, test_chunk_size * 32u); + auto nf = test::create_random_file(test_chunk_size * 32u); + const auto download_source_path = nf.get_path().string(); - const auto dest_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + const auto dest_path = test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -335,8 +333,7 @@ TEST(ring_buffer_open_file, read_full_file) { fsi.directory = false; fsi.api_path = "/test.txt"; fsi.size = test_chunk_size * 32u; - fsi.source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + fsi.source_path = test::generate_test_file_name("ring_buffer_open_file"); EXPECT_CALL(mp, read_file_bytes) .WillRepeatedly([&nf](const std::string & /* api_path */, @@ -346,9 +343,8 @@ TEST(ring_buffer_open_file, read_full_file) { EXPECT_FALSE(stop_requested); std::size_t bytes_read{}; data.resize(size); - auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read) - ? api_error::success - : api_error::os_error; + auto ret = nf.read(data, offset, &bytes_read) ? api_error::success + : api_error::os_error; EXPECT_EQ(bytes_read, data.size()); return ret; }); @@ -356,8 +352,8 @@ TEST(ring_buffer_open_file, read_full_file) { file_manager::ring_buffer_open_file rb(ring_buffer_dir, test_chunk_size, 30U, fsi, mp, 8u); - native_file_ptr nf2; - EXPECT_EQ(api_error::success, native_file::create_or_open(dest_path, nf2)); + auto nf2 = utils::file::file::open_or_create_file(dest_path); + EXPECT_TRUE(nf2); auto to_read = fsi.size; std::size_t chunk = 0u; @@ -367,13 +363,12 @@ TEST(ring_buffer_open_file, read_full_file) { rb.read(test_chunk_size, chunk * test_chunk_size, data)); std::size_t bytes_written{}; - EXPECT_TRUE(nf2->write_bytes(data.data(), data.size(), - chunk * test_chunk_size, bytes_written)); + EXPECT_TRUE(nf2.write(data, chunk * test_chunk_size, &bytes_written)); chunk++; to_read -= data.size(); } - nf2->close(); - nf->close(); + nf2.close(); + nf.close(); EXPECT_STREQ(utils::file::generate_sha256(download_source_path).c_str(), utils::file::generate_sha256(dest_path).c_str()); @@ -383,12 +378,10 @@ TEST(ring_buffer_open_file, read_full_file) { } TEST(ring_buffer_open_file, read_full_file_in_reverse) { - const auto download_source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); - auto nf = create_random_file(download_source_path, test_chunk_size * 32u); + auto nf = test::create_random_file(test_chunk_size * 32u); + const auto download_source_path = nf.get_path().string(); - const auto dest_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + const auto dest_path = test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -398,8 +391,7 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) { fsi.directory = false; fsi.api_path = "/test.txt"; fsi.size = test_chunk_size * 32u; - fsi.source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + fsi.source_path = test::generate_test_file_name("ring_buffer_open_file"); EXPECT_CALL(mp, read_file_bytes) .WillRepeatedly([&nf](const std::string & /* api_path */, @@ -409,7 +401,7 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) { EXPECT_FALSE(stop_requested); std::size_t bytes_read{}; data.resize(size); - auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read) + auto ret = nf.read_bytes(data, offset, &bytes_read) ? api_error::success : api_error::os_error; EXPECT_EQ(bytes_read, data.size()); @@ -419,8 +411,8 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) { file_manager::ring_buffer_open_file rb(ring_buffer_dir, test_chunk_size, 30U, fsi, mp, 8u); - native_file_ptr nf2; - EXPECT_EQ(api_error::success, native_file::create_or_open(dest_path, nf2)); + auto nf2 = utils::file::file::open_or_create_file(dest_path); + EXPECT_TRUE(nf2); auto to_read = fsi.size; std::size_t chunk = rb.get_total_chunks() - 1u; @@ -430,13 +422,12 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) { rb.read(test_chunk_size, chunk * test_chunk_size, data)); std::size_t bytes_written{}; - EXPECT_TRUE(nf2->write_bytes(data.data(), data.size(), - chunk * test_chunk_size, bytes_written)); + EXPECT_TRUE(nf2.write(data, chunk * test_chunk_size, &bytes_written)); chunk--; to_read -= data.size(); } - nf2->close(); - nf->close(); + nf2.close(); + nf.close(); EXPECT_STREQ(utils::file::generate_sha256(download_source_path).c_str(), utils::file::generate_sha256(dest_path).c_str()); @@ -446,12 +437,11 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) { } TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) { + auto nf = test::create_random_file(test_chunk_size * 32u); const auto download_source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); - auto nf = create_random_file(download_source_path, test_chunk_size * 32u); + test::generate_test_file_name("ring_buffer_open_file"); - const auto dest_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + const auto dest_path = test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -461,8 +451,7 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) { fsi.directory = false; fsi.api_path = "/test.txt"; fsi.size = test_chunk_size * 32u; - fsi.source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + fsi.source_path = test::generate_test_file_name("ring_buffer_open_file"); EXPECT_CALL(mp, read_file_bytes) .WillRepeatedly([&nf](const std::string & /* api_path */, @@ -472,7 +461,7 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) { EXPECT_FALSE(stop_requested); std::size_t bytes_read{}; data.resize(size); - auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read) + auto ret = nf.read_bytes(data, offset, &bytes_read) ? api_error::success : api_error::os_error; EXPECT_EQ(bytes_read, data.size()); @@ -482,8 +471,8 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) { file_manager::ring_buffer_open_file rb(ring_buffer_dir, test_chunk_size, 30U, fsi, mp, 8u); - native_file_ptr nf2; - EXPECT_EQ(api_error::success, native_file::create_or_open(dest_path, nf2)); + auto nf2 = + utils::file::file::open_or_create_file(dest_path) : EXPECT_TRUE(nf2); auto total_read = std::uint64_t(0u); @@ -492,12 +481,11 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) { EXPECT_EQ(api_error::success, rb.read(3u, total_read, data)); std::size_t bytes_written{}; - EXPECT_TRUE(nf2->write_bytes(data.data(), data.size(), total_read, - bytes_written)); + EXPECT_TRUE(nf2.write_bytes(data, total_read, &bytes_written)); total_read += data.size(); } - nf2->close(); - nf->close(); + nf2.close(); + nf.close(); EXPECT_STREQ(utils::file::generate_sha256(download_source_path).c_str(), utils::file::generate_sha256(dest_path).c_str()); @@ -508,11 +496,10 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) { TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) { const auto download_source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + test::generate_test_file_name("ring_buffer_open_file"); auto nf = create_random_file(download_source_path, test_chunk_size * 32u); - const auto dest_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + const auto dest_path = test::generate_test_file_name("ring_buffer_open_file"); mock_provider mp; @@ -522,8 +509,7 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) { fsi.directory = false; fsi.api_path = "/test.txt"; fsi.size = test_chunk_size * 32u; - fsi.source_path = - generate_test_file_name("./test_config", "ring_buffer_open_file"); + fsi.source_path = test::generate_test_file_name("ring_buffer_open_file"); EXPECT_CALL(mp, read_file_bytes) .WillRepeatedly([&nf](const std::string & /* api_path */, @@ -533,9 +519,8 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) { EXPECT_FALSE(stop_requested); std::size_t bytes_read{}; data.resize(size); - auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read) - ? api_error::success - : api_error::os_error; + auto ret = nf.read(data, offset, &bytes_read) ? api_error::success + : api_error::os_error; EXPECT_EQ(bytes_read, data.size()); return ret; }); @@ -543,8 +528,8 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) { file_manager::ring_buffer_open_file rb(ring_buffer_dir, test_chunk_size, 30U, fsi, mp, 8u); - native_file_ptr nf2; - EXPECT_EQ(api_error::success, native_file::create_or_open(dest_path, nf2)); + auto nf2 = utils::file::file::open_or_create_file(dest_path); + EXPERT_TRUE(nf2); auto total_read = std::uint64_t(0u); const auto read_size = 3u; @@ -560,13 +545,12 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) { (remain >= read_size) ? offset : 0u, data)); std::size_t bytes_written{}; - EXPECT_TRUE(nf2->write_bytes(data.data(), data.size(), - (remain >= read_size) ? offset : 0u, - bytes_written)); + EXPECT_TRUE( + nf2.write(data, (remain >= read_size) ? offset : 0u, &bytes_written)); total_read += data.size(); } - nf2->close(); - nf->close(); + nf2.close(); + nf.close(); EXPECT_STREQ(utils::file::generate_sha256(download_source_path).c_str(), utils::file::generate_sha256(dest_path).c_str()); diff --git a/repertory/repertory_test/src/file_manager_test.cpp b/repertory/repertory_test/src/file_manager_test.cpp index a7020222..4c6804c3 100644 --- a/repertory/repertory_test/src/file_manager_test.cpp +++ b/repertory/repertory_test/src/file_manager_test.cpp @@ -34,7 +34,6 @@ #include "utils/encrypting_reader.hpp" #include "utils/event_capture.hpp" #include "utils/file_utils.hpp" -#include "utils/native_file.hpp" #include "utils/path.hpp" #include "utils/polling.hpp" #include "utils/string.hpp" @@ -43,7 +42,7 @@ namespace repertory { static std::string file_manager_dir = - utils::path::combine("./test_config", {"file_manager_test"}); + utils::path::combine(test::get_test_output_dir(), {"file_manager_test"}); auto file_manager::open(std::shared_ptr of, const open_file_data &ofd, std::uint64_t &handle, @@ -426,9 +425,8 @@ TEST(file_manager, download_is_stored_after_write_if_partially_downloaded) { false, 1, "key", 2, now + 3u, 3u, 4u, utils::encryption::encrypting_reader::get_data_chunk_size() * 4u, source_path, 10, now + 4u); - auto nf = create_random_file( - generate_test_file_name("./test_config", "file_manage_test"), - utils::string::to_uint64(meta[META_SIZE])); + auto nf = + test::create_random_file(utils::string::to_uint64(meta[META_SIZE])); EXPECT_CALL(mp, get_filesystem_item) .WillRepeatedly([&meta](const std::string &api_path, bool directory, @@ -465,9 +463,8 @@ TEST(file_manager, download_is_stored_after_write_if_partially_downloaded) { if (offset == 0u) { std::size_t bytes_read{}; data.resize(size); - auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read) - ? api_error::success - : api_error::os_error; + auto ret = nf.read(data, offset, &bytes_read) ? api_error::success + : api_error::os_error; EXPECT_EQ(bytes_read, data.size()); return ret; } @@ -542,7 +539,7 @@ TEST(file_manager, download_is_stored_after_write_if_partially_downloaded) { EXPECT_EQ(std::size_t(0u), fm.get_open_file_count()); EXPECT_EQ(std::size_t(0u), fm.get_open_handle_count()); - nf->close(); + nf.close(); } event_system::instance().stop(); @@ -589,9 +586,8 @@ TEST(file_manager, upload_occurs_after_write_if_fully_downloaded) { false, 1, "key", 2, now + 3u, 3u, 4u, utils::encryption::encrypting_reader::get_data_chunk_size() * 4u, source_path, 10, now + 4u); - auto nf = create_random_file( - generate_test_file_name("./test_config", "file_manage_test"), - utils::string::to_uint64(meta[META_SIZE])); + auto nf = + test::create_random_file(utils::string::to_uint64(meta[META_SIZE])); EXPECT_CALL(mp, get_filesystem_item) .WillRepeatedly([&meta](const std::string &api_path, bool directory, @@ -623,9 +619,8 @@ TEST(file_manager, upload_occurs_after_write_if_fully_downloaded) { stop_type & /* stop_requested */) -> api_error { std::size_t bytes_read{}; data.resize(size); - auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read) - ? api_error::success - : api_error::os_error; + auto ret = nf.read(data, offset, &bytes_read) ? api_error::success + : api_error::os_error; EXPECT_EQ(bytes_read, data.size()); return ret; }); @@ -660,7 +655,7 @@ TEST(file_manager, upload_occurs_after_write_if_fully_downloaded) { fm.stop(); - nf->close(); + nf.close(); } polling::instance().stop(); @@ -1601,10 +1596,9 @@ TEST(file_manager, can_remove_file) { file_manager fm(cfg, mp); - native_file::native_file_ptr f{}; - EXPECT_EQ(api_error::success, - native_file::create_or_open("./test_remove.txt", f)); - f->close(); + auto file = utils::file::file::open_or_create_file("./test_remove.txt"); + EXPECT_TRUE(file); + file.close(); EXPECT_TRUE(utils::file::is_file("./test_remove.txt")); EXPECT_CALL(mp, get_filesystem_item) diff --git a/repertory/repertory_test/src/file_manager_upload_test.cpp b/repertory/repertory_test/src/file_manager_upload_test.cpp index deb3cce2..b55af6ec 100644 --- a/repertory/repertory_test/src/file_manager_upload_test.cpp +++ b/repertory/repertory_test/src/file_manager_upload_test.cpp @@ -35,8 +35,7 @@ TEST(upload, can_upload_a_valid_file) { event_system::instance().start(); - const auto source_path = - generate_test_file_name("./test_config", "upload_test"); + const auto source_path = test::generate_test_file_name("upload_test"); mock_provider mp; @@ -79,8 +78,7 @@ TEST(upload, can_cancel_upload) { event_system::instance().start(); - const auto source_path = - generate_test_file_name("./test_config", "upload_test"); + const auto source_path = test::generate_test_file_name("upload_test"); mock_provider mp; @@ -145,8 +143,7 @@ TEST(upload, can_stop_upload) { event_system::instance().start(); - const auto source_path = - generate_test_file_name("./test_config", "upload_test"); + const auto source_path = test::generate_test_file_name("upload_test"); mock_provider mp; diff --git a/repertory/repertory_test/src/fuse_drive_test.cpp b/repertory/repertory_test/src/fuse_drive_test.cpp index cc78ff84..bf5a69ff 100644 --- a/repertory/repertory_test/src/fuse_drive_test.cpp +++ b/repertory/repertory_test/src/fuse_drive_test.cpp @@ -515,7 +515,7 @@ TEST(fuse_drive, all_tests) { std::filesystem::current_path(current_directory); const auto test_directory = utils::path::combine( - "./test_config", {"fuse_drive" + std::to_string(idx)}); + test::get_test_output_dir(), {"fuse_drive" + std::to_string(idx)}); EXPECT_TRUE(utils::file::delete_directory_recursively(test_directory)); const auto mount_location = @@ -538,8 +538,9 @@ TEST(fuse_drive, all_tests) { config_ptr = std::make_unique(provider_type::s3, cfg_directory); { - app_config src_cfg(provider_type::s3, - utils::path::combine(get_test_dir(), {"storj"})); + app_config src_cfg( + provider_type::s3, + utils::path::combine(test::get_test_input_dir(), {"storj"})); config_ptr->set_enable_drive_events(true); config_ptr->set_event_level(event_level::trace); config_ptr->set_s3_config(src_cfg.get_s3_config()); @@ -554,8 +555,9 @@ TEST(fuse_drive, all_tests) { config_ptr = std::make_unique(provider_type::sia, cfg_directory); { - app_config src_cfg(provider_type::sia, - utils::path::combine(get_test_dir(), {"sia"})); + app_config src_cfg( + provider_type::sia, + utils::path::combine(test::get_test_input_dir(), {"sia"})); config_ptr->set_enable_drive_events(true); config_ptr->set_event_level(event_level::debug); config_ptr->set_host_config(src_cfg.get_host_config()); diff --git a/repertory/repertory_test/src/providers_test.cpp b/repertory/repertory_test/src/providers_test.cpp index 1ecbb4cc..86dd8138 100644 --- a/repertory/repertory_test/src/providers_test.cpp +++ b/repertory/repertory_test/src/providers_test.cpp @@ -107,8 +107,7 @@ const auto create_directory = [](repertory::i_provider &provider, const auto create_file = [](repertory::i_provider &provider, const std::string &api_path) { - auto source_path = - repertory::generate_test_file_name("./test_config", "providers_test"); + auto source_path = repertory::test::generate_test_file_name("providers_test"); auto date = repertory::utils::time::get_file_time_now(); auto meta = repertory::create_meta_attributes( @@ -398,7 +397,7 @@ static void get_directory_item_count(const app_config &cfg, EXPECT_EQ(std::size_t(0U), provider.get_directory_item_count("/not_found")); const auto source_path = - utils::path::combine("./test_data/encrypt", {"sub10"}); + utils::path::combine(test::get_test_input_dir(), {"encrypt", "sub10"}); std::string api_path{}; EXPECT_EQ(api_error::success, @@ -630,7 +629,7 @@ static void run_tests(const app_config &cfg, i_provider &provider) { TEST(providers, encrypt_provider) { const auto config_path = - utils::path::combine("./test_config", {"encrypt_provider"}); + utils::path::combine(test::get_test_output_dir(), {"encrypt_provider"}); ASSERT_TRUE(utils::file::delete_directory_recursively(config_path)); console_consumer consumer{}; @@ -639,7 +638,7 @@ TEST(providers, encrypt_provider) { app_config cfg(provider_type::encrypt, config_path); const auto encrypt_path = - utils::path::combine("./test_data/encrypt", {"encrypt"}); + utils::path::combine(test::get_test_input_dir(), {"encrypt"}); EXPECT_STREQ( encrypt_path.c_str(), @@ -673,7 +672,7 @@ TEST(providers, encrypt_provider) { TEST(providers, s3_provider) { const auto config_path = - utils::path::combine("./test_config", {"s3_provider"}); + utils::path::combine(test::get_test_output_dir(), {"s3_provider"}); ASSERT_TRUE(utils::file::delete_directory_recursively(config_path)); console_consumer consumer{}; @@ -681,8 +680,9 @@ TEST(providers, s3_provider) { { app_config cfg(provider_type::s3, config_path); { - app_config src_cfg(provider_type::s3, - utils::path::combine(get_test_dir(), {"storj"})); + app_config src_cfg( + provider_type::s3, + utils::path::combine(test::get_test_input_dir(), {"storj"})); cfg.set_s3_config(src_cfg.get_s3_config()); } @@ -711,7 +711,7 @@ TEST(providers, s3_provider) { TEST(providers, sia_provider) { const auto config_path = - utils::path::combine("./test_config", {"sia_provider"}); + utils::path::combine(test::get_test_output_dir(), {"sia_provider"}); ASSERT_TRUE(utils::file::delete_directory_recursively(config_path)); console_consumer consumer{}; @@ -719,8 +719,9 @@ TEST(providers, sia_provider) { { app_config cfg(provider_type::sia, config_path); { - app_config src_cfg(provider_type::sia, - utils::path::combine(get_test_dir(), {"sia"})); + app_config src_cfg( + provider_type::sia, + utils::path::combine(test::get_test_input_dir(), {"sia"})); cfg.set_host_config(src_cfg.get_host_config()); } diff --git a/repertory/repertory_test/src/remote_fuse_test.cpp b/repertory/repertory_test/src/remote_fuse_test.cpp index 2fd1d4b9..54480d92 100644 --- a/repertory/repertory_test/src/remote_fuse_test.cpp +++ b/repertory/repertory_test/src/remote_fuse_test.cpp @@ -47,7 +47,7 @@ using namespace repertory::remote_fuse; namespace fuse_test { static std::string mount_location_; static std::string fuse_remote_dir = - utils::path::combine("./test_config", {"fuse_remote_test"}); + utils::path::combine(test::get_test_output_dir(), {"fuse_remote_test"}); static void access_test(repertory::remote_fuse::remote_client &client) { const auto test_file = utils::path::combine(fuse_remote_dir, {"access.txt"}); @@ -934,7 +934,7 @@ TEST(remote_fuse, all_tests) { event_system::instance().start(); #if defined(_WIN32) - mount_location_ = std::string("./test_config").substr(0, 2); + mount_location_ = std::string(test::get_test_output_dir(), 2); mock_winfsp_drive drive(mount_location_); remote_server server(config, drive, mount_location_); #else diff --git a/repertory/repertory_test/src/remote_winfsp_test.cpp b/repertory/repertory_test/src/remote_winfsp_test.cpp index 86115d12..91276cb4 100644 --- a/repertory/repertory_test/src/remote_winfsp_test.cpp +++ b/repertory/repertory_test/src/remote_winfsp_test.cpp @@ -40,7 +40,7 @@ using namespace repertory::remote_winfsp; namespace winfsp_test { static std::string mount_location_; static std::string win_remote_dir = - utils::path::combine("./test_config", {"win_remote_test"}); + utils::path::combine(test::get_test_output_dir(), {"win_remote_test"}); static void can_delete_test(remote_client &client) { const auto test_file = @@ -49,15 +49,14 @@ static void can_delete_test(remote_client &client) { auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size()); - native_file::native_file_ptr nf; - EXPECT_EQ(api_error::success, native_file::create_or_open(test_file, nf)); + auto nf = utils::file::file::open_or_create_file(test_file); EXPECT_TRUE(nf); if (nf) { EXPECT_EQ(STATUS_INVALID_HANDLE, client.winfsp_can_delete( - reinterpret_cast(nf->get_handle()), &api_path[0])); + reinterpret_cast(nf.get_handle()), api_path.c_str()); - nf->close(); + nf.close(); EXPECT_TRUE(utils::file::retry_delete_file(test_file)); } } @@ -502,7 +501,7 @@ TEST(remote_winfsp, all_tests) { event_system::instance().start(); #if defined(_WIN32) - mount_location_ = std::string("./test_config").substr(0, 2); + mount_location_ = std::string(test::get_test_output_dir(), 2); mock_winfsp_drive drive(mount_location_); remote_server server(config, drive, mount_location_); #else diff --git a/repertory/repertory_test/src/test_common.cpp b/repertory/repertory_test/src/test_common.cpp deleted file mode 100644 index 74dc7eee..00000000 --- a/repertory/repertory_test/src/test_common.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright <2018-2024> - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ -#include "test_common.hpp" - -#include "types/repertory.hpp" -#include "utils/common.hpp" -#include "utils/path.hpp" - -namespace repertory { -std::vector generated_files; - -void delete_generated_files() { - for (const auto &file : generated_files) { - EXPECT_TRUE(utils::file::retry_delete_file(file)); - } -} - -auto create_random_file(std::string path, std::size_t size) -> native_file_ptr { - native_file_ptr file; - if (native_file::create_or_open(path, file) == api_error::success) { - generated_files.emplace_back(utils::path::absolute(path)); - - EXPECT_TRUE(file->truncate(0U)); - - data_buffer buf(size); - randombytes_buf(buf.data(), buf.size()); - - std::size_t bytes_written{}; - EXPECT_TRUE(file->write_bytes(buf.data(), buf.size(), 0U, bytes_written)); - file->flush(); - - std::uint64_t current_size{}; - EXPECT_TRUE(utils::file::get_file_size(path, current_size)); - EXPECT_EQ(size, current_size); - } - - return file; -} - -auto generate_test_file_name(const std::string &directory, - const std::string &file_name_no_extension) - -> std::string { - static std::atomic idx{0U}; - auto path = utils::path::combine( - directory, {file_name_no_extension + std::to_string(idx++) + ".dat"}); - generated_files.emplace_back(path); - return path; -} - -auto get_test_dir() -> std::string { - auto dir = utils::get_environment_variable("PROJECT_TEST_DIR"); - return utils::path::combine(dir.empty() ? "." : dir, {"test_config"}); -} -} // namespace repertory diff --git a/support/include/utils/all.hpp b/support/include/utils/all.hpp index d0a9455f..ead01732 100644 --- a/support/include/utils/all.hpp +++ b/support/include/utils/all.hpp @@ -24,13 +24,19 @@ #include "utils/config.hpp" +#include "utils/base64.hpp" #include "utils/collection.hpp" #include "utils/com_init_wrapper.hpp" #include "utils/common.hpp" +#include "utils/encrypting_reader.hpp" +#include "utils/encryption.hpp" +#include "utils/error.hpp" +#include "utils/file.hpp" +#include "utils/hash.hpp" #include "utils/path.hpp" #include "utils/string.hpp" #include "utils/time.hpp" #include "utils/unix.hpp" #include "utils/windows.hpp" -#endif // REPERTORY_INCLUDE_UTILS_ALL_HPP_ \ No newline at end of file +#endif // REPERTORY_INCLUDE_UTILS_ALL_HPP_ diff --git a/support/include/utils/config.hpp b/support/include/utils/config.hpp index 11136ead..c5e44ed4 100644 --- a/support/include/utils/config.hpp +++ b/support/include/utils/config.hpp @@ -22,6 +22,8 @@ #ifndef REPERTORY_INCLUDE_UTILS_CONFIG_HPP_ #define REPERTORY_INCLUDE_UTILS_CONFIG_HPP_ +#define NOMINMAX + #if defined(_WIN32) #define WINVER 0x0602 #define _WIN32_WINNT WINVER @@ -300,9 +302,19 @@ namespace repertory { using data_buffer = std::vector; using mutex_lock = std::lock_guard; using recur_mutex_lock = std::lock_guard; +using stop_type = std::atomic_bool; using unique_mutex_lock = std::unique_lock; using unique_recur_mutex_lock = std::unique_lock; +#if defined(_WIN32) +using native_handle = HANDLE; +#else // !defined(_WIN32) +using native_handle = int; +#if !defined(INVALID_HANDLE_VALUE) +#define INVALID_HANDLE_VALUE (-1) +#endif // !defined(INVALID_HANDLE_VALUE) +#endif // defined(_WIN32) + template struct overloaded : Ts... { using Ts::operator()...; }; diff --git a/repertory/librepertory/include/utils/encrypting_reader.hpp b/support/include/utils/encrypting_reader.hpp similarity index 90% rename from repertory/librepertory/include/utils/encrypting_reader.hpp rename to support/include/utils/encrypting_reader.hpp index b4d4bb6a..e13f4d74 100644 --- a/repertory/librepertory/include/utils/encrypting_reader.hpp +++ b/support/include/utils/encrypting_reader.hpp @@ -1,140 +1,146 @@ -/* - Copyright <2018-2024> - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ -#ifndef INCLUDE_UTILS_ENCRYPTING_READER_HPP_ -#define INCLUDE_UTILS_ENCRYPTING_READER_HPP_ - -#include "types/repertory.hpp" -#include "utils/encryption.hpp" -#include "utils/native_file.hpp" - -namespace repertory::utils::encryption { -class encrypting_reader final { -public: - encrypting_reader(std::string_view file_name, std::string_view source_path, - stop_type &stop_requested, std::string_view token, - std::optional relative_parent_path, - std::size_t error_return = 0U); - - encrypting_reader(std::string_view encrypted_file_path, - std::string_view source_path, stop_type &stop_requested, - std::string_view token, std::size_t error_return = 0U); - - encrypting_reader( - std::string_view encrypted_file_path, std::string_view source_path, - stop_type &stop_requested, std::string_view token, - std::vector> - iv_list, - std::size_t error_return = 0U); - - encrypting_reader(const encrypting_reader &reader); - encrypting_reader(encrypting_reader &&) = delete; - - auto operator=(const encrypting_reader &) -> encrypting_reader & = delete; - auto operator=(encrypting_reader &&) -> encrypting_reader & = delete; - - ~encrypting_reader(); - -public: - using iostream = std::basic_iostream>; - using streambuf = std::basic_streambuf>; - -private: - utils::encryption::hash_256_t key_; - stop_type &stop_requested_; - size_t error_return_; - std::unordered_map chunk_buffers_; - std::string encrypted_file_name_; - std::string encrypted_file_path_; - std::vector< - std::array> - iv_list_; - std::size_t last_data_chunk_{}; - std::size_t last_data_chunk_size_{}; - std::uint64_t read_offset_{}; - native_file_ptr source_file_; - std::uint64_t total_size_{}; - -private: - static const std::size_t header_size_; - static const std::size_t data_chunk_size_; - static const std::size_t encrypted_chunk_size_; - -private: - auto reader_function(char *buffer, size_t size, size_t nitems) -> size_t; - -public: - [[nodiscard]] static auto - calculate_decrypted_size(std::uint64_t total_size) -> std::uint64_t; - - [[nodiscard]] static auto - calculate_encrypted_size(std::string_view source_path) -> std::uint64_t; - - [[nodiscard]] auto create_iostream() const -> std::shared_ptr; - - [[nodiscard]] static constexpr auto - get_encrypted_chunk_size() -> std::size_t { - return encrypted_chunk_size_; - } - - [[nodiscard]] static constexpr auto get_data_chunk_size() -> std::size_t { - return data_chunk_size_; - } - - [[nodiscard]] auto get_encrypted_file_name() const -> std::string { - return encrypted_file_name_; - } - - [[nodiscard]] auto get_encrypted_file_path() const -> std::string { - return encrypted_file_path_; - } - - [[nodiscard]] auto get_error_return() const -> std::size_t { - return error_return_; - } - - [[nodiscard]] auto get_iv_list() - -> std::vector> { - return iv_list_; - } - - [[nodiscard]] auto get_stop_requested() const -> bool { - return stop_requested_; - } - - [[nodiscard]] auto get_total_size() const -> std::uint64_t { - return total_size_; - } - - [[nodiscard]] static auto reader_function(char *buffer, size_t size, - size_t nitems, - void *instream) -> size_t { - return reinterpret_cast(instream)->reader_function( - buffer, size, nitems); - } - - void set_read_position(std::uint64_t position) { read_offset_ = position; } -}; -} // namespace repertory::utils::encryption - -#endif // INCLUDE_UTILS_ENCRYPTING_READER_HPP_ +/* + Copyright <2018-2024> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef REPERTORY_INCLUDE_UTILS_ENCRYPTING_READER_HPP_ +#define REPERTORY_INCLUDE_UTILS_ENCRYPTING_READER_HPP_ +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) + +#include "utils/config.hpp" + +#include "utils/file.hpp" +#include "utils/hash.hpp" + +namespace repertory::utils::encryption { + +class encrypting_reader final { +public: + encrypting_reader(std::string_view file_name, std::string_view source_path, + stop_type &stop_requested, std::string_view token, + std::optional relative_parent_path, + std::size_t error_return = 0U); + + encrypting_reader(std::string_view encrypted_file_path, + std::string_view source_path, stop_type &stop_requested, + std::string_view token, std::size_t error_return = 0U); + + encrypting_reader( + std::string_view encrypted_file_path, std::string_view source_path, + stop_type &stop_requested, std::string_view token, + std::vector> + iv_list, + std::size_t error_return = 0U); + + encrypting_reader(const encrypting_reader &reader); + encrypting_reader(encrypting_reader &&) = delete; + + auto operator=(const encrypting_reader &) -> encrypting_reader & = delete; + auto operator=(encrypting_reader &&) -> encrypting_reader & = delete; + + ~encrypting_reader() noexcept = default; + +public: + using iostream = std::basic_iostream>; + using streambuf = std::basic_streambuf>; + +private: + utils::encryption::hash_256_t key_; + stop_type &stop_requested_; + size_t error_return_; + utils::file::file source_file_; + +private: + std::unordered_map chunk_buffers_; + std::string encrypted_file_name_; + std::string encrypted_file_path_; + std::vector< + std::array> + iv_list_; + std::size_t last_data_chunk_{}; + std::size_t last_data_chunk_size_{}; + std::uint64_t read_offset_{}; + std::uint64_t total_size_{}; + +private: + static const std::size_t header_size_; + static const std::size_t data_chunk_size_; + static const std::size_t encrypted_chunk_size_; + +private: + auto reader_function(char *buffer, size_t size, size_t nitems) -> size_t; + +public: + [[nodiscard]] static auto + calculate_decrypted_size(std::uint64_t total_size) -> std::uint64_t; + + [[nodiscard]] static auto + calculate_encrypted_size(std::string_view source_path) -> std::uint64_t; + + [[nodiscard]] auto create_iostream() const -> std::shared_ptr; + + [[nodiscard]] static constexpr auto + get_encrypted_chunk_size() -> std::size_t { + return encrypted_chunk_size_; + } + + [[nodiscard]] static constexpr auto get_data_chunk_size() -> std::size_t { + return data_chunk_size_; + } + + [[nodiscard]] auto get_encrypted_file_name() const -> std::string { + return encrypted_file_name_; + } + + [[nodiscard]] auto get_encrypted_file_path() const -> std::string { + return encrypted_file_path_; + } + + [[nodiscard]] auto get_error_return() const -> std::size_t { + return error_return_; + } + + [[nodiscard]] auto get_iv_list() + -> std::vector> { + return iv_list_; + } + + [[nodiscard]] auto get_stop_requested() const -> bool { + return stop_requested_; + } + + [[nodiscard]] auto get_total_size() const -> std::uint64_t { + return total_size_; + } + + [[nodiscard]] static auto reader_function(char *buffer, size_t size, + size_t nitems, + void *instream) -> size_t { + return reinterpret_cast(instream)->reader_function( + buffer, size, nitems); + } + + void set_read_position(std::uint64_t position) { read_offset_ = position; } +}; +} // namespace repertory::utils::encryption + +#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +#endif // REPERTORY_INCLUDE_UTILS_ENCRYPTING_READER_HPP_ diff --git a/support/include/utils/encryption.hpp b/support/include/utils/encryption.hpp index 28e55ca0..029c6667 100644 --- a/support/include/utils/encryption.hpp +++ b/support/include/utils/encryption.hpp @@ -33,38 +33,24 @@ inline constexpr const std::uint32_t encryption_header_size{ crypto_aead_xchacha20poly1305_IETF_ABYTES, }; -template -[[nodiscard]] inline auto default_create_hash(std::string_view) -> hash_t; - -template -[[nodiscard]] inline auto default_create_hash(std::wstring_view) -> hash_t; - template inline auto generate_key( std::string_view password, - std::optional< - std::function> - hasher = std::nullopt) -> hash_t; + std::function hasher = + default_create_hash()) -> hash_t; template inline auto generate_key( std::wstring_view password, - std::optional< - std::function> - hasher = std::nullopt) -> hash_t; + std::function hasher = + default_create_hash()) -> hash_t; #if defined(PROJECT_ENABLE_BOOST) -[[nodiscard]] auto decrypt_data(std::string_view password, - std::string_view data) -> data_buffer; - -[[nodiscard]] auto encrypt_data(std::string_view password, - std::string_view data) -> data_buffer; - -template +template [[nodiscard]] inline auto decrypt_data(const std::array &key, const unsigned char *buffer, std::size_t buffer_size, - result &res) -> bool { + result_t &res) -> bool { if (buffer_size > encryption_header_size) { const std::uint32_t size = boost::endian::native_to_big(static_cast(buffer_size)); @@ -80,43 +66,42 @@ template return false; } -template [[nodiscard]] inline auto decrypt_data(const std::array &key, - const buffer &buf, result &res) -> bool { - return decrypt_data( + const buffer_t &buf, + result_t &res) -> bool { + return decrypt_data( key, reinterpret_cast(buf.data()), buf.size(), res); } -template +template [[nodiscard]] inline auto decrypt_data( - std::string_view password, const buffer &buf, result &res, - std::optional< - std::function> - hasher = std::nullopt) -> bool { - return decrypt_data(generate_key(password, hasher), buf, res); + std::string_view password, const buffer_t &buf, result_t &res, + std::function hasher = + default_create_hash()) -> bool { + return decrypt_data(generate_key(password, hasher), buf, + res); } -template +template [[nodiscard]] inline auto decrypt_data( std::string_view password, const unsigned char *buffer, - std::size_t buffer_size, result &res, - - std::optional< - std::function> - hasher = std::nullopt) -> bool { - return decrypt_data(generate_key(password, hasher), buffer, - buffer_size, res); + std::size_t buffer_size, result_t &res, + std::function hasher = + default_create_hash()) -> bool { + return decrypt_data(generate_key(password, hasher), buffer, + buffer_size, res); } -template +template inline void encrypt_data(const std::array &iv, const std::array &key, const unsigned char *buffer, std::size_t buffer_size, - result &res) { + result_t &res) { std::array mac{}; const std::uint32_t size = boost::endian::native_to_big( @@ -137,115 +122,74 @@ encrypt_data(const std::array -inline void encrypt_data(const std::array &key, +template +inline void encrypt_data(const std::array &key, const unsigned char *buffer, std::size_t buffer_size, - result &res) { + result_t &res) { std::array iv{}; randombytes_buf(iv.data(), iv.size()); - encrypt_data(iv, key, buffer, buffer_size, res); + encrypt_data(iv, key, buffer, buffer_size, res); } -template +template inline void encrypt_data( std::string_view password, const unsigned char *buffer, - std::size_t buffer_size, result &res, - std::optional< - std::function> - hasher = std::nullopt) { - encrypt_data(generate_key(password, hasher), buffer, buffer_size, - res); + std::size_t buffer_size, result_t &res, + std::function hasher = + default_create_hash()) { + encrypt_data(generate_key(password, hasher), buffer, buffer_size, + res); } -template +template inline void encrypt_data( - std::string_view password, const buffer &buf, result &res, - std::optional< - std::function> - hasher = std::nullopt) { - encrypt_data(generate_key(password, hasher), - reinterpret_cast(buf.data()), - buf.size(), res); + std::string_view password, const buffer_t &buf, result_t &res, + std::function hasher = + default_create_hash()) { + encrypt_data(generate_key(password, hasher), + reinterpret_cast(buf.data()), + buf.size(), res); } -template -inline void encrypt_data(const std::array &key, const buffer &buf, - result &res) { - encrypt_data(key, reinterpret_cast(buf.data()), - buf.size(), res); +template +inline void encrypt_data(const std::array &key, + const buffer_t &buf, result_t &res) { + encrypt_data(key, + reinterpret_cast(buf.data()), + buf.size(), res); } -template +template inline void encrypt_data(const std::array &iv, - const std::array &key, const buffer &buf, result &res) { - encrypt_data(iv, key, - reinterpret_cast(buf.data()), - buf.size(), res); + const std::array &key, const buffer_t &buf, + result_t &res) { + encrypt_data(iv, key, + reinterpret_cast(buf.data()), + buf.size(), res); } #endif // defined(PROJECT_ENABLE_BOOST) -template <> -inline auto -default_create_hash(std::string_view data) -> hash_256_t { - return create_hash_sha256(data); -} - -template <> -inline auto -default_create_hash(std::wstring_view data) -> hash_256_t { - return create_hash_sha256(data); -} - -template <> -inline auto -default_create_hash(std::string_view data) -> hash_384_t { - return create_hash_blake2b_384(data); -} - -template <> -inline auto -default_create_hash(std::wstring_view data) -> hash_384_t { - return create_hash_blake2b_384(data); -} - -template <> -inline auto -default_create_hash(std::string_view data) -> hash_512_t { - return create_hash_sha512(data); -} - -template <> -inline auto -default_create_hash(std::wstring_view data) -> hash_512_t { - return create_hash_sha512(data); -} - template inline auto generate_key( std::string_view password, - std::optional< - std::function> - hasher) -> hash_t { - return hasher.has_value() ? (*hasher)(reinterpret_cast( - password.data()), - password.size()) - : default_create_hash(password); + std::function hasher) + -> hash_t { + return hasher(reinterpret_cast(password.data()), + password.size()); } template inline auto generate_key( std::wstring_view password, - std::optional< - std::function> - hasher) -> hash_t { - return hasher.has_value() - ? (*hasher)( - reinterpret_cast(password.data()), - password.size() * sizeof(std::wstring_view::value_type)) - : default_create_hash(password); + std::function hasher) + -> hash_t { + return hasher(reinterpret_cast(password.data()), + password.size() * sizeof(wchar_t)); } } // namespace repertory::utils::encryption diff --git a/support/include/utils/file.hpp b/support/include/utils/file.hpp index 3f5c3df2..7b0ce701 100644 --- a/support/include/utils/file.hpp +++ b/support/include/utils/file.hpp @@ -27,75 +27,103 @@ namespace repertory::utils::file { class file final { public: - [[nodiscard]] static auto open_file(std::filesystem::path path) -> file; + [[nodiscard]] static auto open_file(std::filesystem::path path, + bool read_only = false) -> file; - [[nodiscard]] static auto - open_or_create_file(std::filesystem::path path) -> file; + [[nodiscard]] static auto open_or_create_file(std::filesystem::path path, + bool read_only = false) -> file; + + file() noexcept = default; protected: - file(std::fstream stream, std::filesystem::path path) - : path_(std::move(path)), stream_(std::move(stream)) {} - file() = default; + file(file_t file_ptr, std::filesystem::path path) + : file_(std::move(file_ptr)), path_(std::move(path)) {} public: file(const file &) = delete; - file(file &&file_) noexcept = default; + + file(file &&move_file) noexcept + : file_(std::move(move_file.file_)), + path_(std::move(move_file.path_)) +#if defined(_WIN32) + , + mtx_() +#endif // defined(_WIN32) + { + } ~file() { close(); } auto operator=(const file &) noexcept -> file & = delete; - auto operator=(file &&file_) noexcept -> file & = default; + + auto operator=(file &&move_file) noexcept -> file & { + if (&move_file != this) { + file_ = std::move(move_file.file_); + path_ = std::move(move_file.path_); + } + + return *this; + } private: - std::error_code error_{}; + file_t file_{nullptr}; std::filesystem::path path_; - std::fstream stream_; +#if defined(_WIN32) + mutable std::recursive_mutex mtx_{}; +#endif // defined(_WIN32) public: void close(); - [[nodiscard]] auto get_error_code() const -> std::error_code { - return error_; - } + void flush(); + + [[nodiscard]] auto get_handle() const -> native_handle; [[nodiscard]] auto get_path() const -> std::filesystem::path { return path_; } [[nodiscard]] auto move_to(std::filesystem::path new_path) -> bool; [[nodiscard]] auto read(data_buffer &data, std::uint64_t offset, - std::size_t *total_read = nullptr) -> bool { - return read_(reinterpret_cast(data.data()), data.size(), - offset, total_read); - } + std::size_t *total_read = nullptr) -> bool; + + [[nodiscard]] auto read(unsigned char *data, std::size_t to_read, + std::uint64_t offset, + std::size_t *total_read = nullptr) -> bool; + + [[nodiscard]] auto read_all(data_buffer &data, std::uint64_t offset, + std::size_t *total_read = nullptr) -> bool; [[nodiscard]] auto remove() -> bool; + [[nodiscard]] auto size() const -> std::uint64_t; + [[nodiscard]] auto truncate() -> bool { return truncate(0U); } [[nodiscard]] auto truncate(std::size_t size) -> bool; [[nodiscard]] auto write(const data_buffer &data, std::uint64_t offset, std::size_t *total_written = nullptr) -> bool { + return write_(reinterpret_cast(data.data()), + data.size() * sizeof(data_buffer::value_type), offset, + total_written); + } + + [[nodiscard]] auto write(std::string_view data, std::uint64_t offset, + std::size_t *total_written = nullptr) -> bool { return write_(reinterpret_cast(data.data()), data.size(), offset, total_written); } -#if defined(PROJECT_ENABLE_JSON) - [[nodiscard]] auto write_json(const nlohmann::json &data, - std::size_t *total_written = nullptr) -> bool { - auto str_data = data.dump(); - return write_(reinterpret_cast(str_data.c_str()), - str_data.size(), 0U, total_written); + [[nodiscard]] auto write(std::wstring_view data, std::uint64_t offset, + std::size_t *total_written = nullptr) -> bool { + return write_(reinterpret_cast(data.data()), + data.size() * sizeof(wchar_t), offset, total_written); } -#endif // defined(PROJECT_ENABLE_JSON) - [[nodiscard]] operator bool() const { return stream_.is_open(); } +public: + [[nodiscard]] operator bool() const { return file_ != nullptr; } private: - [[nodiscard]] auto read_(unsigned char *data, std::size_t to_read, - std::uint64_t offset, - std::size_t *total_read) -> bool; - [[nodiscard]] auto write_(const unsigned char *data, std::size_t to_write, std::size_t offset, std::size_t *total_written) -> bool; diff --git a/support/include/utils/hash.hpp b/support/include/utils/hash.hpp index 9c74f216..a79c9023 100644 --- a/support/include/utils/hash.hpp +++ b/support/include/utils/hash.hpp @@ -35,219 +35,132 @@ using hash_512_t = std::array; [[nodiscard]] auto create_hash_blake2b_256(std::wstring_view data) -> hash_256_t; +[[nodiscard]] auto +create_hash_blake2b_256(const data_buffer &data) -> hash_256_t; + [[nodiscard]] auto create_hash_blake2b_384(std::string_view data) -> hash_384_t; [[nodiscard]] auto create_hash_blake2b_384(std::wstring_view data) -> hash_384_t; -[[nodiscard]] auto create_hash_blake2b_512(std::string_view data) -> hash_512_t; +[[nodiscard]] auto +create_hash_blake2b_384(const data_buffer &data) -> hash_384_t; [[nodiscard]] auto create_hash_blake2b_512(std::wstring_view data) -> hash_512_t; -template [[nodiscard]] auto -create_hash_blake2b_t(std::basic_string_view data) -> hash_t; +create_hash_blake2b_512(const data_buffer &data) -> hash_512_t; + +[[nodiscard]] auto create_hash_blake2b_512(std::string_view data) -> hash_512_t; template -[[nodiscard]] auto create_hash_blake2b_t(const data_buffer &data) -> hash_t; - -template -[[nodiscard]] auto create_hash_blake2b_t( - const std::vector> &data) -> hash_t; - -template -[[nodiscard]] auto -create_hash_blake2b_t(const std::vector> &data) - -> std::array; +[[nodiscard]] auto create_hash_blake2b_t(const unsigned char *data, + std::size_t data_size) -> hash_t; [[nodiscard]] auto create_hash_sha256(std::string_view data) -> hash_256_t; [[nodiscard]] auto create_hash_sha256(std::wstring_view data) -> hash_256_t; +[[nodiscard]] auto create_hash_sha256(const data_buffer &data) -> hash_256_t; + +[[nodiscard]] auto create_hash_sha256(const unsigned char *data, + std::size_t data_size) -> hash_256_t; + [[nodiscard]] auto create_hash_sha512(std::string_view data) -> hash_512_t; [[nodiscard]] auto create_hash_sha512(std::wstring_view data) -> hash_512_t; -template -[[nodiscard]] auto -create_hash_sha256_t(std::basic_string_view data) -> hash_256_t; +[[nodiscard]] auto create_hash_sha512(const data_buffer &data) -> hash_512_t; -template -[[nodiscard]] auto create_hash_sha512_t(std::basic_string_view data) - -> repertory::utils::encryption::hash_512_t; +[[nodiscard]] auto create_hash_sha512(const unsigned char *data, + std::size_t data_size) -> hash_512_t; template -auto create_hash_blake2b_t(const data_buffer &data) -> hash_t { +[[nodiscard]] inline auto default_create_hash() -> const + std::function &; + +template +auto create_hash_blake2b_t(const unsigned char *data, + std::size_t data_size) -> hash_t { hash_t hash{}; crypto_generichash_blake2b_state state{}; auto res = crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size()); if (res != 0) { - throw std::runtime_error("failed to initialize blake2b|" + + throw std::runtime_error("failed to initialize blake2b-" + + std::to_string(hash.size() * 8U) + "|" + std::to_string(res)); } - res = crypto_generichash_blake2b_update( - &state, reinterpret_cast(data.data()), - data.size() * sizeof(data_buffer::value_type)); + res = crypto_generichash_blake2b_update(&state, data, data_size); if (res != 0) { - throw std::runtime_error("failed to update blake2b|" + std::to_string(res)); + throw std::runtime_error("failed to update blake2b-" + + std::to_string(hash.size() * 8U) + "|" + + std::to_string(res)); } res = crypto_generichash_blake2b_final(&state, hash.data(), hash.size()); if (res != 0) { - throw std::runtime_error("failed to finalize blake2b|" + + throw std::runtime_error("failed to finalize blake2b-" + + std::to_string(hash.size() * 8U) + "|" + std::to_string(res)); } return hash; } -template -auto create_hash_blake2b_t(const std::vector> &data) - -> std::array { - using hash_t = std::array; - hash_t hash{}; +inline const std::function + blake2b_256_hasher = + [](const unsigned char *data, std::size_t data_size) -> hash_256_t { + return create_hash_blake2b_t(data, data_size); +}; - crypto_generichash_blake2b_state state{}; - auto res = crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size()); - if (res != 0) { - throw std::runtime_error("failed to initialize blake2b|" + - std::to_string(res)); - } +inline const std::function + blake2b_384_hasher = + [](const unsigned char *data, std::size_t data_size) -> hash_384_t { + return create_hash_blake2b_t(data, data_size); +}; - for (const auto &item : data) { - res = crypto_generichash_blake2b_update( - &state, reinterpret_cast(item.data()), - item.size()); - if (res != 0) { - throw std::runtime_error("failed to update blake2b|" + - std::to_string(res)); - } - } +inline const std::function + blake2b_512_hasher = + [](const unsigned char *data, std::size_t data_size) -> hash_512_t { + return create_hash_blake2b_t(data, data_size); +}; - res = crypto_generichash_blake2b_final(&state, hash.data(), hash.size()); - if (res != 0) { - throw std::runtime_error("failed to finalize blake2b|" + - std::to_string(res)); - } +inline const std::function + sha256_hasher = + [](const unsigned char *data, std::size_t data_size) -> hash_256_t { + return create_hash_sha256(data, data_size); +}; - return hash; +inline const std::function + sha512_hasher = + [](const unsigned char *data, std::size_t data_size) -> hash_512_t { + return create_hash_sha512(data, data_size); +}; + +template <> +[[nodiscard]] inline auto default_create_hash() -> const + std::function & { + return blake2b_256_hasher; } -template -auto create_hash_blake2b_t(const std::vector> &data) - -> hash_t { - hash_t hash{}; - - crypto_generichash_blake2b_state state{}; - auto res = crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size()); - if (res != 0) { - throw std::runtime_error("failed to initialize blake2b|" + - std::to_string(res)); - } - - for (const auto &item : data) { - res = crypto_generichash_blake2b_update( - &state, reinterpret_cast(item.data()), - item.size() * sizeof(char_t)); - if (res != 0) { - throw std::runtime_error("failed to update blake2b|" + - std::to_string(res)); - } - } - - res = crypto_generichash_blake2b_final(&state, hash.data(), hash.size()); - if (res != 0) { - throw std::runtime_error("failed to finalize blake2b|" + - std::to_string(res)); - } - - return hash; +template <> +[[nodiscard]] inline auto default_create_hash() -> const + std::function & { + return blake2b_384_hasher; } -template -auto create_hash_blake2b_t(std::basic_string_view data) -> hash_t { - hash_t hash{}; - - crypto_generichash_blake2b_state state{}; - auto res = crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size()); - if (res != 0) { - throw std::runtime_error("failed to initialize blake2b|" + - std::to_string(res)); - } - - res = crypto_generichash_blake2b_update( - &state, reinterpret_cast(data.data()), - data.size() * sizeof(char_t)); - if (res != 0) { - throw std::runtime_error("failed to update blake2b|" + std::to_string(res)); - } - - res = crypto_generichash_blake2b_final(&state, hash.data(), hash.size()); - if (res != 0) { - throw std::runtime_error("failed to finalize blake2b|" + - std::to_string(res)); - } - - return hash; -} - -template -auto create_hash_sha256_t(std::basic_string_view data) - -> repertory::utils::encryption::hash_256_t { - repertory::utils::encryption::hash_256_t hash{}; - - crypto_hash_sha256_state state{}; - auto res = crypto_hash_sha256_init(&state); - if (res != 0) { - throw std::runtime_error("failed to initialize sha256|" + - std::to_string(res)); - } - - res = crypto_hash_sha256_update( - &state, reinterpret_cast(data.data()), - data.size() * sizeof(char_t)); - if (res != 0) { - throw std::runtime_error("failed to update sha256|" + std::to_string(res)); - } - - res = crypto_hash_sha256_final(&state, hash.data()); - if (res != 0) { - throw std::runtime_error("failed to finalize sha256|" + - std::to_string(res)); - } - - return hash; -} - -template -auto create_hash_sha512_t(std::basic_string_view data) - -> repertory::utils::encryption::hash_512_t { - repertory::utils::encryption::hash_512_t hash{}; - - crypto_hash_sha512_state state{}; - auto res = crypto_hash_sha512_init(&state); - if (res != 0) { - throw std::runtime_error("failed to initialize sha512|" + - std::to_string(res)); - } - - res = crypto_hash_sha512_update( - &state, reinterpret_cast(data.data()), - data.size() * sizeof(char_t)); - if (res != 0) { - throw std::runtime_error("failed to update sha512|" + std::to_string(res)); - } - - res = crypto_hash_sha512_final(&state, hash.data()); - if (res != 0) { - throw std::runtime_error("failed to finalize sha512|" + - std::to_string(res)); - } - - return hash; +template <> +[[nodiscard]] inline auto default_create_hash() -> const + std::function & { + return blake2b_512_hasher; } } // namespace repertory::utils::encryption diff --git a/support/src/utils/common.cpp b/support/src/utils/common.cpp index 72b926e6..c548d446 100644 --- a/support/src/utils/common.cpp +++ b/support/src/utils/common.cpp @@ -21,7 +21,6 @@ */ #include "utils/common.hpp" -#include "utils/path.hpp" #include "utils/string.hpp" namespace repertory::utils { diff --git a/repertory/librepertory/src/utils/encrypting_reader.cpp b/support/src/utils/encrypting_reader.cpp similarity index 83% rename from repertory/librepertory/src/utils/encrypting_reader.cpp rename to support/src/utils/encrypting_reader.cpp index c61e2610..b8df9ef5 100644 --- a/repertory/librepertory/src/utils/encrypting_reader.cpp +++ b/support/src/utils/encrypting_reader.cpp @@ -1,405 +1,397 @@ -/* - Copyright <2018-2024> - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ -#include "utils/encrypting_reader.hpp" - -#include "platform/platform.hpp" -#include "types/repertory.hpp" -#include "utils/collection.hpp" -#include "utils/common.hpp" -#include "utils/error_utils.hpp" -#include "utils/file.hpp" - -namespace repertory::utils::encryption { -class encrypting_streambuf final : public encrypting_reader::streambuf { -public: - encrypting_streambuf(const encrypting_streambuf &) = default; - encrypting_streambuf(encrypting_streambuf &&) = delete; - auto - operator=(const encrypting_streambuf &) -> encrypting_streambuf & = delete; - auto operator=(encrypting_streambuf &&) -> encrypting_streambuf & = delete; - - explicit encrypting_streambuf(const encrypting_reader &reader) - : reader_(reader) { - setg(reinterpret_cast(0), reinterpret_cast(0), - reinterpret_cast(reader_.get_total_size())); - } - - ~encrypting_streambuf() override = default; - -private: - encrypting_reader reader_; - -protected: - auto seekoff(off_type off, std::ios_base::seekdir dir, - std::ios_base::openmode which = std::ios_base::out | - std::ios_base::in) - -> pos_type override { - if ((which & std::ios_base::in) != std::ios_base::in) { - throw std::runtime_error("output is not supported"); - } - - const auto set_position = [this](char *next) -> pos_type { - if ((next <= egptr()) && (next >= eback())) { - setg(eback(), next, reinterpret_cast(reader_.get_total_size())); - return static_cast( - reinterpret_cast(gptr())); - } - - return {traits_type::eof()}; - }; - - switch (dir) { - case std::ios_base::beg: - return set_position(eback() + off); - - case std::ios_base::cur: - return set_position(gptr() + off); - - case std::ios_base::end: - return set_position(egptr() + off); - } - - return encrypting_reader::streambuf::seekoff(off, dir, which); - } - - auto seekpos(pos_type pos, std::ios_base::openmode which = - std::ios_base::out | - std::ios_base::in) -> pos_type override { - return seekoff(pos, std::ios_base::beg, which); - } - - auto uflow() -> int_type override { - auto ret = underflow(); - if (ret == traits_type::eof()) { - return ret; - } - - gbump(1); - - return ret; - } - - auto underflow() -> int_type override { - if (gptr() == egptr()) { - return traits_type::eof(); - } - - reader_.set_read_position(reinterpret_cast(gptr())); - - char c{}; - const auto res = encrypting_reader::reader_function(&c, 1U, 1U, &reader_); - if (res != 1) { - return traits_type::eof(); - } - - return c; - } - - auto xsgetn(char *ptr, std::streamsize count) -> std::streamsize override { - if (gptr() == egptr()) { - return traits_type::eof(); - } - - reader_.set_read_position(reinterpret_cast(gptr())); - - const auto res = encrypting_reader::reader_function( - ptr, 1U, static_cast(count), &reader_); - if ((res == reader_.get_error_return()) || - (reader_.get_stop_requested() && (res == CURL_READFUNC_ABORT))) { - return traits_type::eof(); - } - - setg(eback(), gptr() + res, - reinterpret_cast(reader_.get_total_size())); - return static_cast(res); - } -}; - -class encrypting_reader_iostream final : public encrypting_reader::iostream { -public: - encrypting_reader_iostream(const encrypting_reader_iostream &) = delete; - encrypting_reader_iostream(encrypting_reader_iostream &&) = delete; - - auto operator=(const encrypting_reader_iostream &) - -> encrypting_reader_iostream & = delete; - auto operator=(encrypting_reader_iostream &&) - -> encrypting_reader_iostream & = delete; - - explicit encrypting_reader_iostream( - std::unique_ptr buffer) - : encrypting_reader::iostream(buffer.get()), buffer_(std::move(buffer)) {} - - ~encrypting_reader_iostream() override = default; - -private: - std::unique_ptr buffer_; -}; - -const std::size_t encrypting_reader::header_size_ = ([]() { - return crypto_aead_xchacha20poly1305_IETF_NPUBBYTES + - crypto_aead_xchacha20poly1305_IETF_ABYTES; -})(); -const std::size_t encrypting_reader::data_chunk_size_ = (8UL * 1024UL * 1024UL); -const std::size_t encrypting_reader::encrypted_chunk_size_ = - data_chunk_size_ + header_size_; - -encrypting_reader::encrypting_reader( - std::string_view file_name, std::string_view source_path, - stop_type &stop_requested, std::string_view token, - std::optional relative_parent_path, - std::size_t error_return) - : key_(utils::encryption::generate_key( - token)), - stop_requested_(stop_requested), - error_return_(error_return) { - const auto res = native_file::create_or_open(source_path, true, source_file_); - if (res != api_error::success) { - throw std::runtime_error("file open failed|src|" + - std::string{source_path} + '|' + - api_error_to_string(res)); - } - - data_buffer result; - utils::encryption::encrypt_data( - key_, reinterpret_cast(file_name.data()), - file_name.size(), result); - encrypted_file_name_ = utils::collection::to_hex_string(result); - - if (relative_parent_path.has_value()) { - for (auto &&part : std::filesystem::path(relative_parent_path.value())) { - utils::encryption::encrypt_data( - key_, reinterpret_cast(part.string().c_str()), - strnlen(part.string().c_str(), part.string().size()), result); - encrypted_file_path_ += '/' + utils::collection::to_hex_string(result); - } - encrypted_file_path_ += '/' + encrypted_file_name_; - } - - std::uint64_t file_size{}; - if (not utils::file::get_file_size(source_path, file_size)) { - throw std::runtime_error("get file size failed|src|" + - std::string{source_path} + '|' + - std::to_string(utils::get_last_error_code())); - } - - const auto total_chunks = utils::divide_with_ceiling( - file_size, static_cast(data_chunk_size_)); - total_size_ = file_size + (total_chunks * encryption_header_size); - last_data_chunk_ = total_chunks - 1U; - last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size - : (file_size % data_chunk_size_) == 0U - ? data_chunk_size_ - : file_size % data_chunk_size_; - iv_list_.resize(total_chunks); - for (auto &iv : iv_list_) { - randombytes_buf(iv.data(), iv.size()); - } -} - -encrypting_reader::encrypting_reader(std::string_view encrypted_file_path, - std::string_view source_path, - stop_type &stop_requested, - std::string_view token, - std::size_t error_return) - : key_(utils::encryption::generate_key( - token)), - stop_requested_(stop_requested), - error_return_(error_return) { - const auto res = native_file::create_or_open(source_path, true, source_file_); - if (res != api_error::success) { - throw std::runtime_error("file open failed|src|" + - std::string{source_path} + '|' + - api_error_to_string(res)); - } - - encrypted_file_path_ = encrypted_file_path; - encrypted_file_name_ = - std::filesystem::path(encrypted_file_path_).filename().string(); - - std::uint64_t file_size{}; - if (not utils::file::get_file_size(source_path, file_size)) { - throw std::runtime_error("get file size failed|src|" + - std::string{source_path} + '|' + - std::to_string(utils::get_last_error_code())); - } - - const auto total_chunks = utils::divide_with_ceiling( - file_size, static_cast(data_chunk_size_)); - total_size_ = file_size + (total_chunks * encryption_header_size); - last_data_chunk_ = total_chunks - 1U; - last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size - : (file_size % data_chunk_size_) == 0U - ? data_chunk_size_ - : file_size % data_chunk_size_; - iv_list_.resize(total_chunks); - for (auto &iv : iv_list_) { - randombytes_buf(iv.data(), iv.size()); - } -} - -encrypting_reader::encrypting_reader( - std::string_view encrypted_file_path, std::string_view source_path, - stop_type &stop_requested, std::string_view token, - std::vector< - std::array> - iv_list, - std::size_t error_return) - : key_(utils::encryption::generate_key( - token)), - stop_requested_(stop_requested), - error_return_(error_return) { - const auto res = native_file::create_or_open(source_path, true, source_file_); - if (res != api_error::success) { - throw std::runtime_error("file open failed|src|" + - std::string{source_path} + '|' + - api_error_to_string(res)); - } - - encrypted_file_path_ = encrypted_file_path; - encrypted_file_name_ = - std::filesystem::path(encrypted_file_path_).filename().string(); - - std::uint64_t file_size{}; - if (not utils::file::get_file_size(source_path, file_size)) { - throw std::runtime_error("get file size failed|src|" + - std::string{source_path} + '|' + - std::to_string(utils::get_last_error_code())); - } - - const auto total_chunks = utils::divide_with_ceiling( - file_size, static_cast(data_chunk_size_)); - total_size_ = file_size + (total_chunks * encryption_header_size); - last_data_chunk_ = total_chunks - 1U; - last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size - : (file_size % data_chunk_size_) == 0U - ? data_chunk_size_ - : file_size % data_chunk_size_; - iv_list_ = std::move(iv_list); -} - -encrypting_reader::encrypting_reader(const encrypting_reader &reader) - : key_(reader.key_), - stop_requested_(reader.stop_requested_), - error_return_(reader.error_return_), - chunk_buffers_(reader.chunk_buffers_), - encrypted_file_name_(reader.encrypted_file_name_), - encrypted_file_path_(reader.encrypted_file_path_), - iv_list_(reader.iv_list_), - last_data_chunk_(reader.last_data_chunk_), - last_data_chunk_size_(reader.last_data_chunk_size_), - read_offset_(reader.read_offset_), - source_file_(native_file::clone(reader.source_file_)), - total_size_(reader.total_size_) {} - -encrypting_reader::~encrypting_reader() { - if (source_file_) { - source_file_->close(); - } -} - -auto encrypting_reader::calculate_decrypted_size(std::uint64_t total_size) - -> std::uint64_t { - return total_size - (utils::divide_with_ceiling( - total_size, static_cast( - get_encrypted_chunk_size())) * - encryption_header_size); -} - -auto encrypting_reader::calculate_encrypted_size(std::string_view source_path) - -> std::uint64_t { - std::uint64_t file_size{}; - if (not utils::file::get_file_size(source_path, file_size)) { - throw std::runtime_error("get file size failed|src|" + - std::string{source_path} + '|' + - std::to_string(utils::get_last_error_code())); - } - - const auto total_chunks = utils::divide_with_ceiling( - file_size, static_cast(data_chunk_size_)); - return file_size + (total_chunks * encryption_header_size); -} - -auto encrypting_reader::create_iostream() const - -> std::shared_ptr { - return std::make_shared( - std::make_unique(*this)); -} - -auto encrypting_reader::reader_function(char *buffer, size_t size, - size_t nitems) -> size_t { - static constexpr const std::string_view function_name{ - static_cast(__FUNCTION__), - }; - - const auto read_size = static_cast(std::min( - static_cast(size * nitems), total_size_ - read_offset_)); - - auto chunk = read_offset_ / encrypted_chunk_size_; - auto chunk_offset = read_offset_ % encrypted_chunk_size_; - std::size_t total_read{}; - - auto ret = false; - if (read_offset_ < total_size_) { - try { - ret = true; - auto remain = read_size; - while (not stop_requested_ && ret && (remain != 0U)) { - if (chunk_buffers_.find(chunk) == chunk_buffers_.end()) { - auto &chunk_buffer = chunk_buffers_[chunk]; - data_buffer file_data(chunk == last_data_chunk_ - ? last_data_chunk_size_ - : data_chunk_size_); - chunk_buffer.resize(file_data.size() + encryption_header_size); - - std::size_t bytes_read{}; - if ((ret = source_file_->read_bytes(&file_data[0u], file_data.size(), - chunk * data_chunk_size_, - bytes_read))) { - utils::encryption::encrypt_data(iv_list_.at(chunk), key_, file_data, - chunk_buffer); - } - } else if (chunk) { - chunk_buffers_.erase(chunk - 1u); - } - - auto &chunk_buffer = chunk_buffers_[chunk]; - const auto to_read = std::min( - static_cast(chunk_buffer.size() - chunk_offset), - remain); - std::memcpy(buffer + total_read, &chunk_buffer[chunk_offset], to_read); - total_read += to_read; - remain -= to_read; - chunk_offset = 0u; - chunk++; - read_offset_ += to_read; - } - } catch (const std::exception &e) { - utils::error::raise_error(function_name, e, "exception occurred"); - ret = false; - } - } - - return stop_requested_ ? CURL_READFUNC_ABORT - : ret ? total_read - : error_return_; -} -} // namespace repertory::utils::encryption +/* + Copyright <2018-2024> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#include "utils/encrypting_reader.hpp" + +#include "utils/collection.hpp" +#include "utils/common.hpp" +#include "utils/encryption.hpp" +#include "utils/error.hpp" +#include "utils/unix.hpp" +#include "utils/windows.hpp" + +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) + +#if !defined(CURL_READFUNC_ABORT) +#define CURL_READFUNC_ABORT (-1) +#endif // !defined(CURL_READFUNC_ABORT) + +namespace repertory::utils::encryption { +class encrypting_streambuf final : public encrypting_reader::streambuf { +public: + encrypting_streambuf(const encrypting_streambuf &) = default; + encrypting_streambuf(encrypting_streambuf &&) = delete; + auto + operator=(const encrypting_streambuf &) -> encrypting_streambuf & = delete; + auto operator=(encrypting_streambuf &&) -> encrypting_streambuf & = delete; + + explicit encrypting_streambuf(const encrypting_reader &reader) + : reader_(reader) { + setg(reinterpret_cast(0), reinterpret_cast(0), + reinterpret_cast(reader_.get_total_size())); + } + + ~encrypting_streambuf() override = default; + +private: + encrypting_reader reader_; + +protected: + auto seekoff(off_type off, std::ios_base::seekdir dir, + std::ios_base::openmode which = std::ios_base::out | + std::ios_base::in) + -> pos_type override { + if ((which & std::ios_base::in) != std::ios_base::in) { + throw std::runtime_error("output is not supported"); + } + + const auto set_position = [this](char *next) -> pos_type { + if ((next <= egptr()) && (next >= eback())) { + setg(eback(), next, reinterpret_cast(reader_.get_total_size())); + return static_cast( + reinterpret_cast(gptr())); + } + + return {traits_type::eof()}; + }; + + switch (dir) { + case std::ios_base::beg: + return set_position(eback() + off); + + case std::ios_base::cur: + return set_position(gptr() + off); + + case std::ios_base::end: + return set_position(egptr() + off); + } + + return encrypting_reader::streambuf::seekoff(off, dir, which); + } + + auto seekpos(pos_type pos, std::ios_base::openmode which = + std::ios_base::out | + std::ios_base::in) -> pos_type override { + return seekoff(pos, std::ios_base::beg, which); + } + + auto uflow() -> int_type override { + auto ret = underflow(); + if (ret == traits_type::eof()) { + return ret; + } + + gbump(1); + + return ret; + } + + auto underflow() -> int_type override { + if (gptr() == egptr()) { + return traits_type::eof(); + } + + reader_.set_read_position(reinterpret_cast(gptr())); + + char c{}; + const auto res = encrypting_reader::reader_function(&c, 1U, 1U, &reader_); + if (res != 1) { + return traits_type::eof(); + } + + return c; + } + + auto xsgetn(char *ptr, std::streamsize count) -> std::streamsize override { + if (gptr() == egptr()) { + return traits_type::eof(); + } + + reader_.set_read_position(reinterpret_cast(gptr())); + + const auto res = encrypting_reader::reader_function( + ptr, 1U, static_cast(count), &reader_); + if ((res == reader_.get_error_return()) || + (reader_.get_stop_requested() && (res == CURL_READFUNC_ABORT))) { + return traits_type::eof(); + } + + setg(eback(), gptr() + res, + reinterpret_cast(reader_.get_total_size())); + return static_cast(res); + } +}; + +class encrypting_reader_iostream final : public encrypting_reader::iostream { +public: + encrypting_reader_iostream(const encrypting_reader_iostream &) = delete; + encrypting_reader_iostream(encrypting_reader_iostream &&) = delete; + + auto operator=(const encrypting_reader_iostream &) + -> encrypting_reader_iostream & = delete; + auto operator=(encrypting_reader_iostream &&) + -> encrypting_reader_iostream & = delete; + + explicit encrypting_reader_iostream( + std::unique_ptr buffer) + : encrypting_reader::iostream(buffer.get()), buffer_(std::move(buffer)) {} + + ~encrypting_reader_iostream() override = default; + +private: + std::unique_ptr buffer_; +}; + +const std::size_t encrypting_reader::header_size_ = ([]() { + return crypto_aead_xchacha20poly1305_IETF_NPUBBYTES + + crypto_aead_xchacha20poly1305_IETF_ABYTES; +})(); +const std::size_t encrypting_reader::data_chunk_size_ = (8UL * 1024UL * 1024UL); +const std::size_t encrypting_reader::encrypted_chunk_size_ = + data_chunk_size_ + header_size_; + +encrypting_reader::encrypting_reader( + std::string_view file_name, std::string_view source_path, + stop_type &stop_requested, std::string_view token, + std::optional relative_parent_path, + std::size_t error_return) + : key_(utils::encryption::generate_key( + token)), + stop_requested_(stop_requested), + error_return_(error_return), + source_file_(utils::file::file::open_or_create_file(source_path)) { + if (not source_file_) { + throw std::runtime_error("file open failed|src|" + + std::string{source_path}); + } + + data_buffer result; + utils::encryption::encrypt_data( + key_, reinterpret_cast(file_name.data()), + file_name.size(), result); + encrypted_file_name_ = utils::collection::to_hex_string(result); + + if (relative_parent_path.has_value()) { + for (auto &&part : std::filesystem::path(relative_parent_path.value())) { + utils::encryption::encrypt_data( + key_, reinterpret_cast(part.string().c_str()), + strnlen(part.string().c_str(), part.string().size()), result); + encrypted_file_path_ += '/' + utils::collection::to_hex_string(result); + } + encrypted_file_path_ += '/' + encrypted_file_name_; + } + + auto file_size = source_file_.size(); + + const auto total_chunks = utils::divide_with_ceiling( + file_size, static_cast(data_chunk_size_)); + total_size_ = file_size + (total_chunks * encryption_header_size); + last_data_chunk_ = total_chunks - 1U; + last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size + : (file_size % data_chunk_size_) == 0U + ? data_chunk_size_ + : file_size % data_chunk_size_; + iv_list_.resize(total_chunks); + for (auto &iv : iv_list_) { + randombytes_buf(iv.data(), iv.size()); + } +} + +encrypting_reader::encrypting_reader(std::string_view encrypted_file_path, + std::string_view source_path, + stop_type &stop_requested, + std::string_view token, + std::size_t error_return) + : key_(utils::encryption::generate_key( + token)), + stop_requested_(stop_requested), + error_return_(error_return), + source_file_(utils::file::file::open_or_create_file(source_path)) { + if (not source_file_) { + throw std::runtime_error("file open failed|src|" + + std::string{source_path}); + } + + encrypted_file_path_ = encrypted_file_path; + encrypted_file_name_ = + std::filesystem::path(encrypted_file_path_).filename().string(); + + auto file_size = source_file_.size(); + + const auto total_chunks = utils::divide_with_ceiling( + file_size, static_cast(data_chunk_size_)); + total_size_ = file_size + (total_chunks * encryption_header_size); + last_data_chunk_ = total_chunks - 1U; + last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size + : (file_size % data_chunk_size_) == 0U + ? data_chunk_size_ + : file_size % data_chunk_size_; + iv_list_.resize(total_chunks); + for (auto &iv : iv_list_) { + randombytes_buf(iv.data(), iv.size()); + } +} + +encrypting_reader::encrypting_reader( + std::string_view encrypted_file_path, std::string_view source_path, + stop_type &stop_requested, std::string_view token, + std::vector< + std::array> + iv_list, + std::size_t error_return) + : key_(utils::encryption::generate_key( + token)), + stop_requested_(stop_requested), + error_return_(error_return), + source_file_(utils::file::file::open_or_create_file(source_path)) { + if (not source_file_) { + throw std::runtime_error("file open failed|src|" + + std::string{source_path}); + } + + encrypted_file_path_ = encrypted_file_path; + encrypted_file_name_ = + std::filesystem::path(encrypted_file_path_).filename().string(); + + auto file_size = source_file_.size(); + + const auto total_chunks = utils::divide_with_ceiling( + file_size, static_cast(data_chunk_size_)); + total_size_ = file_size + (total_chunks * encryption_header_size); + last_data_chunk_ = total_chunks - 1U; + last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size + : (file_size % data_chunk_size_) == 0U + ? data_chunk_size_ + : file_size % data_chunk_size_; + iv_list_ = std::move(iv_list); +} + +encrypting_reader::encrypting_reader(const encrypting_reader &reader) + : key_(reader.key_), + stop_requested_(reader.stop_requested_), + error_return_(reader.error_return_), + source_file_( + utils::file::file::open_file(reader.source_file_.get_path())), + chunk_buffers_(reader.chunk_buffers_), + encrypted_file_name_(reader.encrypted_file_name_), + encrypted_file_path_(reader.encrypted_file_path_), + iv_list_(reader.iv_list_), + last_data_chunk_(reader.last_data_chunk_), + last_data_chunk_size_(reader.last_data_chunk_size_), + read_offset_(reader.read_offset_), + total_size_(reader.total_size_) { + if (not source_file_) { + throw std::runtime_error("file open failed|src|" + + source_file_.get_path().string()); + } +} + +auto encrypting_reader::calculate_decrypted_size(std::uint64_t total_size) + -> std::uint64_t { + return total_size - (utils::divide_with_ceiling( + total_size, static_cast( + get_encrypted_chunk_size())) * + encryption_header_size); +} + +auto encrypting_reader::calculate_encrypted_size(std::string_view source_path) + -> std::uint64_t { + std::uint64_t file_size{}; + if (not utils::file::get_file_size(source_path, file_size)) { + throw std::runtime_error("get file size failed|src|" + + std::string{source_path} + '|' + + std::to_string(utils::get_last_error_code())); + } + + const auto total_chunks = utils::divide_with_ceiling( + file_size, static_cast(data_chunk_size_)); + return file_size + (total_chunks * encryption_header_size); +} + +auto encrypting_reader::create_iostream() const + -> std::shared_ptr { + return std::make_shared( + std::make_unique(*this)); +} + +auto encrypting_reader::reader_function(char *buffer, size_t size, + size_t nitems) -> size_t { + static constexpr const std::string_view function_name{ + static_cast(__FUNCTION__), + }; + + const auto read_size = static_cast(std::min( + static_cast(size * nitems), total_size_ - read_offset_)); + + auto chunk = read_offset_ / encrypted_chunk_size_; + auto chunk_offset = read_offset_ % encrypted_chunk_size_; + std::size_t total_read{}; + + auto ret = false; + if (read_offset_ < total_size_) { + try { + ret = true; + auto remain = read_size; + while (not stop_requested_ && ret && (remain != 0U)) { + if (chunk_buffers_.find(chunk) == chunk_buffers_.end()) { + auto &chunk_buffer = chunk_buffers_[chunk]; + data_buffer file_data(chunk == last_data_chunk_ + ? last_data_chunk_size_ + : data_chunk_size_); + chunk_buffer.resize(file_data.size() + encryption_header_size); + + std::size_t bytes_read{}; + if ((ret = source_file_.read(file_data, chunk * data_chunk_size_, + &bytes_read))) { + utils::encryption::encrypt_data(iv_list_.at(chunk), key_, file_data, + chunk_buffer); + } + } else if (chunk) { + chunk_buffers_.erase(chunk - 1u); + } + + auto &chunk_buffer = chunk_buffers_[chunk]; + const auto to_read = std::min( + static_cast(chunk_buffer.size() - chunk_offset), + remain); + std::memcpy(buffer + total_read, &chunk_buffer[chunk_offset], to_read); + total_read += to_read; + remain -= to_read; + chunk_offset = 0u; + chunk++; + read_offset_ += to_read; + } + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + ret = false; + } catch (...) { + utils::error::handle_exception(function_name); + ret = false; + } + } + + return stop_requested_ ? CURL_READFUNC_ABORT + : ret ? total_read + : error_return_; +} +} // namespace repertory::utils::encryption + +#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) diff --git a/support/src/utils/file.cpp b/support/src/utils/file.cpp index 1657e842..4f5b1b03 100644 --- a/support/src/utils/file.cpp +++ b/support/src/utils/file.cpp @@ -27,184 +27,12 @@ #include "utils/string.hpp" namespace repertory::utils::file { -auto file::open_file(std::filesystem::path path) -> file { - path = utils::path::absolute(path.string()); - if (not is_file(path.string())) { - throw std::runtime_error("file not found: " + path.string()); - } - - auto stream = std::fstream{ - path, - std::ios_base::binary | std::ios_base::in | std::ios_base::out, - }; - return { - std::move(stream), - path, - }; -} - -auto file::open_or_create_file(std::filesystem::path path) -> file { - path = utils::path::absolute(path.string()); - auto stream = std::fstream{ - path.string().c_str(), - std::ios_base::binary | std::ios_base::trunc | std::ios_base::in | - std::ios_base::out, - }; - - return { - std::move(stream), - path, - }; -} - -void file::close() { - if (stream_.is_open()) { - stream_.close(); - } -} - -auto file::move_to(std::filesystem::path new_path) -> bool { - new_path = utils::path::absolute(new_path.string()); - - auto reopen{false}; - if (stream_.is_open()) { - reopen = true; - close(); - } - - std::filesystem::rename(path_, new_path, error_); - if (not error_) { - path_ = new_path; - if (reopen) { - *this = open_file(path_); - } - return true; - } - - if (reopen) { - *this = open_file(path_); - } - return false; -} - -auto file::read_(unsigned char *data, std::size_t to_read, std::uint64_t offset, - std::size_t *total_read) -> bool { - static constexpr const std::string_view function_name{ - static_cast(__FUNCTION__), - }; - - if (total_read != nullptr) { - (*total_read) = 0U; - } - - try { - stream_.seekg(static_cast(offset)); - - auto before = stream_.tellg(); - if (before == -1) { - throw std::runtime_error("failed to tellg() before read"); - } - - stream_.read(reinterpret_cast(data), - static_cast(to_read)); - if (total_read != nullptr) { - auto after = stream_.tellg(); - if (after >= 0) { - (*total_read) = static_cast(after - before); - } else if (after == -1 && not stream_.eof()) { - throw std::runtime_error("failed to tellg() after read"); - } - } - - return true; - } catch (const std::exception &e) { - utils::error::handle_exception(function_name, e); - } catch (...) { - utils::error::handle_exception(function_name); - } - - return false; -} - -auto file::remove() -> bool { - close(); - return std::filesystem::remove(path_, error_); -} - -auto file::truncate(std::size_t size) -> bool { - auto reopen{false}; - if (stream_.is_open()) { - reopen = true; - close(); - } - - std::filesystem::resize_file(path_, size, error_); - if (reopen) { - *this = open_file(path_); - } - - return not error_; -} - -auto file::write_(const unsigned char *data, std::size_t to_write, - std::size_t offset, std::size_t *total_written) -> bool { - static constexpr const std::string_view function_name{ - static_cast(__FUNCTION__), - }; - - if (total_written != nullptr) { - (*total_written) = 0U; - } - - try { - stream_.seekp(static_cast(offset)); - auto before = stream_.tellp(); - if (before == -1) { - throw std::runtime_error("failed to tellp() before write"); - } - - stream_.write(reinterpret_cast(data), - static_cast(to_write)); - - auto after = stream_.tellp(); - if (after == -1) { - throw std::runtime_error("failed to tellp() after write"); - } - - if (total_written != nullptr) { - (*total_written) = static_cast(after - before); - } - - return true; - } catch (const std::exception &e) { - utils::error::handle_exception(function_name, e); - } catch (...) { - utils::error::handle_exception(function_name); - } - - return false; -} - auto get_file_size(std::string_view path, std::uint64_t &file_size) -> bool { auto abs_path = utils::path::absolute(path); - file_size = 0U; - -#if defined(_WIN32) - struct _stat64 st {}; - if (_stat64(abs_path.c_str(), &st) != 0) { -#else // !defined(_WIN32) - struct stat st {}; - if (stat(abs_path.c_str(), &st) != 0) { -#endif // defined(_WIN32) - return false; - } - - if (st.st_size >= 0) { - file_size = static_cast(st.st_size); - } - - return (st.st_size >= 0); + std::error_code ec{}; + file_size = std::filesystem::file_size(abs_path, ec); + return ec.value() == 0; } auto get_file_size(std::wstring_view path, std::uint64_t &file_size) -> bool { @@ -255,44 +83,42 @@ auto read_json_file(std::string_view path, nlohmann::json &data) -> bool { try { auto abs_path = utils::path::absolute(path); - if (not is_file(abs_path)) { - return true; + auto file = file::open_file(abs_path); + if (not file) { + return false; } - std::ifstream file_stream{ - abs_path.c_str(), - std::ios_base::binary | std::ios::in, - }; - if (not file_stream.is_open()) { - throw std::runtime_error("failed to open file: " + abs_path); - } - - auto ret{true}; try { - std::stringstream stream; - stream << file_stream.rdbuf(); + data_buffer buffer{}; + if (not file.read_all(buffer, 0U)) { + return false; + } - auto json_text = stream.str(); #if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) if (password.has_value()) { - auto decrypted_data = - utils::encryption::decrypt_data(*password, json_text); - json_text = {decrypted_data.begin(), decrypted_data.end()}; + data_buffer decrypted_data{}; + if (not utils::encryption::decrypt_data(*password, buffer, + decrypted_data)) { + return false; + } + + buffer = decrypted_data; } #endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - if (not json_text.empty()) { - data = nlohmann::json::parse(json_text.c_str()); + + std::string json_str(buffer.begin(), buffer.end()); + if (not json_str.empty()) { + data = nlohmann::json::parse(json_str); } } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); - ret = false; + return false; } catch (...) { utils::error::handle_exception(function_name); - ret = false; + return false; } - file_stream.close(); - return ret; + return true; } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { @@ -316,18 +142,22 @@ auto write_json_file(std::string_view path, try { auto file = file::open_or_create_file(path); if (not file.truncate()) { - throw std::runtime_error("failed to truncate file: " + - file.get_error_code().message()); + throw std::runtime_error("failed to truncate file"); } #if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) if (password.has_value()) { - return file.write(utils::encryption::encrypt_data(*password, data.dump()), - 0U); + const auto str_data = data.dump(); + + data_buffer encrypted_data{}; + utils::encryption::encrypt_data( + *password, reinterpret_cast(str_data.c_str()), + str_data.size(), encrypted_data); + return file.write(encrypted_data, 0U); } #endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - return file.write(data, 0U); + return file.write(data.dump(), 0U); } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { diff --git a/support/src/utils/file_file.cpp b/support/src/utils/file_file.cpp new file mode 100644 index 00000000..0723696e --- /dev/null +++ b/support/src/utils/file_file.cpp @@ -0,0 +1,353 @@ +/* + Copyright <2018-2024> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#include "utils/file.hpp" + +#include "utils/encryption.hpp" +#include "utils/error.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" + +namespace repertory::utils::file { +auto file::open_file(std::filesystem::path path, bool read_only) -> file { + path = utils::path::absolute(path.string()); + if (not is_file(path.string())) { + throw std::runtime_error("file not found: " + path.string()); + } + + if (not read_only) { +#if defined(_WIN32) + _chmod(path.string().c_str(), 0600U); +#else // !defined(_WIN32) + chmod(path.string().c_str(), 0600U); +#endif // defined(_WIN32) + } + +#if defined(_WIN32) + auto *ptr = + _fsopen(path.string().c_str(), read_only ? "rb" : "rb+", _SH_DENYNO); + std::cout << errno << std::endl; +#else // !defined(_WIN32) + auto *ptr = fopen(path.string().c_str(), read_only ? "rb" : "rb+"); +#endif // defined(_WIN32) + + return file{ + file_t{ptr}, + path, + }; +} + +auto file::open_or_create_file(std::filesystem::path path, + bool read_only) -> file { + path = utils::path::absolute(path.string()); + +#if defined(_WIN32) + int old_mode{}; + _umask_s(0600U, &old_mode); +#else // !defined(_WIN32) + auto old_mode = umask(0600U); +#endif // defined(_WIN32) + +#if defined(_WIN32) + auto *ptr = _fsopen(path.string().c_str(), "ab+", _SH_DENYNO); +#else // !defined(_WIN32) + auto *ptr = fopen(path.string().c_str(), "ab+"); +#endif // defined(_WIN32) + +#if defined(_WIN32) + _umask_s(old_mode, nullptr); +#else // !defined(_WIN32) + umask(old_mode); +#endif // defined(_WIN32) + + if (ptr != nullptr) { + fclose(ptr); + } + + return open_file(path, read_only); +} + +void file::close() { +#if defined(_WIN32) + recur_mutex_lock lock{mtx_}; +#endif // defined(_WIN32) + + file_.reset(); +} + +void file::flush() { +#if defined(_WIN32) + recur_mutex_lock lock{mtx_}; +#endif // defined(_WIN32) + + if (file_) { + fflush(file_.get()); + } +} + +auto file::get_handle() const -> native_handle { + if (file_) { +#if defined(_WIN32) + return reinterpret_cast( + _get_osfhandle(_fileno(file_.get()))); +#else // !defined(_WIN32) + return fileno(file_.get()); +#endif // defined(_WIN32) + } + + return INVALID_HANDLE_VALUE; +} + +auto file::move_to(std::filesystem::path new_path) -> bool { +#if defined(_WIN32) + recur_mutex_lock lock{mtx_}; +#endif // defined(_WIN32) + + new_path = utils::path::absolute(new_path.string()); + + auto reopen{false}; + if (file_) { + reopen = true; + close(); + } + + std::error_code ec{}; + std::filesystem::rename(path_, new_path, ec); + if (not ec) { + path_ = new_path; + if (reopen) { + *this = open_file(path_); + } + + return true; + } + + if (reopen) { + *this = open_file(path_); + } + + return false; +} + +auto file::read_all(data_buffer &data, std::uint64_t offset, + std::size_t *total_read) -> bool { +#if defined(_WIN32) + recur_mutex_lock lock{mtx_}; +#endif // defined(_WIN32) + + data_buffer buffer; + buffer.resize(65536U); + + std::size_t current_read{}; + while (read(reinterpret_cast(buffer.data()), + buffer.size() * sizeof(data_buffer::value_type), offset, + ¤t_read)) { + if (total_read != nullptr) { + *total_read += current_read; + } + + if (current_read != 0U) { + offset += current_read; + + data.insert( + data.end(), buffer.begin(), + std::next(buffer.begin(), + static_cast( + current_read / sizeof(data_buffer::value_type)))); + continue; + } + + return true; + } + + return false; +} + +auto file::read(data_buffer &data, std::uint64_t offset, + std::size_t *total_read) -> bool { +#if defined(_WIN32) + recur_mutex_lock lock{mtx_}; +#endif // defined(_WIN32) + + std::size_t bytes_read{}; + auto ret = + read(reinterpret_cast(data.data()), + data.size() * sizeof(data_buffer::value_type), offset, &bytes_read); + data.resize(bytes_read / sizeof(data_buffer::value_type)); + + if (total_read != nullptr) { + (*total_read) = bytes_read; + } + + return ret; +} + +auto file::read(unsigned char *data, std::size_t to_read, std::uint64_t offset, + std::size_t *total_read) -> bool { +#if defined(_WIN32) + recur_mutex_lock lock{mtx_}; +#endif // defined(_WIN32) + + static constexpr const std::string_view function_name{ + static_cast(__FUNCTION__), + }; + + if (total_read != nullptr) { + (*total_read) = 0U; + } + + try { + if (not file_) { + throw std::runtime_error("file is not open for reading"); + } + + auto res = fseeko(file_.get(), static_cast(offset), SEEK_SET); + if (res == -1) { + throw std::runtime_error("failed to seek before read"); + } + + auto bytes_read = fread(data, 1U, to_read, file_.get()); + if (not feof(file_.get()) && ferror(file_.get())) { + throw std::runtime_error("failed to read file bytes"); + } + + if (total_read != nullptr) { + (*total_read) = bytes_read; + } + + return true; + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); + } + + return false; +} + +auto file::remove() -> bool { +#if defined(_WIN32) + recur_mutex_lock lock{mtx_}; +#endif // defined(_WIN32) + + close(); + + std::error_code ec{}; + return std::filesystem::remove(path_, ec); +} + +auto file::truncate(std::size_t size) -> bool { +#if defined(_WIN32) + recur_mutex_lock lock{mtx_}; +#endif // defined(_WIN32) + + auto reopen{false}; + if (file_) { + reopen = true; + close(); + } + + std::error_code ec{}; + std::filesystem::resize_file(path_, size, ec); + if (reopen) { + *this = open_file(path_); + } + + return ec.value() == 0; +} + +auto file::write_(const unsigned char *data, std::size_t to_write, + std::size_t offset, std::size_t *total_written) -> bool { +#if defined(_WIN32) + recur_mutex_lock lock{mtx_}; +#endif // defined(_WIN32) + + static constexpr const std::string_view function_name{ + static_cast(__FUNCTION__), + }; + + if (total_written != nullptr) { + (*total_written) = 0U; + } + + try { + if (not file_) { + throw std::runtime_error("file is not open for writing"); + } + + auto res = fseeko(file_.get(), static_cast(offset), SEEK_SET); + if (res == -1) { + throw std::runtime_error("failed to seek before write"); + } + + auto bytes_written = + fwrite(reinterpret_cast(data), 1U, to_write, file_.get()); + if (not feof(file_.get()) && ferror(file_.get())) { + throw std::runtime_error("failed to read file bytes"); + } + + flush(); + + if (total_written != nullptr) { + (*total_written) = bytes_written; + } + + return true; + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); + } + + return false; +} + +auto file::size() const -> std::uint64_t { +#if defined(_WIN32) + recur_mutex_lock lock{mtx_}; +#endif // defined(_WIN32) + + static constexpr const std::string_view function_name{ + static_cast(__FUNCTION__), + }; + + try { + if (file_) { + if (fseeko(file_.get(), 0, SEEK_END) == -1) { + throw std::runtime_error("failed to seek"); + } + + auto size = ftello(file_.get()); + if (size == -1) { + throw std::runtime_error("failed to get position"); + } + + return static_cast(size); + } + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); + } + + return 0U; +} +} // namespace repertory::utils::file diff --git a/support/src/utils/hash.cpp b/support/src/utils/hash.cpp index 7cc2fe52..7b4895c8 100644 --- a/support/src/utils/hash.cpp +++ b/support/src/utils/hash.cpp @@ -23,47 +23,140 @@ #if defined(PROJECT_ENABLE_LIBSODIUM) -namespace {} // namespace - namespace repertory::utils::encryption { auto create_hash_blake2b_256(std::string_view data) -> hash_256_t { - return create_hash_blake2b_t(data); + return create_hash_blake2b_t( + reinterpret_cast(data.data()), data.size()); } auto create_hash_blake2b_256(std::wstring_view data) -> hash_256_t { - return create_hash_blake2b_t(data); + return create_hash_blake2b_t( + reinterpret_cast(data.data()), + data.size() * sizeof(wchar_t)); +} + +auto create_hash_blake2b_256(const data_buffer &data) -> hash_256_t { + return create_hash_blake2b_t( + reinterpret_cast(data.data()), + data.size() * sizeof(data_buffer::value_type)); } auto create_hash_blake2b_384(std::string_view data) -> hash_384_t { - return create_hash_blake2b_t(data); + return create_hash_blake2b_t( + reinterpret_cast(data.data()), data.size()); } auto create_hash_blake2b_384(std::wstring_view data) -> hash_384_t { - return create_hash_blake2b_t(data); + return create_hash_blake2b_t( + reinterpret_cast(data.data()), + data.size() * sizeof(wchar_t)); +} + +auto create_hash_blake2b_384(const data_buffer &data) -> hash_384_t { + return create_hash_blake2b_t( + reinterpret_cast(data.data()), + data.size() * sizeof(data_buffer::value_type)); } auto create_hash_blake2b_512(std::string_view data) -> hash_512_t { - return create_hash_blake2b_t(data); + return create_hash_blake2b_t( + reinterpret_cast(data.data()), data.size()); } auto create_hash_blake2b_512(std::wstring_view data) -> hash_512_t { - return create_hash_blake2b_t(data); + return create_hash_blake2b_t( + reinterpret_cast(data.data()), + data.size() * sizeof(wchar_t)); +} + +auto create_hash_blake2b_512(const data_buffer &data) -> hash_512_t { + return create_hash_blake2b_t( + reinterpret_cast(data.data()), + data.size() * sizeof(data_buffer::value_type)); } auto create_hash_sha256(std::string_view data) -> hash_256_t { - return create_hash_sha256_t(data); + return create_hash_sha256( + reinterpret_cast(data.data()), data.size()); } auto create_hash_sha256(std::wstring_view data) -> hash_256_t { - return create_hash_sha256_t(data); + return create_hash_sha256( + reinterpret_cast(data.data()), + data.size() * sizeof(wchar_t)); +} + +auto create_hash_sha256(const data_buffer &data) -> hash_256_t { + return create_hash_sha256( + reinterpret_cast(data.data()), + data.size() * sizeof(data_buffer::value_type)); } auto create_hash_sha512(std::string_view data) -> hash_512_t { - return create_hash_sha512_t(data); + return create_hash_sha512( + reinterpret_cast(data.data()), data.size()); } auto create_hash_sha512(std::wstring_view data) -> hash_512_t { - return create_hash_sha512_t(data); + return create_hash_sha512( + reinterpret_cast(data.data()), + data.size() * sizeof(wchar_t)); +} + +auto create_hash_sha512(const data_buffer &data) -> hash_512_t { + return create_hash_sha512( + reinterpret_cast(data.data()), + data.size() * sizeof(data_buffer::value_type)); +} + +auto create_hash_sha512(const unsigned char *data, + std::size_t data_size) -> hash_512_t { + hash_512_t hash{}; + + crypto_hash_sha512_state state{}; + auto res = crypto_hash_sha512_init(&state); + if (res != 0) { + throw std::runtime_error("failed to initialize sha-512|" + + std::to_string(res)); + } + + res = crypto_hash_sha512_update(&state, data, data_size); + if (res != 0) { + throw std::runtime_error("failed to update sha-512|" + std::to_string(res)); + } + + res = crypto_hash_sha512_final(&state, hash.data()); + if (res != 0) { + throw std::runtime_error("failed to finalize sha-512|" + + std::to_string(res)); + } + + return hash; +} + +auto create_hash_sha256(const unsigned char *data, + std::size_t data_size) -> hash_256_t { + hash_256_t hash{}; + + crypto_hash_sha256_state state{}; + auto res = crypto_hash_sha256_init(&state); + if (res != 0) { + throw std::runtime_error("failed to initialize sha-256|" + + std::to_string(res)); + } + + res = crypto_hash_sha256_update(&state, data, data_size); + if (res != 0) { + throw std::runtime_error("failed to update sha-256|" + std::to_string(res)); + } + + res = crypto_hash_sha256_final(&state, hash.data()); + if (res != 0) { + throw std::runtime_error("failed to finalize sha-256|" + + std::to_string(res)); + } + + return hash; } } // namespace repertory::utils::encryption diff --git a/support/src/utils/encryption.cpp b/support/test/include/test.hpp similarity index 53% rename from support/src/utils/encryption.cpp rename to support/test/include/test.hpp index cb146c69..8801c978 100644 --- a/support/src/utils/encryption.cpp +++ b/support/test/include/test.hpp @@ -19,36 +19,40 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "utils/encryption.hpp" +#ifndef REPERTORY_TEST_INCLUDE_TEST_HPP_ +#define REPERTORY_TEST_INCLUDE_TEST_HPP_ -#if defined(PROJECT_ENABLE_LIBSODIUM) -namespace repertory::utils::encryption { -#if defined(PROJECT_ENABLE_BOOST) -auto decrypt_data(std::string_view password, - std::string_view data) -> data_buffer { - auto key = generate_key(password); +#if defined(U) +#undef U +#endif // defined(U) - data_buffer buf{}; - if (not decrypt_data(key, - reinterpret_cast(data.data()), - data.size(), buf)) { - throw std::runtime_error("decryption failed"); - } +#include "gmock/gmock.h" +#include "gtest/gtest.h" - return buf; +using ::testing::_; +using namespace ::testing; + +#define COMMA , + +#include "utils/config.hpp" + +#include "utils/all.hpp" + +namespace repertory::test { +[[nodiscard]] auto create_random_file(std::size_t size) -> utils::file::file; + +[[nodiscard]] auto +generate_test_file_name(std::string_view file_name_no_extension) -> std::string; + +template +static void decrypt_and_verify(const buffer_t &buffer, std::string_view token, + result_t &result) { + EXPECT_TRUE(utils::encryption::decrypt_data(token, buffer, result)); } -auto encrypt_data(std::string_view password, - std::string_view data) -> data_buffer { - auto key = generate_key(password); +[[nodiscard]] auto get_test_input_dir() -> std::string; - data_buffer buf{}; - encrypt_data(key, reinterpret_cast(data.data()), - data.size(), buf); +[[nodiscard]] auto get_test_output_dir() -> std::string; +} // namespace repertory::test - return buf; -} -#endif // defined(PROJECT_ENABLE_BOOST) -} // namespace repertory::utils::encryption - -#endif // defined(PROJECT_ENABLE_LIBSODIUM) +#endif // REPERTORY_TEST_INCLUDE_TEST_HPP_ diff --git a/support/test/src/test.cpp b/support/test/src/test.cpp new file mode 100644 index 00000000..5d059d2a --- /dev/null +++ b/support/test/src/test.cpp @@ -0,0 +1,120 @@ +/* + Copyright <2018-2024> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#include "test.hpp" + +namespace { +static std::recursive_mutex file_mtx{}; + +static std::vector generated_files; + +static void delete_generated_files() { + repertory::recur_mutex_lock lock{file_mtx}; + std::optional parent_path; + for (auto &&path : generated_files) { + if (parent_path->empty()) { + parent_path = std::filesystem::path(path).parent_path().string(); + } + + std::error_code ec{}; + std::filesystem::remove(path, ec); + } + generated_files.clear(); + + if (parent_path.has_value()) { + std::error_code ec{}; + std::filesystem::remove_all(*parent_path, ec); + } +} + +struct file_deleter final { + ~file_deleter() { delete_generated_files(); } +}; + +static auto deleter{std::make_unique()}; +} // namespace + +namespace repertory::test { +auto create_random_file(std::size_t size) -> utils::file::file { + recur_mutex_lock lock{file_mtx}; + + auto path = generate_test_file_name("random"); + auto file = utils::file::file::open_or_create_file(path); + EXPECT_TRUE(file); + if (file) { + data_buffer buf(size); + randombytes_buf(buf.data(), buf.size()); + + std::size_t bytes_written{}; + EXPECT_TRUE(file.write(buf, 0U, &bytes_written)); + EXPECT_EQ(size, bytes_written); + + EXPECT_EQ(size, file.size()); + + generated_files.emplace_back(path); + } + + return file; +} + +auto generate_test_file_name(std::string_view file_name_no_extension) + -> std::string { + recur_mutex_lock lock{file_mtx}; + + auto path = utils::path::combine( + get_test_output_dir(), { + std::string{file_name_no_extension} + + std::to_string(generated_files.size()), + }); + generated_files.emplace_back(path); + return path; +} + +auto get_test_input_dir() -> std::string { + static auto test_path = ([]() -> std::string { + auto dir = utils::get_environment_variable("PROJECT_TEST_DIR"); + return utils::path::combine(dir.empty() ? "." : dir, {"test_config"}); + })(); + + return test_path; +} + +auto get_test_output_dir() -> std::string { + static auto test_path = ([]() -> std::string { + std::string name{"project_test_XXXXXX"}; + std::string temp{mktemp(name.data())}; + +#if defined(_WIN32) + auto path = utils::path::combine("%TEMP%", {temp}); +#else // !defined(_WIN32) + auto path = utils::path::combine("/tmp", {temp}); +#endif // defined(_WIN32) + + if (not utils::file::is_directory(path)) { + std::filesystem::create_directories(path); + } + + return path; + })(); + + return test_path; +} +} // namespace repertory::test diff --git a/support/test/src/utils/common_test.cpp b/support/test/src/utils/common_test.cpp index 0d1d822d..abb2ce54 100644 --- a/support/test/src/utils/common_test.cpp +++ b/support/test/src/utils/common_test.cpp @@ -19,12 +19,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "gtest/gtest.h" - -#include "utils/common.hpp" - -#include "utils/collection.hpp" -#include "utils/string.hpp" +#include "test.hpp" namespace repertory { TEST(utils_common, calculate_read_size) { @@ -298,7 +293,7 @@ TEST(utils_common, get_environment_variable) { #if defined(PROJECT_ENABLE_BOOST) TEST(utils_common, get_next_available_port) { std::uint16_t available_port{}; - for (std::uint16_t port = 1U; port < 65535; ++port) { + for (std::uint16_t port = 1025U; port < 1030U; ++port) { EXPECT_TRUE(utils::get_next_available_port(port, available_port)); EXPECT_GE(available_port, port); } diff --git a/support/test/src/utils/encrypting_reader_test.cpp b/support/test/src/utils/encrypting_reader_test.cpp new file mode 100644 index 00000000..536177b2 --- /dev/null +++ b/support/test/src/utils/encrypting_reader_test.cpp @@ -0,0 +1,224 @@ +/* + Copyright <2018-2024> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#include "test.hpp" + +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +namespace repertory { +TEST(utils_encrypting_reader, read_file_data) { + const auto token = std::string("moose"); + auto source_file = test::create_random_file( + 8U * utils::encryption::encrypting_reader::get_data_chunk_size()); + EXPECT_TRUE(source_file); + if (source_file) { + stop_type stop_requested{false}; + utils::encryption::encrypting_reader reader( + "test.dat", source_file.get_path().string(), stop_requested, token); + + for (std::uint8_t i = 0U; i < 8U; i++) { + data_buffer buffer( + utils::encryption::encrypting_reader::get_encrypted_chunk_size()); + for (std::uint8_t j = 0U; j < 2U; j++) { + ASSERT_EQ( + buffer.size() / 2U, + utils::encryption::encrypting_reader::reader_function( + reinterpret_cast(&buffer[(buffer.size() / 2U) * j]), + buffer.size() / 2U, 1U, &reader)); + } + + data_buffer decrypted_data; + EXPECT_TRUE( + utils::encryption::decrypt_data(token, buffer, decrypted_data)); + + EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(), + decrypted_data.size()); + + std::size_t bytes_read{}; + data_buffer file_data(decrypted_data.size()); + EXPECT_TRUE(source_file.read( + file_data, + utils::encryption::encrypting_reader::get_data_chunk_size() * i, + &bytes_read)); + EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(), + file_data.size())); + } + } +} + +TEST(utils_encrypting_reader, read_file_data_in_multiple_chunks) { + const auto token = std::string("moose"); + auto source_file = test::create_random_file( + 8U * utils::encryption::encrypting_reader::get_data_chunk_size()); + EXPECT_TRUE(source_file); + if (source_file) { + stop_type stop_requested{false}; + utils::encryption::encrypting_reader reader( + "test.dat", source_file.get_path().string(), stop_requested, token); + + for (std::uint8_t i = 0U; i < 8U; i += 2U) { + data_buffer buffer( + utils::encryption::encrypting_reader::get_encrypted_chunk_size() * + 2U); + EXPECT_EQ(buffer.size(), + utils::encryption::encrypting_reader::reader_function( + reinterpret_cast(buffer.data()), buffer.size(), 1U, + &reader)); + + for (std::uint8_t j = 0U; j < 2U; j++) { + data_buffer decrypted_data; + const auto offset = (j * (buffer.size() / 2U)); + EXPECT_TRUE(utils::encryption::decrypt_data( + token, + data_buffer( + std::next(buffer.begin(), static_cast(offset)), + std::next(buffer.begin(), static_cast( + offset + (buffer.size() / 2U)))), + decrypted_data)); + + EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(), + decrypted_data.size()); + + std::size_t bytes_read{}; + data_buffer file_data(decrypted_data.size()); + EXPECT_TRUE(source_file.read( + file_data, + (utils::encryption::encrypting_reader::get_data_chunk_size() * i) + + (j * + utils::encryption::encrypting_reader::get_data_chunk_size()), + &bytes_read)); + EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(), + file_data.size())); + } + } + } +} + +TEST(utils_encrypting_reader, read_file_data_as_stream) { + const auto token = std::string("moose"); + auto source_file = test::create_random_file( + 8U * utils::encryption::encrypting_reader::get_data_chunk_size()); + EXPECT_TRUE(source_file); + if (source_file) { + stop_type stop_requested{false}; + utils::encryption::encrypting_reader reader( + "test.dat", source_file.get_path().string(), stop_requested, token); + auto io_stream = reader.create_iostream(); + EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail()); + EXPECT_TRUE(io_stream->good()); + EXPECT_EQ(reader.get_total_size(), + static_cast(io_stream->tellg())); + EXPECT_FALSE(io_stream->seekg(0, std::ios_base::beg).fail()); + EXPECT_TRUE(io_stream->good()); + + for (std::uint8_t i = 0U; i < 8U; i++) { + data_buffer buffer( + utils::encryption::encrypting_reader::get_encrypted_chunk_size()); + EXPECT_FALSE( + io_stream->seekg(static_cast(i * buffer.size())) + .fail()); + EXPECT_TRUE(io_stream->good()); + for (std::uint8_t j = 0U; j < 2U; j++) { + EXPECT_FALSE( + io_stream + ->read( + reinterpret_cast(&buffer[(buffer.size() / 2U) * j]), + static_cast(buffer.size()) / 2U) + .fail()); + EXPECT_TRUE(io_stream->good()); + } + + data_buffer decrypted_data; + EXPECT_TRUE( + utils::encryption::decrypt_data(token, buffer, decrypted_data)); + + EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(), + decrypted_data.size()); + + std::size_t bytes_read{}; + data_buffer file_data(decrypted_data.size()); + EXPECT_TRUE(source_file.read( + file_data, + utils::encryption::encrypting_reader::get_data_chunk_size() * i, + &bytes_read)); + EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(), + file_data.size())); + } + } +} + +TEST(utils_encrypting_reader, read_file_data_in_multiple_chunks_as_stream) { + const auto token = std::string("moose"); + auto source_file = test::create_random_file( + 8u * utils::encryption::encrypting_reader::get_data_chunk_size()); + EXPECT_TRUE(source_file); + if (source_file) { + stop_type stop_requested{false}; + utils::encryption::encrypting_reader reader( + "test.dat", source_file.get_path().string(), stop_requested, token); + auto io_stream = reader.create_iostream(); + EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail()); + EXPECT_TRUE(io_stream->good()); + EXPECT_EQ(reader.get_total_size(), + static_cast(io_stream->tellg())); + EXPECT_FALSE(io_stream->seekg(0, std::ios_base::beg).fail()); + EXPECT_TRUE(io_stream->good()); + + for (std::uint8_t i = 0U; i < 8U; i += 2U) { + data_buffer buffer( + utils::encryption::encrypting_reader::get_encrypted_chunk_size() * + 2U); + EXPECT_FALSE(io_stream + ->read(reinterpret_cast(buffer.data()), + static_cast(buffer.size())) + .fail()); + EXPECT_TRUE(io_stream->good()); + + for (std::uint8_t j = 0U; j < 2U; j++) { + data_buffer decrypted_data; + const auto offset = (j * (buffer.size() / 2U)); + EXPECT_TRUE(utils::encryption::decrypt_data( + token, + data_buffer( + std::next(buffer.begin(), static_cast(offset)), + std::next(buffer.begin(), static_cast( + offset + (buffer.size() / 2U)))), + decrypted_data)); + + EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(), + decrypted_data.size()); + + std::size_t bytes_read{}; + data_buffer file_data(decrypted_data.size()); + EXPECT_TRUE(source_file.read( + file_data, + (utils::encryption::encrypting_reader::get_data_chunk_size() * i) + + (j * + utils::encryption::encrypting_reader::get_data_chunk_size()), + &bytes_read)); + EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(), + file_data.size())); + } + } + } +} +} // namespace repertory + +#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) diff --git a/support/test/src/utils/encryption_test.cpp b/support/test/src/utils/encryption_test.cpp index 73c1dec7..de1a933c 100644 --- a/support/test/src/utils/encryption_test.cpp +++ b/support/test/src/utils/encryption_test.cpp @@ -19,13 +19,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "test.hpp" + #if defined(PROJECT_ENABLE_LIBSODIUM) -#include "gtest/gtest.h" - -#include "utils/collection.hpp" -#include "utils/encryption.hpp" - namespace repertory { static const std::string token{"moose"}; static const std::wstring token_w{L"moose"}; @@ -34,7 +31,7 @@ TEST(utils_encryption, generate_key) { auto key1 = utils::encryption::generate_key(token); EXPECT_STREQ( - "182072537ada59e4d6b18034a80302ebae935f66adbdf0f271d3d36309c2d481", + "ab4a0b004e824962913f7c0f79582b6ec7a3b8726426ca61d1a0a28ce5049e96", utils::collection::to_hex_string(key1).c_str()); auto key2 = @@ -50,9 +47,15 @@ TEST(utils_encryption, generate_key) { auto key1_w = utils::encryption::generate_key(token_w); EXPECT_NE(key1, key1_w); +#if defined(_WIN32) EXPECT_STREQ( - L"590ac70125bec4501172937f6a2cbdeb22a87b5e40d5595eccd06b2b20548d8f", + L"4f5eb2a2ab34e3777b230465283923080b9ba59311e74058ccd74185131d11fe", utils::collection::to_hex_wstring(key1_w).c_str()); +#else // !defined(_WIN32) + EXPECT_STREQ( + L"0392d95ed3eee9772fbb9af68fedf829a8eb0adbe8575d9691cc9a752196766a", + utils::collection::to_hex_wstring(key1_w).c_str()); +#endif auto key2_w = utils::encryption::generate_key(L"moose"); @@ -68,12 +71,12 @@ TEST(utils_encryption, generate_key) { EXPECT_NE(key4_w, key4); } -TEST(utils_encryption, generate_key_default_hasher_is_sha256) { +TEST(utils_encryption, generate_key_default_hasher_is_blake2b_256) { auto key1 = utils::encryption::generate_key(token); auto key2 = utils::encryption::generate_key( token, [](auto &&data, auto &&size) -> auto { - return utils::encryption::create_hash_sha256( + return utils::encryption::create_hash_blake2b_256( std::string_view(reinterpret_cast(data), size)); }); EXPECT_EQ(key1, key2); @@ -82,7 +85,7 @@ TEST(utils_encryption, generate_key_default_hasher_is_sha256) { utils::encryption::generate_key(token_w); auto key2_w = utils::encryption::generate_key( token_w, [](auto &&data, auto &&size) -> auto { - return utils::encryption::create_hash_sha256(std::wstring_view( + return utils::encryption::create_hash_blake2b_256(std::wstring_view( reinterpret_cast(data), size / sizeof(wchar_t))); }); EXPECT_EQ(key1_w, key2_w); @@ -93,44 +96,44 @@ TEST(utils_encryption, generate_key_default_hasher_is_sha256) { TEST(utils_encryption, generate_key_with_hasher) { auto key1 = utils::encryption::generate_key( - token, [](auto &&data, auto &&size) -> auto { - return utils::encryption::create_hash_sha256( - std::string_view(reinterpret_cast(data), size)); - }); + token, utils::encryption::blake2b_256_hasher); EXPECT_STREQ( - "182072537ada59e4d6b18034a80302ebae935f66adbdf0f271d3d36309c2d481", + "ab4a0b004e824962913f7c0f79582b6ec7a3b8726426ca61d1a0a28ce5049e96", utils::collection::to_hex_string(key1).c_str()); auto key2 = utils::encryption::generate_key( - token, [](auto &&data, auto &&size) -> auto { - return utils::encryption::create_hash_blake2b_256( - std::string_view(reinterpret_cast(data), size)); - }); + token, utils::encryption::sha256_hasher); EXPECT_NE(key1, key2); EXPECT_STREQ( - "ab4a0b004e824962913f7c0f79582b6ec7a3b8726426ca61d1a0a28ce5049e96", + "182072537ada59e4d6b18034a80302ebae935f66adbdf0f271d3d36309c2d481", utils::collection::to_hex_string(key2).c_str()); auto key1_w = utils::encryption::generate_key( - token_w, [](auto &&data, auto &&size) -> auto { - return utils::encryption::create_hash_sha256(std::wstring_view( - reinterpret_cast(data), size / sizeof(wchar_t))); - }); + token_w, utils::encryption::blake2b_256_hasher); +#if defined(_WIN32) EXPECT_STREQ( - L"590ac70125bec4501172937f6a2cbdeb22a87b5e40d5595eccd06b2b20548d8f", + L"4f5eb2a2ab34e3777b230465283923080b9ba59311e74058ccd74185131d11fe", utils::collection::to_hex_wstring(key1_w).c_str()); - - auto key2_w = utils::encryption::generate_key( - token_w, [](auto &&data, auto &&size) -> auto { - return utils::encryption::create_hash_blake2b_256(std::wstring_view( - reinterpret_cast(data), size / sizeof(wchar_t))); - }); - EXPECT_NE(key1_w, key2_w); - +#else // !defined(_WIN32) EXPECT_STREQ( L"0392d95ed3eee9772fbb9af68fedf829a8eb0adbe8575d9691cc9a752196766a", + utils::collection::to_hex_wstring(key1_w).c_str()); +#endif + + auto key2_w = utils::encryption::generate_key( + token_w, utils::encryption::sha256_hasher); + EXPECT_NE(key1_w, key2_w); + +#if defined(_WIN32) + EXPECT_STREQ( + L"918e4c6d39bb373f139b5fac8ec0548a9770da399b2835608974ffeac7fab6c4", utils::collection::to_hex_wstring(key2_w).c_str()); +#else // !defined(_WIN32) + EXPECT_STREQ( + L"590ac70125bec4501172937f6a2cbdeb22a87b5e40d5595eccd06b2b20548d8f", + utils::collection::to_hex_wstring(key2_w).c_str()); +#endif EXPECT_NE(key1_w, key1); EXPECT_NE(key2_w, key2); diff --git a/support/test/src/utils/file_test.cpp b/support/test/src/utils/file_test.cpp new file mode 100644 index 00000000..cb7fd81e --- /dev/null +++ b/support/test/src/utils/file_test.cpp @@ -0,0 +1,65 @@ +/* + Copyright <2018-2024> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#include "test.hpp" + +namespace repertory { +#if defined(PROJECT_ENABLE_JSON) +TEST(utils_file, read_and_write_json_file) { + auto path = test::generate_test_file_name("utils_file"); + + auto data = nlohmann::json({{"moose", "cow"}}); + EXPECT_TRUE(utils::file::write_json_file(path, data)); + + nlohmann::json data2{}; + EXPECT_TRUE(utils::file::read_json_file(path, data2)); + EXPECT_STREQ(data.dump().c_str(), data2.dump().c_str()); +} + +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +TEST(utils_file, read_and_write_json_file_encrypted) { + auto path = test::generate_test_file_name("utils_file"); + + auto data = nlohmann::json({{"moose", "cow"}}); + EXPECT_TRUE(utils::file::write_json_file(path, data, "moose")); + + nlohmann::json data2{}; + EXPECT_TRUE(utils::file::read_json_file(path, data2, "moose")); + EXPECT_STREQ(data.dump().c_str(), data2.dump().c_str()); + + { + auto file = utils::file::file::open_file(path); + data_buffer encrypted_data{}; + EXPECT_TRUE(file.read_all(encrypted_data, 0U)); + + data_buffer decrypted_data{}; + EXPECT_TRUE(utils::encryption::decrypt_data("moose", encrypted_data, + decrypted_data)); + EXPECT_STREQ(data.dump().c_str(), + nlohmann::json::parse( + std::string{decrypted_data.begin(), decrypted_data.end()}) + .dump() + .c_str()); + } +} +#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +#endif // defined(PROJECT_ENABLE_JSON) +} // namespace repertory diff --git a/support/test/src/utils/hash_test.cpp b/support/test/src/utils/hash_test.cpp new file mode 100644 index 00000000..13287bbd --- /dev/null +++ b/support/test/src/utils/hash_test.cpp @@ -0,0 +1,186 @@ +/* + Copyright <2018-2024> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#include "test.hpp" + +#if defined(PROJECT_ENABLE_LIBSODIUM) + +namespace repertory { +TEST(utils_hash, hash_type_sizes) { + EXPECT_EQ(32U, utils::encryption::hash_256_t{}.size()); + EXPECT_EQ(48U, utils::encryption::hash_384_t{}.size()); + EXPECT_EQ(64U, utils::encryption::hash_512_t{}.size()); +} + +TEST(utils_hash, default_hasher_is_blake2b) { + EXPECT_EQ( + &utils::encryption::blake2b_256_hasher, + &utils::encryption::default_create_hash()); + + EXPECT_EQ( + &utils::encryption::blake2b_384_hasher, + &utils::encryption::default_create_hash()); + + EXPECT_EQ( + &utils::encryption::blake2b_512_hasher, + &utils::encryption::default_create_hash()); +} + +TEST(utils_hash, blake2b_256) { + auto hash = utils::collection::to_hex_string( + utils::encryption::create_hash_blake2b_256("a")); + EXPECT_STREQ( + "8928aae63c84d87ea098564d1e03ad813f107add474e56aedd286349c0c03ea4", + hash.c_str()); + + hash = utils::collection::to_hex_string( + utils::encryption::create_hash_blake2b_256(L"a")); +#if defined(_WIN32) + EXPECT_STREQ( + "d2373b17cd8a8e19e39f52fa4905a274f93805fbb8bb4c7f3cb4b2cd6708ec8a", + hash.c_str()); +#else // !defined(_WIN32) + EXPECT_STREQ( + "9fdf5757d7eea386f0d34d2c0e202527986febf1ebb4315fcf7fff40776fa41d", + hash.c_str()); +#endif + + hash = utils::collection::to_hex_string( + utils::encryption::create_hash_blake2b_256({1U})); + EXPECT_STREQ( + "ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e25", + hash.c_str()); +} + +TEST(utils_hash, blake2b_384) { + auto hash = utils::collection::to_hex_string( + utils::encryption::create_hash_blake2b_384("a")); + EXPECT_STREQ("7d40de16ff771d4595bf70cbda0c4ea0a066a6046fa73d34471cd4d93d827d7" + "c94c29399c50de86983af1ec61d5dcef0", + hash.c_str()); + + hash = utils::collection::to_hex_string( + utils::encryption::create_hash_blake2b_384(L"a")); +#if defined(_WIN32) + EXPECT_STREQ("637fe31d1e955760ef31043d525d9321826a778ddbe82fcde45a98394241380" + "96675e2f87e36b53ab223a7fd254198fd", + hash.c_str()); +#else // !defined(_WIN32) + EXPECT_STREQ("9d469bd9dab9d4b48b8688de7c22704a8de1b081294f9be294100dfa9f05c92" + "e8d3616476e46cd14f9e613fed80fd157", + hash.c_str()); +#endif + + hash = utils::collection::to_hex_string( + utils::encryption::create_hash_blake2b_384({1U})); + EXPECT_STREQ("42cfe875d08d816538103b906bb0b05202e0b09c4e981680c1110684fc7845b" + "c91c178fa167afcc445490644b2bf5f5b", + hash.c_str()); +} + +TEST(utils_hash, blake2b_512) { + auto hash = utils::collection::to_hex_string( + utils::encryption::create_hash_blake2b_512("a")); + EXPECT_STREQ( + "333fcb4ee1aa7c115355ec66ceac917c8bfd815bf7587d325aec1864edd24e34d5abe2c6" + "b1b5ee3face62fed78dbef802f2a85cb91d455a8f5249d330853cb3c", + hash.c_str()); + + hash = utils::collection::to_hex_string( + utils::encryption::create_hash_blake2b_512(L"a")); +#if defined(_WIN32) + EXPECT_STREQ( + "05970b95468b0b1941066ff189091493e73859ce41cde5ad08118e93ea1d81a57a144296" + "a26a9fe7781481bde97b886725e36e30b305d8bd5cce1ae36bf1564a", + hash.c_str()); +#else // !defined(_WIN32) + EXPECT_STREQ( + "bbc187c6e4d8525655d0ada62d16eed59f3db3ab07e04fb0483fd4ae21d88b984774add9" + "b3fbcff56f9638091013994f8e2d4646fdbbcb4879e2b5160bbb755d", + hash.c_str()); +#endif + + hash = utils::collection::to_hex_string( + utils::encryption::create_hash_blake2b_512({1U})); + EXPECT_STREQ( + "9545ba37b230d8a2e716c4707586542780815b7c4088edcb9af6a9452d50f32474d5ba9a" + "ab52a67aca864ef2696981c2eadf49020416136afd838fb048d21653", + hash.c_str()); +} + +TEST(utils_hash, sha256) { + auto hash = utils::collection::to_hex_string( + utils::encryption::create_hash_sha256("a")); + EXPECT_STREQ( + "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", + hash.c_str()); + + hash = utils::collection::to_hex_string( + utils::encryption::create_hash_sha256(L"a")); +#if defined(_WIN32) + EXPECT_STREQ( + "ffe9aaeaa2a2d5048174df0b80599ef0197ec024c4b051bc9860cff58ef7f9f3", + hash.c_str()); +#else // !defined(_WIN32) + EXPECT_STREQ( + "a2d398922901344d08180dc41d3e9d73d8c148c7f6e092835bbb28e02dbcf184", + hash.c_str()); +#endif + + hash = utils::collection::to_hex_string( + utils::encryption::create_hash_sha256({1U})); + EXPECT_STREQ( + "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a", + hash.c_str()); +} + +TEST(utils_hash, sha512) { + auto hash = utils::collection::to_hex_string( + utils::encryption::create_hash_sha512("a")); + EXPECT_STREQ( + "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c65" + "2bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75", + hash.c_str()); + + hash = utils::collection::to_hex_string( + utils::encryption::create_hash_sha512(L"a")); +#if defined(_WIN32) + EXPECT_STREQ( + "5c2ca3d50f46ece6066c53bd1a490cbe5f72d2738ae9417332e91e5c3f75205c639d71a9" + "a41d67d965fa137dddf439e0ab9443a6ea44915e90d8b5b566d1c076", + hash.c_str()); +#else // !defined(_WIN32) + EXPECT_STREQ( + "a93498d992e81915075144cb304d2bdf040b336283f888252244882d8366dd3a6e2d9749" + "077114dda1a9aa1a7b69d33f7a781f003ccd12e599a6341014f29aaf", + hash.c_str()); +#endif + + hash = utils::collection::to_hex_string( + utils::encryption::create_hash_sha512({1U})); + EXPECT_STREQ( + "7b54b66836c1fbdd13d2441d9e1434dc62ca677fb68f5fe66a464baadecdbd00576f8d6b" + "5ac3bcc80844b7d50b1cc6603444bbe7cfcf8fc0aa1ee3c636d9e339", + hash.c_str()); +} +} // namespace repertory + +#endif // defined(PROJECT_ENABLE_LIBSODIUM) diff --git a/support/test/src/utils/path_test.cpp b/support/test/src/utils/path_test.cpp index da767ab3..f1479341 100644 --- a/support/test/src/utils/path_test.cpp +++ b/support/test/src/utils/path_test.cpp @@ -19,11 +19,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "gtest/gtest.h" - -#include "utils/common.hpp" -#include "utils/path.hpp" -#include "utils/string.hpp" +#include "test.hpp" namespace repertory { TEST(utils_path, constants) { diff --git a/support/test/src/utils/string_test.cpp b/support/test/src/utils/string_test.cpp index 41e770c8..f25bc9d6 100644 --- a/support/test/src/utils/string_test.cpp +++ b/support/test/src/utils/string_test.cpp @@ -19,9 +19,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "gtest/gtest.h" - -#include "utils/string.hpp" +#include "test.hpp" namespace repertory { TEST(utils_string, begins_with) {