v2.0.4-rc (#37)
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				BlockStorage/repertory/pipeline/head This commit looks good
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	BlockStorage/repertory/pipeline/head This commit looks good
				
			# Changelog ## v2.0.4-rc ### BREAKING CHANGES * `renterd` v2.0.0+ is now required. Prior versions will fail to mount. ### Issues * \#35 [bug] Low frequency check is set to '0' instead of 1 hour by default * \#36 [bug] Max cache size bytes is set to '0' by default ### Changes from v2.0.3-rc * Added Sia API version check prior to mounting * Added back `-cv` (check version) CLI option * Continue documentation updates * Fixed setting `ApiAuth` via `set_value_by_name` * Fixed setting `HostConfig.ApiUser` via `set_value_by_name` * Fixed setting `HostConfig.Path` via `set_value_by_name` * Fixed setting `HostConfig.Protocol` via `set_value_by_name` * Improved ring buffer read-ahead * Integrated `renterd` version 2.0.0 * Prefer using local cache file when opening files * Refactored `app_config` unit tests * Refactored polling to be more accurate on scheduling tasks Reviewed-on: #37
This commit is contained in:
		| @@ -31,26 +31,26 @@ private: | ||||
|   static stop_type stop_requested; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] static auto | ||||
|   default_agent_name(const provider_type &prov) -> std::string; | ||||
|   [[nodiscard]] static auto default_agent_name(const provider_type &prov) | ||||
|       -> std::string; | ||||
|  | ||||
|   [[nodiscard]] static auto | ||||
|   default_api_port(const provider_type &prov) -> std::uint16_t; | ||||
|   [[nodiscard]] static auto default_api_port(const provider_type &prov) | ||||
|       -> std::uint16_t; | ||||
|  | ||||
|   [[nodiscard]] static auto | ||||
|   default_data_directory(const provider_type &prov) -> std::string; | ||||
|   [[nodiscard]] static auto default_data_directory(const provider_type &prov) | ||||
|       -> std::string; | ||||
|  | ||||
|   [[nodiscard]] static auto | ||||
|   default_remote_api_port(const provider_type &prov) -> std::uint16_t; | ||||
|   [[nodiscard]] static auto default_remote_api_port(const provider_type &prov) | ||||
|       -> std::uint16_t; | ||||
|  | ||||
|   [[nodiscard]] static auto | ||||
|   default_rpc_port(const provider_type &prov) -> std::uint16_t; | ||||
|   [[nodiscard]] static auto default_rpc_port(const provider_type &prov) | ||||
|       -> std::uint16_t; | ||||
|  | ||||
|   [[nodiscard]] static auto | ||||
|   get_provider_display_name(const provider_type &prov) -> std::string; | ||||
|   [[nodiscard]] static auto get_provider_display_name(const provider_type &prov) | ||||
|       -> std::string; | ||||
|  | ||||
|   [[nodiscard]] static auto | ||||
|   get_provider_name(const provider_type &prov) -> std::string; | ||||
|   [[nodiscard]] static auto get_provider_name(const provider_type &prov) | ||||
|       -> std::string; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] static auto get_stop_requested() -> bool; | ||||
| @@ -91,7 +91,6 @@ private: | ||||
|   std::atomic<std::uint8_t> max_upload_count_; | ||||
|   std::atomic<std::uint16_t> med_freq_interval_secs_; | ||||
|   std::atomic<std::uint16_t> online_check_retry_secs_; | ||||
|   std::atomic<std::uint16_t> orphaned_file_retention_days_; | ||||
|   std::atomic<download_type> preferred_download_type_; | ||||
|   std::atomic<std::uint16_t> retry_read_count_; | ||||
|   std::atomic<std::uint16_t> ring_buffer_file_size_; | ||||
| @@ -172,8 +171,6 @@ public: | ||||
|  | ||||
|   [[nodiscard]] auto get_online_check_retry_secs() const -> std::uint16_t; | ||||
|  | ||||
|   [[nodiscard]] auto get_orphaned_file_retention_days() const -> std::uint16_t; | ||||
|  | ||||
|   [[nodiscard]] auto get_preferred_download_type() const -> download_type; | ||||
|  | ||||
|   [[nodiscard]] auto get_provider_type() const -> provider_type; | ||||
| @@ -192,8 +189,11 @@ public: | ||||
|  | ||||
|   [[nodiscard]] auto get_task_wait_ms() const -> std::uint16_t; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   get_value_by_name(const std::string &name) const -> std::string; | ||||
|   [[nodiscard]] auto get_value_by_name(const std::string &name) const | ||||
|       -> std::string; | ||||
|  | ||||
|   [[nodiscard]] auto get_raw_value_by_name(const std::string &name) const | ||||
|       -> std::string; | ||||
|  | ||||
|   [[nodiscard]] auto get_version() const -> std::uint64_t; | ||||
|  | ||||
| @@ -239,8 +239,6 @@ public: | ||||
|  | ||||
|   void set_online_check_retry_secs(std::uint16_t value); | ||||
|  | ||||
|   void set_orphaned_file_retention_days(std::uint16_t value); | ||||
|  | ||||
|   void set_preferred_download_type(const download_type &value); | ||||
|  | ||||
|   void set_remote_config(remote::remote_config value); | ||||
|   | ||||
| @@ -57,7 +57,7 @@ using json = nlohmann::json; | ||||
| inline constexpr const std::string_view REPERTORY = "repertory"; | ||||
| inline constexpr const std::wstring_view REPERTORY_W = L"repertory"; | ||||
|  | ||||
| inline constexpr const std::uint64_t REPERTORY_CONFIG_VERSION = 0ULL; | ||||
| inline constexpr const std::uint64_t REPERTORY_CONFIG_VERSION = 1ULL; | ||||
| inline constexpr const std::string_view REPERTORY_DATA_NAME = "repertory2"; | ||||
| inline constexpr const std::string_view REPERTORY_MIN_REMOTE_VERSION = "2.0.0"; | ||||
|  | ||||
| @@ -221,44 +221,25 @@ using WCHAR = wchar_t; | ||||
|  | ||||
| #define MAX_PATH 260 | ||||
|  | ||||
| #define STATUS_SUCCESS                                                         \ | ||||
|   std::uint32_t { 0U } | ||||
| #define STATUS_ACCESS_DENIED                                                   \ | ||||
|   std::uint32_t { 0xC0000022L } | ||||
| #define STATUS_DEVICE_BUSY                                                     \ | ||||
|   std::uint32_t { 0x80000011L } | ||||
| #define STATUS_DEVICE_INSUFFICIENT_RESOURCES                                   \ | ||||
|   std::uint32_t { 0xC0000468L } | ||||
| #define STATUS_DIRECTORY_NOT_EMPTY                                             \ | ||||
|   std::uint32_t { 0xC0000101L } | ||||
| #define STATUS_FILE_IS_A_DIRECTORY                                             \ | ||||
|   std::uint32_t { 0xC00000BAL } | ||||
| #define STATUS_FILE_TOO_LARGE                                                  \ | ||||
|   std::uint32_t { 0xC0000904L } | ||||
| #define STATUS_INSUFFICIENT_RESOURCES                                          \ | ||||
|   std::uint32_t { 0xC000009AL } | ||||
| #define STATUS_INTERNAL_ERROR                                                  \ | ||||
|   std::uint32_t { 0xC00000E5L } | ||||
| #define STATUS_INVALID_ADDRESS                                                 \ | ||||
|   std::uint32_t { 0xC0000141L } | ||||
| #define STATUS_INVALID_HANDLE                                                  \ | ||||
|   std::uint32_t { 0xC0000006L } | ||||
| #define STATUS_INVALID_IMAGE_FORMAT                                            \ | ||||
|   std::uint32_t { 0xC000007BL } | ||||
| #define STATUS_INVALID_PARAMETER                                               \ | ||||
|   std::uint32_t { 0xC000000DL } | ||||
| #define STATUS_NO_MEMORY                                                       \ | ||||
|   std::uint32_t { 0xC0000017L } | ||||
| #define STATUS_NOT_IMPLEMENTED                                                 \ | ||||
|   std::uint32_t { 0xC0000002L } | ||||
| #define STATUS_OBJECT_NAME_EXISTS                                              \ | ||||
|   std::uint32_t { 0x40000000L } | ||||
| #define STATUS_OBJECT_NAME_NOT_FOUND                                           \ | ||||
|   std::uint32_t { 0xC0000034L } | ||||
| #define STATUS_OBJECT_PATH_INVALID                                             \ | ||||
|   std::uint32_t { 0xC0000039L } | ||||
| #define STATUS_UNEXPECTED_IO_ERROR                                             \ | ||||
|   std::uint32_t { 0xC00000E9L } | ||||
| #define STATUS_SUCCESS std::uint32_t{0U} | ||||
| #define STATUS_ACCESS_DENIED std::uint32_t{0xC0000022L} | ||||
| #define STATUS_DEVICE_BUSY std::uint32_t{0x80000011L} | ||||
| #define STATUS_DEVICE_INSUFFICIENT_RESOURCES std::uint32_t{0xC0000468L} | ||||
| #define STATUS_DIRECTORY_NOT_EMPTY std::uint32_t{0xC0000101L} | ||||
| #define STATUS_FILE_IS_A_DIRECTORY std::uint32_t{0xC00000BAL} | ||||
| #define STATUS_FILE_TOO_LARGE std::uint32_t{0xC0000904L} | ||||
| #define STATUS_INSUFFICIENT_RESOURCES std::uint32_t{0xC000009AL} | ||||
| #define STATUS_INTERNAL_ERROR std::uint32_t{0xC00000E5L} | ||||
| #define STATUS_INVALID_ADDRESS std::uint32_t{0xC0000141L} | ||||
| #define STATUS_INVALID_HANDLE std::uint32_t{0xC0000006L} | ||||
| #define STATUS_INVALID_IMAGE_FORMAT std::uint32_t{0xC000007BL} | ||||
| #define STATUS_INVALID_PARAMETER std::uint32_t{0xC000000DL} | ||||
| #define STATUS_NO_MEMORY std::uint32_t{0xC0000017L} | ||||
| #define STATUS_NOT_IMPLEMENTED std::uint32_t{0xC0000002L} | ||||
| #define STATUS_OBJECT_NAME_EXISTS std::uint32_t{0x40000000L} | ||||
| #define STATUS_OBJECT_NAME_NOT_FOUND std::uint32_t{0xC0000034L} | ||||
| #define STATUS_OBJECT_PATH_INVALID std::uint32_t{0xC0000039L} | ||||
| #define STATUS_UNEXPECTED_IO_ERROR std::uint32_t{0xC00000E9L} | ||||
|  | ||||
| #define CONVERT_STATUS_NOT_IMPLEMENTED(e)                                      \ | ||||
|   ((std::uint32_t(e) == STATUS_NOT_IMPLEMENTED) ? -ENOTSUP : e) | ||||
|   | ||||
| @@ -26,6 +26,7 @@ | ||||
| #include "comm/packet/packet_client.hpp" | ||||
| #include "drives/remote/remote_open_file_table.hpp" | ||||
| #include "drives/winfsp/remotewinfsp/i_remote_instance.hpp" | ||||
| #include "types/remote.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
|   | ||||
| @@ -0,0 +1,78 @@ | ||||
| /* | ||||
|   Copyright <2018-2025> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   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_EVENTS_TYPES_PRODIVER_INVALID_VERSION_HPP_ | ||||
| #define REPERTORY_INCLUDE_EVENTS_TYPES_PRODIVER_INVALID_VERSION_HPP_ | ||||
|  | ||||
| #include "events/i_event.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| struct provider_invalid_version final : public i_event { | ||||
|   provider_invalid_version() = default; | ||||
|   provider_invalid_version(std::string_view function_name_, | ||||
|                            std::string required_version_, | ||||
|                            std::string returned_version_) | ||||
|       : function_name(std::string(function_name_)), | ||||
|         required_version(std::move(required_version_)), | ||||
|         returned_version(std::move(returned_version_)) {} | ||||
|  | ||||
|   static constexpr const event_level level{event_level::error}; | ||||
|   static constexpr const std::string_view name{"provider_invalid_version"}; | ||||
|  | ||||
|   std::string function_name; | ||||
|   std::string required_version; | ||||
|   std::string returned_version; | ||||
|  | ||||
|   [[nodiscard]] auto get_event_level() const -> event_level override { | ||||
|     return level; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_name() const -> std::string_view override { | ||||
|     return name; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_single_line() const -> std::string override { | ||||
|     return fmt::format("{}|func|{}|required|{}|returned|{}", name, | ||||
|                        function_name, required_version, returned_version); | ||||
|   } | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| NLOHMANN_JSON_NAMESPACE_BEGIN | ||||
| template <> struct adl_serializer<repertory::provider_invalid_version> { | ||||
|   static void to_json(json &data, | ||||
|                       const repertory::provider_invalid_version &value) { | ||||
|     data["function_name"] = value.function_name; | ||||
|     data["required_version"] = value.required_version; | ||||
|     data["returned_version"] = value.returned_version; | ||||
|   } | ||||
|  | ||||
|   static void from_json(const json &data, | ||||
|                         repertory::provider_invalid_version &value) { | ||||
|     data.at("function_name").get_to(value.function_name); | ||||
|     data.at("required_version").get_to(value.required_version); | ||||
|     data.at("returned_version").get_to(value.returned_version); | ||||
|   } | ||||
| }; | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
|  | ||||
| #endif // REPERTORY_INCLUDE_EVENTS_TYPES_PRODIVER_INVALID_VERSION_HPP_ | ||||
| @@ -85,6 +85,13 @@ private: | ||||
|   void remove_deleted_files(stop_type &stop_requested); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto check_version(std::string &required_version, | ||||
|                                    std::string &returned_version) const | ||||
|       -> bool override { | ||||
|     required_version = returned_version = ""; | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto create_directory(const std::string &api_path, | ||||
|                                       api_meta_map &meta) -> api_error override; | ||||
|  | ||||
|   | ||||
| @@ -31,6 +31,10 @@ class i_provider { | ||||
|   INTERFACE_SETUP(i_provider); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] virtual auto check_version(std::string &required_version, | ||||
|                                            std::string &returned_version) const | ||||
|       -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto create_directory(const std::string &api_path, | ||||
|                                               api_meta_map &meta) | ||||
|       -> api_error = 0; | ||||
|   | ||||
| @@ -113,6 +113,13 @@ protected: | ||||
|       -> api_error override; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto check_version(std::string &required_version, | ||||
|                                    std::string &returned_version) const | ||||
|       -> bool override { | ||||
|     required_version = returned_version = ""; | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] static auto convert_api_date(std::string_view date) | ||||
|       -> std::uint64_t; | ||||
|  | ||||
|   | ||||
| @@ -80,6 +80,10 @@ protected: | ||||
|       -> api_error override; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto check_version(std::string &required_version, | ||||
|                                    std::string &returned_version) const | ||||
|       -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_item_count(const std::string &api_path) const | ||||
|       -> std::uint64_t override; | ||||
|  | ||||
|   | ||||
| @@ -24,30 +24,27 @@ | ||||
|  | ||||
| namespace repertory { | ||||
| constexpr const auto default_api_auth_size{48U}; | ||||
| constexpr const auto default_download_timeout_ces{30U}; | ||||
| constexpr const auto default_download_timeout_secs{30U}; | ||||
| constexpr const auto default_eviction_delay_mins{1U}; | ||||
| constexpr const auto default_high_freq_interval_secs{30U}; | ||||
| constexpr const auto default_low_freq_interval_secs{0U * 60U}; | ||||
| constexpr const auto default_high_freq_interval_secs{std::uint16_t{30U}}; | ||||
| constexpr const auto default_low_freq_interval_secs{std::uint16_t(60U * 60U)}; | ||||
| constexpr const auto default_max_cache_size_bytes{ | ||||
|     std::uint64_t(20UL * 1024UL * 1024UL * 1024UL), | ||||
|     std::uint64_t(20ULL * 1024ULL * 1024ULL * 1024ULL), | ||||
| }; | ||||
| constexpr const auto default_max_upload_count{5U}; | ||||
| constexpr const auto default_med_freq_interval_secs{2U * 60U}; | ||||
| constexpr const auto default_med_freq_interval_secs{std::uint16_t{2U * 60U}}; | ||||
| constexpr const auto default_online_check_retry_secs{60U}; | ||||
| constexpr const auto default_orphaned_file_retention_days{15U}; | ||||
| constexpr const auto default_retry_read_count{6U}; | ||||
| constexpr const auto default_ring_buffer_file_size{512U}; | ||||
| constexpr const auto default_task_wait_ms{100U}; | ||||
| constexpr const auto default_timeout_ms{60000U}; | ||||
| constexpr const auto max_orphaned_file_retention_days{std::uint16_t(31U)}; | ||||
| constexpr const auto max_ring_buffer_file_size{std::uint16_t(1024U)}; | ||||
| constexpr const auto max_s3_object_name_length{1024U}; | ||||
| constexpr const auto min_cache_size_bytes{ | ||||
|     std::uint64_t(100UL * 1024UL * 1024UL), | ||||
|     std::uint64_t(100ULL * 1024ULL * 1024ULL), | ||||
| }; | ||||
| constexpr const auto min_download_timeout_secs{std::uint8_t(5U)}; | ||||
| constexpr const auto min_online_check_retry_secs{std::uint16_t(15U)}; | ||||
| constexpr const auto min_orphaned_file_retention_days{std::uint16_t(1U)}; | ||||
| constexpr const auto min_retry_read_count{std::uint16_t(2U)}; | ||||
| constexpr const auto min_ring_buffer_file_size{std::uint16_t(64U)}; | ||||
| constexpr const auto min_task_wait_ms{std::uint16_t(50U)}; | ||||
| @@ -333,7 +330,6 @@ struct directory_item final { | ||||
|   bool directory{false}; | ||||
|   std::uint64_t size{}; | ||||
|   api_meta_map meta; | ||||
|   bool resolved{false}; | ||||
| }; | ||||
|  | ||||
| struct encrypt_config final { | ||||
| @@ -493,8 +489,6 @@ inline constexpr const auto JSON_MED_FREQ_INTERVAL_SECS{ | ||||
| inline constexpr const auto JSON_META{"Meta"}; | ||||
| inline constexpr const auto JSON_ONLINE_CHECK_RETRY_SECS{ | ||||
|     "OnlineCheckRetrySeconds"}; | ||||
| inline constexpr const auto JSON_ORPHANED_FILE_RETENTION_DAYS{ | ||||
|     "OrphanedFileRetentionDays"}; | ||||
| inline constexpr const auto JSON_PATH{"Path"}; | ||||
| inline constexpr const auto JSON_PREFERRED_DOWNLOAD_TYPE{ | ||||
|     "PreferredDownloadType"}; | ||||
| @@ -619,6 +613,16 @@ template <typename data_t> struct adl_serializer<repertory::atomic<data_t>> { | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <> struct adl_serializer<std::atomic<std::uint64_t>> { | ||||
|   static void to_json(json &data, const std::atomic<std::uint64_t> &value) { | ||||
|     data = value.load(); | ||||
|   } | ||||
|  | ||||
|   static void from_json(const json &data, std::atomic<std::uint64_t> &value) { | ||||
|     value.store(data.get<std::uint64_t>()); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename primitive_t> | ||||
| struct adl_serializer<std::atomic<primitive_t>> { | ||||
|   static void to_json(json &data, const std::atomic<primitive_t> &value) { | ||||
| @@ -642,6 +646,18 @@ template <> struct adl_serializer<std::atomic<repertory::database_type>> { | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <> struct adl_serializer<std::atomic<repertory::event_level>> { | ||||
|   static void to_json(json &data, | ||||
|                       const std::atomic<repertory::event_level> &value) { | ||||
|     data = repertory::event_level_to_string(value.load()); | ||||
|   } | ||||
|  | ||||
|   static void from_json(const json &data, | ||||
|                         std::atomic<repertory::event_level> &value) { | ||||
|     value.store(repertory::event_level_from_string(data.get<std::string>())); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <> struct adl_serializer<std::atomic<repertory::download_type>> { | ||||
|   static void to_json(json &data, | ||||
|                       const std::atomic<repertory::download_type> &value) { | ||||
| @@ -674,15 +690,13 @@ template <> struct adl_serializer<repertory::download_type> { | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <> struct adl_serializer<std::atomic<repertory::event_level>> { | ||||
|   static void to_json(json &data, | ||||
|                       const std::atomic<repertory::event_level> &value) { | ||||
|     data = repertory::event_level_to_string(value.load()); | ||||
| template <> struct adl_serializer<repertory::event_level> { | ||||
|   static void to_json(json &data, const repertory::event_level &value) { | ||||
|     data = repertory::event_level_to_string(value); | ||||
|   } | ||||
|  | ||||
|   static void from_json(const json &data, | ||||
|                         std::atomic<repertory::event_level> &value) { | ||||
|     value.store(repertory::event_level_from_string(data.get<std::string>())); | ||||
|   static void from_json(const json &data, repertory::event_level &value) { | ||||
|     value = repertory::event_level_from_string(data.get<std::string>()); | ||||
|   } | ||||
| }; | ||||
| NLOHMANN_JSON_NAMESPACE_END | ||||
|   | ||||
| @@ -70,7 +70,7 @@ app_config::app_config(const provider_type &prov, | ||||
|       api_port_(default_rpc_port(prov)), | ||||
|       api_user_(std::string{REPERTORY}), | ||||
|       config_changed_(false), | ||||
|       download_timeout_secs_(default_download_timeout_ces), | ||||
|       download_timeout_secs_(default_download_timeout_secs), | ||||
|       enable_download_timeout_(true), | ||||
|       enable_drive_events_(false), | ||||
| #if defined(_WIN32) | ||||
| @@ -85,7 +85,6 @@ app_config::app_config(const provider_type &prov, | ||||
|       max_upload_count_(default_max_upload_count), | ||||
|       med_freq_interval_secs_(default_med_freq_interval_secs), | ||||
|       online_check_retry_secs_(default_online_check_retry_secs), | ||||
|       orphaned_file_retention_days_(default_orphaned_file_retention_days), | ||||
|       preferred_download_type_(download_type::default_), | ||||
|       retry_read_count_(default_retry_read_count), | ||||
|       ring_buffer_file_size_(default_ring_buffer_file_size), | ||||
| @@ -166,8 +165,14 @@ app_config::app_config(const provider_type &prov, | ||||
|        [this]() { return get_host_config().api_password; }}, | ||||
|       {fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_API_PORT), | ||||
|        [this]() { return std::to_string(get_host_config().api_port); }}, | ||||
|       {fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_API_USER), | ||||
|        [this]() { return get_host_config().api_user; }}, | ||||
|       {fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_HOST_NAME_OR_IP), | ||||
|        [this]() { return get_host_config().host_name_or_ip; }}, | ||||
|       {fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_PATH), | ||||
|        [this]() { return get_host_config().path; }}, | ||||
|       {fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_PROTOCOL), | ||||
|        [this]() { return get_host_config().protocol; }}, | ||||
|       {fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_TIMEOUT_MS), | ||||
|        [this]() { return std::to_string(get_host_config().timeout_ms); }}, | ||||
|       {JSON_LOW_FREQ_INTERVAL_SECS, | ||||
| @@ -180,8 +185,6 @@ app_config::app_config(const provider_type &prov, | ||||
|        [this]() { return std::to_string(get_med_frequency_interval_secs()); }}, | ||||
|       {JSON_ONLINE_CHECK_RETRY_SECS, | ||||
|        [this]() { return std::to_string(get_online_check_retry_secs()); }}, | ||||
|       {JSON_ORPHANED_FILE_RETENTION_DAYS, | ||||
|        [this]() { return std::to_string(get_orphaned_file_retention_days()); }}, | ||||
|       {JSON_PREFERRED_DOWNLOAD_TYPE, | ||||
|        [this]() { | ||||
|          return download_type_to_string(get_preferred_download_type()); | ||||
| @@ -250,7 +253,7 @@ app_config::app_config(const provider_type &prov, | ||||
|  | ||||
|   value_set_lookup_ = { | ||||
|       { | ||||
|           JSON_API_PATH, | ||||
|           JSON_API_AUTH, | ||||
|           [this](const std::string &value) { | ||||
|             set_api_auth(value); | ||||
|             return get_api_auth(); | ||||
| @@ -349,7 +352,7 @@ app_config::app_config(const provider_type &prov, | ||||
|       { | ||||
|           JSON_HIGH_FREQ_INTERVAL_SECS, | ||||
|           [this](const std::string &value) { | ||||
|             set_high_frequency_interval_secs(utils::string::to_uint8(value)); | ||||
|             set_high_frequency_interval_secs(utils::string::to_uint16(value)); | ||||
|             return std::to_string(get_high_frequency_interval_secs()); | ||||
|           }, | ||||
|       }, | ||||
| @@ -380,6 +383,15 @@ app_config::app_config(const provider_type &prov, | ||||
|             return std::to_string(get_host_config().api_port); | ||||
|           }, | ||||
|       }, | ||||
|       { | ||||
|           fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_API_USER), | ||||
|           [this](const std::string &value) { | ||||
|             auto cfg = get_host_config(); | ||||
|             cfg.api_user = value; | ||||
|             set_host_config(cfg); | ||||
|             return get_host_config().api_user; | ||||
|           }, | ||||
|       }, | ||||
|       { | ||||
|           fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_HOST_NAME_OR_IP), | ||||
|           [this](const std::string &value) { | ||||
| @@ -389,6 +401,24 @@ app_config::app_config(const provider_type &prov, | ||||
|             return get_host_config().host_name_or_ip; | ||||
|           }, | ||||
|       }, | ||||
|       { | ||||
|           fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_PATH), | ||||
|           [this](const std::string &value) { | ||||
|             auto cfg = get_host_config(); | ||||
|             cfg.path = value; | ||||
|             set_host_config(cfg); | ||||
|             return get_host_config().path; | ||||
|           }, | ||||
|       }, | ||||
|       { | ||||
|           fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_PROTOCOL), | ||||
|           [this](const std::string &value) { | ||||
|             auto cfg = get_host_config(); | ||||
|             cfg.protocol = value; | ||||
|             set_host_config(cfg); | ||||
|             return get_host_config().protocol; | ||||
|           }, | ||||
|       }, | ||||
|       { | ||||
|           fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_TIMEOUT_MS), | ||||
|           [this](const std::string &value) { | ||||
| @@ -401,14 +431,14 @@ app_config::app_config(const provider_type &prov, | ||||
|       { | ||||
|           JSON_LOW_FREQ_INTERVAL_SECS, | ||||
|           [this](const std::string &value) { | ||||
|             set_low_frequency_interval_secs(utils::string::to_uint8(value)); | ||||
|             set_low_frequency_interval_secs(utils::string::to_uint16(value)); | ||||
|             return std::to_string(get_low_frequency_interval_secs()); | ||||
|           }, | ||||
|       }, | ||||
|       { | ||||
|           JSON_MED_FREQ_INTERVAL_SECS, | ||||
|           [this](const std::string &value) { | ||||
|             set_med_frequency_interval_secs(utils::string::to_uint8(value)); | ||||
|             set_med_frequency_interval_secs(utils::string::to_uint16(value)); | ||||
|             return std::to_string(get_med_frequency_interval_secs()); | ||||
|           }, | ||||
|       }, | ||||
| @@ -433,13 +463,6 @@ app_config::app_config(const provider_type &prov, | ||||
|             return std::to_string(get_online_check_retry_secs()); | ||||
|           }, | ||||
|       }, | ||||
|       { | ||||
|           JSON_ORPHANED_FILE_RETENTION_DAYS, | ||||
|           [this](const std::string &value) { | ||||
|             set_orphaned_file_retention_days(utils::string::to_uint16(value)); | ||||
|             return std::to_string(get_orphaned_file_retention_days()); | ||||
|           }, | ||||
|       }, | ||||
|       { | ||||
|           JSON_PREFERRED_DOWNLOAD_TYPE, | ||||
|           [this](const std::string &value) { | ||||
| @@ -812,7 +835,6 @@ auto app_config::get_json() const -> json { | ||||
|       {JSON_MAX_UPLOAD_COUNT, max_upload_count_}, | ||||
|       {JSON_MED_FREQ_INTERVAL_SECS, med_freq_interval_secs_}, | ||||
|       {JSON_ONLINE_CHECK_RETRY_SECS, online_check_retry_secs_}, | ||||
|       {JSON_ORPHANED_FILE_RETENTION_DAYS, orphaned_file_retention_days_}, | ||||
|       {JSON_PREFERRED_DOWNLOAD_TYPE, preferred_download_type_}, | ||||
|       {JSON_REMOTE_CONFIG, remote_config_}, | ||||
|       {JSON_REMOTE_MOUNT, remote_mount_}, | ||||
| @@ -834,7 +856,6 @@ auto app_config::get_json() const -> json { | ||||
|     ret.erase(JSON_MAX_CACHE_SIZE_BYTES); | ||||
|     ret.erase(JSON_MAX_UPLOAD_COUNT); | ||||
|     ret.erase(JSON_ONLINE_CHECK_RETRY_SECS); | ||||
|     ret.erase(JSON_ORPHANED_FILE_RETENTION_DAYS); | ||||
|     ret.erase(JSON_PREFERRED_DOWNLOAD_TYPE); | ||||
|     ret.erase(JSON_REMOTE_CONFIG); | ||||
|     ret.erase(JSON_RETRY_READ_COUNT); | ||||
| @@ -856,7 +877,6 @@ auto app_config::get_json() const -> json { | ||||
|     ret.erase(JSON_MAX_UPLOAD_COUNT); | ||||
|     ret.erase(JSON_MED_FREQ_INTERVAL_SECS); | ||||
|     ret.erase(JSON_ONLINE_CHECK_RETRY_SECS); | ||||
|     ret.erase(JSON_ORPHANED_FILE_RETENTION_DAYS); | ||||
|     ret.erase(JSON_PREFERRED_DOWNLOAD_TYPE); | ||||
|     ret.erase(JSON_REMOTE_MOUNT); | ||||
|     ret.erase(JSON_RETRY_READ_COUNT); | ||||
| @@ -912,12 +932,6 @@ auto app_config::get_online_check_retry_secs() const -> std::uint16_t { | ||||
|   return std::max(min_online_check_retry_secs, online_check_retry_secs_.load()); | ||||
| } | ||||
|  | ||||
| auto app_config::get_orphaned_file_retention_days() const -> std::uint16_t { | ||||
|   return std::min(max_orphaned_file_retention_days, | ||||
|                   std::max(min_orphaned_file_retention_days, | ||||
|                            orphaned_file_retention_days_.load())); | ||||
| } | ||||
|  | ||||
| auto app_config::get_preferred_download_type() const -> download_type { | ||||
|   return preferred_download_type_; | ||||
| } | ||||
| @@ -1053,8 +1067,6 @@ auto app_config::load() -> bool { | ||||
|               med_freq_interval_secs_, found); | ||||
|     get_value(json_document, JSON_ONLINE_CHECK_RETRY_SECS, | ||||
|               online_check_retry_secs_, found); | ||||
|     get_value(json_document, JSON_ORPHANED_FILE_RETENTION_DAYS, | ||||
|               orphaned_file_retention_days_, found); | ||||
|     get_value(json_document, JSON_PREFERRED_DOWNLOAD_TYPE, | ||||
|               preferred_download_type_, found); | ||||
|     get_value(json_document, JSON_REMOTE_CONFIG, remote_config_, found); | ||||
| @@ -1069,10 +1081,17 @@ auto app_config::load() -> bool { | ||||
|     std::uint64_t version{}; | ||||
|     get_value(json_document, JSON_VERSION, version, found); | ||||
|  | ||||
|     // Handle configuration defaults for new config versions | ||||
|     if (version != REPERTORY_CONFIG_VERSION) { | ||||
|       version_ = REPERTORY_CONFIG_VERSION; | ||||
|       // TODO upgrade future version | ||||
|       if (version_ == 1U) { | ||||
|         if (low_freq_interval_secs_ == 0UL) { | ||||
|           set_value(low_freq_interval_secs_, default_low_freq_interval_secs); | ||||
|         } | ||||
|  | ||||
|         if (max_cache_size_bytes_ == 0UL) { | ||||
|           set_value(max_cache_size_bytes_, default_max_cache_size_bytes); | ||||
|         } | ||||
|       } | ||||
|       found = false; | ||||
|     } | ||||
|  | ||||
| @@ -1199,10 +1218,6 @@ void app_config::set_online_check_retry_secs(std::uint16_t value) { | ||||
|   set_value(online_check_retry_secs_, value); | ||||
| } | ||||
|  | ||||
| void app_config::set_orphaned_file_retention_days(std::uint16_t value) { | ||||
|   set_value(orphaned_file_retention_days_, value); | ||||
| } | ||||
|  | ||||
| void app_config::set_preferred_download_type(const download_type &value) { | ||||
|   set_value(preferred_download_type_, value); | ||||
| } | ||||
|   | ||||
| @@ -43,8 +43,8 @@ | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory::remote_fuse { | ||||
| auto remote_fuse_drive::access_impl(std::string api_path, | ||||
|                                     int mask) -> api_error { | ||||
| auto remote_fuse_drive::access_impl(std::string api_path, int mask) | ||||
|     -> api_error { | ||||
|   return utils::to_api_error( | ||||
|       remote_instance_->fuse_access(api_path.c_str(), mask)); | ||||
| } | ||||
| @@ -62,8 +62,8 @@ auto remote_fuse_drive::chmod_impl(std::string api_path, mode_t mode, | ||||
|                                    struct fuse_file_info * /*f_info*/) | ||||
|     -> api_error { | ||||
| #else | ||||
| auto remote_fuse_drive::chmod_impl(std::string api_path, | ||||
|                                    mode_t mode) -> api_error { | ||||
| auto remote_fuse_drive::chmod_impl(std::string api_path, mode_t mode) | ||||
|     -> api_error { | ||||
| #endif | ||||
|   return utils::to_api_error(remote_instance_->fuse_chmod( | ||||
|       api_path.c_str(), static_cast<remote::file_mode>(mode))); | ||||
| @@ -74,8 +74,8 @@ auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid, | ||||
|                                    struct fuse_file_info * /*f_info*/) | ||||
|     -> api_error { | ||||
| #else | ||||
| auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, | ||||
|                                    gid_t gid) -> api_error { | ||||
| auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid) | ||||
|     -> api_error { | ||||
| #endif | ||||
|   return utils::to_api_error( | ||||
|       remote_instance_->fuse_chown(api_path.c_str(), uid, gid)); | ||||
| @@ -94,7 +94,7 @@ void remote_fuse_drive::destroy_impl(void *ptr) { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   event_system::instance().raise<drive_unmount_pending>(function_name, | ||||
|                                                          get_mount_location()); | ||||
|                                                         get_mount_location()); | ||||
|  | ||||
|   if (server_) { | ||||
|     server_->stop(); | ||||
| @@ -116,14 +116,15 @@ void remote_fuse_drive::destroy_impl(void *ptr) { | ||||
|   } | ||||
|  | ||||
|   event_system::instance().raise<drive_unmounted>(function_name, | ||||
|                                                    get_mount_location()); | ||||
|                                                   get_mount_location()); | ||||
|  | ||||
|   fuse_base::destroy_impl(ptr); | ||||
| } | ||||
|  | ||||
| auto remote_fuse_drive::fgetattr_impl( | ||||
|     std::string api_path, struct stat *unix_st, | ||||
|     struct fuse_file_info *f_info) -> api_error { | ||||
| auto remote_fuse_drive::fgetattr_impl(std::string api_path, | ||||
|                                       struct stat *unix_st, | ||||
|                                       struct fuse_file_info *f_info) | ||||
|     -> api_error { | ||||
|   remote::stat r_stat{}; | ||||
|   auto directory = false; | ||||
|  | ||||
| @@ -184,8 +185,8 @@ auto remote_fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st, | ||||
|                                      struct fuse_file_info * /*f_info*/) | ||||
|     -> api_error { | ||||
| #else | ||||
| auto remote_fuse_drive::getattr_impl(std::string api_path, | ||||
|                                      struct stat *unix_st) -> api_error { | ||||
| auto remote_fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st) | ||||
|     -> api_error { | ||||
| #endif | ||||
|   bool directory = false; | ||||
|   remote::stat r_stat{}; | ||||
| @@ -263,14 +264,14 @@ auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn) -> void * { | ||||
|     server_ = std::make_shared<server>(config_); | ||||
|     server_->start(); | ||||
|     event_system::instance().raise<drive_mounted>(function_name, | ||||
|                                                    get_mount_location()); | ||||
|                                                   get_mount_location()); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto remote_fuse_drive::mkdir_impl(std::string api_path, | ||||
|                                    mode_t mode) -> api_error { | ||||
| auto remote_fuse_drive::mkdir_impl(std::string api_path, mode_t mode) | ||||
|     -> api_error { | ||||
|   return utils::to_api_error(remote_instance_->fuse_mkdir( | ||||
|       api_path.c_str(), static_cast<remote::file_mode>(mode))); | ||||
| } | ||||
| @@ -295,8 +296,9 @@ auto remote_fuse_drive::open_impl(std::string api_path, | ||||
|       f_info->fh)); | ||||
| } | ||||
|  | ||||
| auto remote_fuse_drive::opendir_impl( | ||||
|     std::string api_path, struct fuse_file_info *f_info) -> api_error { | ||||
| auto remote_fuse_drive::opendir_impl(std::string api_path, | ||||
|                                      struct fuse_file_info *f_info) | ||||
|     -> api_error { | ||||
|   if ((f_info->flags & O_APPEND) == O_APPEND || | ||||
|       (f_info->flags & O_EXCL) == O_EXCL) { | ||||
|     return api_error::directory_exists; | ||||
| @@ -309,12 +311,14 @@ auto remote_fuse_drive::opendir_impl( | ||||
| void remote_fuse_drive::populate_stat(const remote::stat &r_stat, | ||||
|                                       bool directory, struct stat &unix_st) { | ||||
|   std::memset(&unix_st, 0, sizeof(struct stat)); | ||||
|   unix_st.st_blksize = r_stat.st_blksize; | ||||
|   unix_st.st_blocks = static_cast<blkcnt_t>(r_stat.st_blocks); | ||||
|   unix_st.st_blksize = | ||||
|       static_cast<decltype(unix_st.st_blksize)>(r_stat.st_blksize); | ||||
|   unix_st.st_blocks = | ||||
|       static_cast<decltype(unix_st.st_blocks)>(r_stat.st_blocks); | ||||
|   unix_st.st_gid = r_stat.st_gid; | ||||
|   unix_st.st_mode = (directory ? S_IFDIR : S_IFREG) | r_stat.st_mode; | ||||
|   unix_st.st_nlink = r_stat.st_nlink; | ||||
|   unix_st.st_size = static_cast<off_t>(r_stat.st_size); | ||||
|   unix_st.st_size = static_cast<decltype(unix_st.st_size)>(r_stat.st_size); | ||||
|   unix_st.st_uid = r_stat.st_uid; | ||||
|  | ||||
| #if defined(__APPLE__) | ||||
| @@ -373,14 +377,18 @@ auto remote_fuse_drive::read_impl(std::string api_path, char *buffer, | ||||
| } | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
| auto remote_fuse_drive::readdir_impl( | ||||
|     std::string api_path, void *buf, fuse_fill_dir_t fuse_fill_dir, | ||||
|     off_t offset, struct fuse_file_info *f_info, | ||||
|     fuse_readdir_flags /*flags*/) -> api_error { | ||||
| auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf, | ||||
|                                      fuse_fill_dir_t fuse_fill_dir, | ||||
|                                      off_t offset, | ||||
|                                      struct fuse_file_info *f_info, | ||||
|                                      fuse_readdir_flags /*flags*/) | ||||
|     -> api_error { | ||||
| #else | ||||
| auto remote_fuse_drive::readdir_impl( | ||||
|     std::string api_path, void *buf, fuse_fill_dir_t fuse_fill_dir, | ||||
|     off_t offset, struct fuse_file_info *f_info) -> api_error { | ||||
| auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf, | ||||
|                                      fuse_fill_dir_t fuse_fill_dir, | ||||
|                                      off_t offset, | ||||
|                                      struct fuse_file_info *f_info) | ||||
|     -> api_error { | ||||
| #endif | ||||
|   std::string item_path; | ||||
|   int res = 0; | ||||
| @@ -408,14 +416,16 @@ auto remote_fuse_drive::readdir_impl( | ||||
|   return utils::to_api_error(res); | ||||
| } | ||||
|  | ||||
| auto remote_fuse_drive::release_impl( | ||||
|     std::string api_path, struct fuse_file_info *f_info) -> api_error { | ||||
| auto remote_fuse_drive::release_impl(std::string api_path, | ||||
|                                      struct fuse_file_info *f_info) | ||||
|     -> api_error { | ||||
|   return utils::to_api_error( | ||||
|       remote_instance_->fuse_release(api_path.c_str(), f_info->fh)); | ||||
| } | ||||
|  | ||||
| auto remote_fuse_drive::releasedir_impl( | ||||
|     std::string api_path, struct fuse_file_info *f_info) -> api_error { | ||||
| auto remote_fuse_drive::releasedir_impl(std::string api_path, | ||||
|                                         struct fuse_file_info *f_info) | ||||
|     -> api_error { | ||||
|   return utils::to_api_error( | ||||
|       remote_instance_->fuse_releasedir(api_path.c_str(), f_info->fh)); | ||||
| } | ||||
| @@ -512,8 +522,8 @@ api_error remote_fuse_drive::statfs_x_impl(std::string api_path, | ||||
|   return utils::to_api_error(res); | ||||
| } | ||||
| #else  // __APPLE__ | ||||
| auto remote_fuse_drive::statfs_impl(std::string api_path, | ||||
|                                     struct statvfs *stbuf) -> api_error { | ||||
| auto remote_fuse_drive::statfs_impl(std::string api_path, struct statvfs *stbuf) | ||||
|     -> api_error { | ||||
|   auto res = statvfs(config_.get_data_directory().c_str(), stbuf); | ||||
|   if (res == 0) { | ||||
|     remote::statfs r_stat{}; | ||||
| @@ -540,8 +550,8 @@ auto remote_fuse_drive::truncate_impl(std::string api_path, off_t size, | ||||
|                                       struct fuse_file_info * /*f_info*/) | ||||
|     -> api_error { | ||||
| #else | ||||
| auto remote_fuse_drive::truncate_impl(std::string api_path, | ||||
|                                       off_t size) -> api_error { | ||||
| auto remote_fuse_drive::truncate_impl(std::string api_path, off_t size) | ||||
|     -> api_error { | ||||
| #endif | ||||
|   return utils::to_api_error(remote_instance_->fuse_truncate( | ||||
|       api_path.c_str(), static_cast<remote::file_offset>(size))); | ||||
| @@ -552,9 +562,10 @@ auto remote_fuse_drive::unlink_impl(std::string api_path) -> api_error { | ||||
| } | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
| auto remote_fuse_drive::utimens_impl( | ||||
|     std::string api_path, const struct timespec tv[2], | ||||
|     struct fuse_file_info * /*f_info*/) -> api_error { | ||||
| auto remote_fuse_drive::utimens_impl(std::string api_path, | ||||
|                                      const struct timespec tv[2], | ||||
|                                      struct fuse_file_info * /*f_info*/) | ||||
|     -> api_error { | ||||
| #else | ||||
| auto remote_fuse_drive::utimens_impl(std::string api_path, | ||||
|                                      const struct timespec tv[2]) -> api_error { | ||||
|   | ||||
| @@ -22,13 +22,11 @@ | ||||
| #include "drives/winfsp/remotewinfsp/remote_client.hpp" | ||||
|  | ||||
| #include "app_config.hpp" | ||||
| #include "drives/winfsp/remotewinfsp/i_remote_instance.hpp" | ||||
| #include "events/event_system.hpp" | ||||
| #include "events/types/drive_mounted.hpp" | ||||
| #include "events/types/drive_unmount_pending.hpp" | ||||
| #include "events/types/drive_unmounted.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/string.hpp" | ||||
| #include "version.hpp" | ||||
|  | ||||
| namespace repertory::remote_winfsp { | ||||
| @@ -44,11 +42,7 @@ auto remote_client::winfsp_can_delete(PVOID file_desc, PWSTR file_name) | ||||
|   request.encode(file_name); | ||||
|  | ||||
|   std::uint32_t service_flags{}; | ||||
|   auto ret{ | ||||
|       packet_client_.send(function_name, request, service_flags), | ||||
|   }; | ||||
|  | ||||
|   return ret; | ||||
|   return packet_client_.send(function_name, request, service_flags); | ||||
| } | ||||
|  | ||||
| auto remote_client::json_create_directory_snapshot(const std::string &path, | ||||
| @@ -103,11 +97,7 @@ auto remote_client::json_release_directory_snapshot( | ||||
|   request.encode(handle); | ||||
|  | ||||
|   std::uint32_t service_flags{}; | ||||
|   auto ret{ | ||||
|       packet_client_.send(function_name, request, service_flags), | ||||
|   }; | ||||
|  | ||||
|   return ret; | ||||
|   return packet_client_.send(function_name, request, service_flags); | ||||
| } | ||||
|  | ||||
| auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name, | ||||
| @@ -273,8 +263,8 @@ auto remote_client::winfsp_get_security_by_name(PWSTR file_name, | ||||
|  | ||||
|   packet request; | ||||
|   request.encode(file_name); | ||||
|   request.encode(static_cast<std::uint64_t>( | ||||
|       descriptor_size == nullptr ? 0 : *descriptor_size)); | ||||
|   request.encode(descriptor_size == nullptr ? std::uint64_t(0U) | ||||
|                                             : *descriptor_size); | ||||
|   request.encode(static_cast<std::uint8_t>(attributes != nullptr)); | ||||
|  | ||||
|   packet response; | ||||
| @@ -417,7 +407,7 @@ auto remote_client::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, | ||||
|     ret = response.decode(buffer, *bytes_transferred); | ||||
| #if defined(_WIN32) | ||||
|     if ((ret == STATUS_SUCCESS) && | ||||
|         (not*bytes_transferred || (*bytes_transferred != length))) { | ||||
|         ((*bytes_transferred == 0U) || (*bytes_transferred != length))) { | ||||
|       ::SetLastError(ERROR_HANDLE_EOF); | ||||
|     } | ||||
| #endif | ||||
| @@ -461,11 +451,7 @@ auto remote_client::winfsp_rename(PVOID file_desc, PWSTR file_name, | ||||
|   request.encode(replace_if_exists); | ||||
|  | ||||
|   std::uint32_t service_flags{}; | ||||
|   auto ret{ | ||||
|       packet_client_.send(function_name, request, service_flags), | ||||
|   }; | ||||
|  | ||||
|   return ret; | ||||
|   return packet_client_.send(function_name, request, service_flags); | ||||
| } | ||||
|  | ||||
| auto remote_client::winfsp_set_basic_info( | ||||
|   | ||||
| @@ -466,6 +466,13 @@ auto file_manager::open(const std::string &api_path, bool directory, | ||||
|         return download_type::default_; | ||||
|       } | ||||
|  | ||||
|       if (utils::file::file{fsi.source_path}.exists()) { | ||||
|         auto size = utils::file::file{fsi.source_path}.size(); | ||||
|         if (size.has_value() && *size == fsi.size) { | ||||
|           return download_type::default_; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (type == download_type::direct) { | ||||
|         return type; | ||||
|       } | ||||
|   | ||||
| @@ -98,19 +98,23 @@ auto ring_buffer_base::close() -> bool { | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| auto ring_buffer_base::download_chunk(std::size_t chunk, | ||||
|                                       bool skip_active) -> api_error { | ||||
| auto ring_buffer_base::download_chunk(std::size_t chunk, bool skip_active) | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   unique_mutex_lock chunk_lock(chunk_mtx_); | ||||
|   const auto unlock_and_notify = [this, &chunk_lock]() { | ||||
|   if (not skip_active) { | ||||
|     ring_pos_ = chunk; | ||||
|   } | ||||
|  | ||||
|   const auto notify_and_unlock = [this, &chunk_lock]() { | ||||
|     chunk_notify_.notify_all(); | ||||
|     chunk_lock.unlock(); | ||||
|   }; | ||||
|  | ||||
|   const auto unlock_and_return = | ||||
|       [&unlock_and_notify](api_error res) -> api_error { | ||||
|     unlock_and_notify(); | ||||
|       [¬ify_and_unlock](api_error res) -> api_error { | ||||
|     notify_and_unlock(); | ||||
|     return res; | ||||
|   }; | ||||
|  | ||||
| @@ -124,7 +128,7 @@ auto ring_buffer_base::download_chunk(std::size_t chunk, | ||||
|     } | ||||
|  | ||||
|     auto active_download = get_active_downloads().at(chunk); | ||||
|     unlock_and_notify(); | ||||
|     notify_and_unlock(); | ||||
|  | ||||
|     return active_download->wait(); | ||||
|   } | ||||
| @@ -142,7 +146,7 @@ auto ring_buffer_base::download_chunk(std::size_t chunk, | ||||
|         chunk == (total_chunks_ - 1U) ? get_last_chunk_size() | ||||
|                                       : get_chunk_size(), | ||||
|     }; | ||||
|     unlock_and_notify(); | ||||
|     notify_and_unlock(); | ||||
|  | ||||
|     auto result{ | ||||
|         get_provider().read_file_bytes(get_api_path(), data_size, data_offset, | ||||
| @@ -167,7 +171,7 @@ auto ring_buffer_base::download_chunk(std::size_t chunk, | ||||
|     } | ||||
|  | ||||
|     get_active_downloads().erase(chunk); | ||||
|     unlock_and_notify(); | ||||
|     notify_and_unlock(); | ||||
|  | ||||
|     active_download->notify(result); | ||||
|     return result; | ||||
| @@ -226,7 +230,6 @@ auto ring_buffer_base::read(std::size_t read_size, std::uint64_t read_offset, | ||||
|     } else if (chunk < ring_pos_) { | ||||
|       reverse(ring_pos_ - chunk); | ||||
|     } | ||||
|  | ||||
|     res = download_chunk(chunk, false); | ||||
|     if (res != api_error::success) { | ||||
|       if (res == api_error::invalid_ring_buffer_position) { | ||||
| @@ -264,38 +267,46 @@ void ring_buffer_base::reader_thread() { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   unique_mutex_lock chunk_lock(chunk_mtx_); | ||||
|   auto next_chunk{ring_pos_}; | ||||
|   chunk_notify_.notify_all(); | ||||
|   chunk_lock.unlock(); | ||||
|   const auto notify_and_unlock = [this, &chunk_lock]() { | ||||
|     chunk_notify_.notify_all(); | ||||
|     chunk_lock.unlock(); | ||||
|   }; | ||||
|  | ||||
|   auto last_pos = ring_pos_; | ||||
|   auto next_chunk = ring_pos_; | ||||
|   notify_and_unlock(); | ||||
|  | ||||
|   while (not get_stop_requested()) { | ||||
|     chunk_lock.lock(); | ||||
|  | ||||
|     next_chunk = next_chunk + 1U > ring_end_ ? ring_begin_ : next_chunk + 1U; | ||||
|     const auto check_and_wait = [this, &chunk_lock, &next_chunk]() { | ||||
|     if (last_pos == ring_pos_) { | ||||
|       ++next_chunk; | ||||
|     } else { | ||||
|       next_chunk = ring_pos_ + 1U; | ||||
|       last_pos = ring_pos_; | ||||
|     } | ||||
|  | ||||
|     if (next_chunk > ring_end_) { | ||||
|       next_chunk = ring_begin_; | ||||
|     } | ||||
|  | ||||
|     if (read_state_[next_chunk % read_state_.size()]) { | ||||
|       if (get_stop_requested()) { | ||||
|         chunk_notify_.notify_all(); | ||||
|         chunk_lock.unlock(); | ||||
|         notify_and_unlock(); | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       if (get_read_state().all()) { | ||||
|         chunk_notify_.wait(chunk_lock); | ||||
|         last_pos = ring_pos_; | ||||
|         next_chunk = ring_pos_; | ||||
|       } | ||||
|  | ||||
|       chunk_notify_.notify_all(); | ||||
|       chunk_lock.unlock(); | ||||
|     }; | ||||
|  | ||||
|     if (read_state_[next_chunk % read_state_.size()]) { | ||||
|       check_and_wait(); | ||||
|       notify_and_unlock(); | ||||
|       continue; | ||||
|     } | ||||
|  | ||||
|     chunk_notify_.notify_all(); | ||||
|     chunk_lock.unlock(); | ||||
|  | ||||
|     notify_and_unlock(); | ||||
|     download_chunk(next_chunk, true); | ||||
|   } | ||||
|  | ||||
| @@ -351,30 +362,31 @@ void ring_buffer_base::update_position(std::size_t count, bool is_forward) { | ||||
|   if (is_forward ? (ring_pos_ + count) <= ring_end_ | ||||
|                  : (ring_pos_ - count) >= ring_begin_) { | ||||
|     ring_pos_ += is_forward ? count : -count; | ||||
|   } else { | ||||
|     auto delta = is_forward ? count - (ring_end_ - ring_pos_) | ||||
|                             : count - (ring_pos_ - ring_begin_); | ||||
|  | ||||
|     if (delta >= read_state_.size()) { | ||||
|       read_state_.set(0U, read_state_.size(), false); | ||||
|       ring_pos_ += is_forward ? count : -count; | ||||
|       ring_begin_ += is_forward ? delta : -delta; | ||||
|     } else { | ||||
|       for (std::size_t idx = 0U; idx < delta; ++idx) { | ||||
|         if (is_forward) { | ||||
|           read_state_[(ring_begin_ + idx) % read_state_.size()] = false; | ||||
|         } else { | ||||
|           read_state_[(ring_end_ - idx) % read_state_.size()] = false; | ||||
|         } | ||||
|       } | ||||
|       ring_begin_ += is_forward ? delta : -delta; | ||||
|       ring_pos_ += is_forward ? count : -count; | ||||
|     } | ||||
|  | ||||
|     ring_end_ = | ||||
|         std::min(total_chunks_ - 1U, ring_begin_ + read_state_.size() - 1U); | ||||
|     chunk_notify_.notify_all(); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   auto delta = is_forward ? count - (ring_end_ - ring_pos_) | ||||
|                           : count - (ring_pos_ - ring_begin_); | ||||
|   if (delta >= read_state_.size()) { | ||||
|     read_state_.set(0U, read_state_.size(), false); | ||||
|     ring_pos_ += is_forward ? count : -count; | ||||
|     ring_begin_ += is_forward ? delta : -delta; | ||||
|   } else { | ||||
|     for (std::size_t idx = 0U; idx < delta; ++idx) { | ||||
|       if (is_forward) { | ||||
|         read_state_[(ring_begin_ + idx) % read_state_.size()] = false; | ||||
|       } else { | ||||
|         read_state_[(ring_end_ - idx) % read_state_.size()] = false; | ||||
|       } | ||||
|     } | ||||
|     ring_begin_ += is_forward ? delta : -delta; | ||||
|     ring_pos_ += is_forward ? count : -count; | ||||
|   } | ||||
|  | ||||
|   ring_end_ = | ||||
|       std::min(total_chunks_ - 1U, ring_begin_ + read_state_.size() - 1U); | ||||
|  | ||||
|   chunk_notify_.notify_all(); | ||||
| } | ||||
| } // namespace repertory | ||||
|   | ||||
| @@ -50,10 +50,6 @@ | ||||
|  | ||||
| namespace repertory { | ||||
| auto project_initialize() -> bool { | ||||
|   spdlog::drop_all(); | ||||
|   spdlog::flush_every(std::chrono::seconds(10)); | ||||
|   spdlog::set_pattern("%Y-%m-%d|%T.%e|%^%l%$|%v"); | ||||
|  | ||||
| #if defined(PROJECT_REQUIRE_ALPINE) && !defined(PROJECT_IS_MINGW) | ||||
|   { | ||||
|     static constexpr const auto guard_size{4096U}; | ||||
| @@ -68,6 +64,10 @@ auto project_initialize() -> bool { | ||||
|   } | ||||
| #endif // defined(PROJECT_REQUIRE_ALPINE) && !defined (PROJECT_IS_MINGW) | ||||
|  | ||||
|   spdlog::drop_all(); | ||||
|   spdlog::flush_every(std::chrono::seconds(10)); | ||||
|   spdlog::set_pattern("%Y-%m-%d|%T.%e|%^%l%$|%v"); | ||||
|  | ||||
| #if defined(PROJECT_ENABLE_LIBSODIUM) | ||||
|   { | ||||
|     if (sodium_init() == -1) { | ||||
| @@ -77,7 +77,9 @@ auto project_initialize() -> bool { | ||||
| #endif // defined(PROJECT_ENABLE_LIBSODIUM) | ||||
|  | ||||
| #if defined(PROJECT_ENABLE_OPENSSL) | ||||
|   { SSL_library_init(); } | ||||
|   { | ||||
|     SSL_library_init(); | ||||
|   } | ||||
| #endif // defined(PROJECT_ENABLE_OPENSSL) | ||||
|  | ||||
| #if defined(PROJECT_ENABLE_CURL) | ||||
|   | ||||
| @@ -34,6 +34,7 @@ | ||||
| #include "events/types/orphaned_file_processing_failed.hpp" | ||||
| #include "events/types/orphaned_source_file_detected.hpp" | ||||
| #include "events/types/orphaned_source_file_removed.hpp" | ||||
| #include "events/types/provider_invalid_version.hpp" | ||||
| #include "events/types/provider_offline.hpp" | ||||
| #include "events/types/provider_upload_begin.hpp" | ||||
| #include "events/types/provider_upload_end.hpp" | ||||
| @@ -69,8 +70,8 @@ void base_provider::add_all_items(stop_type &stop_requested) { | ||||
| } | ||||
|  | ||||
| auto base_provider::create_api_file(std::string path, std::string key, | ||||
|                                     std::uint64_t size, | ||||
|                                     std::uint64_t file_time) -> api_file { | ||||
|                                     std::uint64_t size, std::uint64_t file_time) | ||||
|     -> api_file { | ||||
|   api_file file{}; | ||||
|   file.api_path = utils::path::create_api_path(path); | ||||
|   file.api_parent = utils::path::get_parent_api_path(file.api_path); | ||||
| @@ -102,8 +103,8 @@ auto base_provider::create_api_file(std::string path, std::uint64_t size, | ||||
| } | ||||
|  | ||||
| auto base_provider::create_directory_clone_source_meta( | ||||
|     const std::string &source_api_path, | ||||
|     const std::string &api_path) -> api_error { | ||||
|     const std::string &source_api_path, const std::string &api_path) | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   bool exists{}; | ||||
| @@ -201,8 +202,8 @@ auto base_provider::create_directory(const std::string &api_path, | ||||
|   return api_error::error; | ||||
| } | ||||
|  | ||||
| auto base_provider::create_file(const std::string &api_path, | ||||
|                                 api_meta_map &meta) -> api_error { | ||||
| auto base_provider::create_file(const std::string &api_path, api_meta_map &meta) | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   try { | ||||
| @@ -259,8 +260,9 @@ auto base_provider::create_file(const std::string &api_path, | ||||
|   return api_error::error; | ||||
| } | ||||
|  | ||||
| auto base_provider::get_api_path_from_source( | ||||
|     const std::string &source_path, std::string &api_path) const -> api_error { | ||||
| auto base_provider::get_api_path_from_source(const std::string &source_path, | ||||
|                                              std::string &api_path) const | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   if (source_path.empty()) { | ||||
| @@ -273,8 +275,9 @@ auto base_provider::get_api_path_from_source( | ||||
|   return db3_->get_api_path(source_path, api_path); | ||||
| } | ||||
|  | ||||
| auto base_provider::get_directory_items( | ||||
|     const std::string &api_path, directory_item_list &list) const -> api_error { | ||||
| auto base_provider::get_directory_items(const std::string &api_path, | ||||
|                                         directory_item_list &list) const | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   try { | ||||
| @@ -283,8 +286,15 @@ auto base_provider::get_directory_items( | ||||
|     if (res != api_error::success) { | ||||
|       return res; | ||||
|     } | ||||
|  | ||||
|     if (not exists) { | ||||
|       return api_error::directory_not_found; | ||||
|       res = is_file(api_path, exists); | ||||
|       if (res != api_error::success) { | ||||
|         utils::error::raise_api_path_error( | ||||
|             function_name, api_path, res, "failed to determine if file exists"); | ||||
|       } | ||||
|  | ||||
|       return exists ? api_error::item_exists : api_error::directory_not_found; | ||||
|     } | ||||
|  | ||||
|     res = get_directory_items_impl(api_path, list); | ||||
| @@ -342,9 +352,10 @@ auto base_provider::get_file_size(const std::string &api_path, | ||||
|   return api_error::success; | ||||
| } | ||||
|  | ||||
| auto base_provider::get_filesystem_item( | ||||
|     const std::string &api_path, bool directory, | ||||
|     filesystem_item &fsi) const -> api_error { | ||||
| auto base_provider::get_filesystem_item(const std::string &api_path, | ||||
|                                         bool directory, | ||||
|                                         filesystem_item &fsi) const | ||||
|     -> api_error { | ||||
|   bool exists{}; | ||||
|   auto res = is_directory(api_path, exists); | ||||
|   if (res != api_error::success) { | ||||
| @@ -377,9 +388,10 @@ auto base_provider::get_filesystem_item( | ||||
|   return api_error::success; | ||||
| } | ||||
|  | ||||
| auto base_provider::get_filesystem_item_and_file( | ||||
|     const std::string &api_path, api_file &file, | ||||
|     filesystem_item &fsi) const -> api_error { | ||||
| auto base_provider::get_filesystem_item_and_file(const std::string &api_path, | ||||
|                                                  api_file &file, | ||||
|                                                  filesystem_item &fsi) const | ||||
|     -> api_error { | ||||
|   auto res = get_file(api_path, file); | ||||
|   if (res != api_error::success) { | ||||
|     return res; | ||||
| @@ -829,6 +841,14 @@ auto base_provider::start(api_item_added_callback api_item_added, | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   std::string returned_version; | ||||
|   std::string required_version; | ||||
|   if (not check_version(required_version, returned_version)) { | ||||
|     event_system::instance().raise<provider_invalid_version>( | ||||
|         function_name, required_version, returned_version); | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   cache_size_mgr::instance().initialize(&config_); | ||||
|  | ||||
|   polling::instance().set_callback({ | ||||
|   | ||||
| @@ -40,6 +40,7 @@ | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/polling.hpp" | ||||
| #include <spdlog/fmt/bundled/base.h> | ||||
|  | ||||
| namespace repertory { | ||||
| encrypt_provider::encrypt_provider(app_config &config) | ||||
| @@ -262,7 +263,6 @@ auto encrypt_provider::get_directory_items(const std::string &api_path, | ||||
|               dir_item.api_parent = file.api_parent; | ||||
|               dir_item.api_path = file.api_path; | ||||
|               dir_item.directory = dir_entry->is_directory_item(); | ||||
|               dir_item.resolved = true; | ||||
|               dir_item.size = file.file_size; | ||||
|               create_item_meta(dir_item.meta, dir_item.directory, file); | ||||
|  | ||||
| @@ -342,13 +342,23 @@ auto encrypt_provider::get_file_list(api_file_list &list, | ||||
|   const auto &cfg{get_encrypt_config()}; | ||||
|  | ||||
|   try { | ||||
|     for (const auto &dir_entry : utils::file::directory{cfg.path}.get_items()) { | ||||
|       std::string api_path{}; | ||||
|       if (process_directory_entry(*dir_entry.get(), cfg, api_path)) { | ||||
|         list.emplace_back(create_api_file( | ||||
|             api_path, dir_entry->is_directory_item(), dir_entry->get_path())); | ||||
|     using func = std::function<void(std::string path)>; | ||||
|     const func process_directory = [&](std::string path) { | ||||
|       for (const auto &dir_entry : utils::file::directory{path}.get_items()) { | ||||
|         std::string api_path{}; | ||||
|         if (dir_entry->is_directory_item()) { | ||||
|           process_directory_entry(*dir_entry.get(), cfg, api_path); | ||||
|           process_directory(dir_entry->get_path()); | ||||
|           continue; | ||||
|         } | ||||
|  | ||||
|         if (process_directory_entry(*dir_entry.get(), cfg, api_path)) { | ||||
|           list.emplace_back(create_api_file( | ||||
|               api_path, dir_entry->is_directory_item(), dir_entry->get_path())); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     }; | ||||
|     process_directory(cfg.path); | ||||
|  | ||||
|     return api_error::success; | ||||
|   } catch (const std::exception &ex) { | ||||
|   | ||||
| @@ -43,9 +43,9 @@ | ||||
| #include "utils/time.hpp" | ||||
|  | ||||
| namespace { | ||||
| [[nodiscard]] auto | ||||
| set_request_path(auto &request, | ||||
|                  const std::string &object_name) -> repertory::api_error { | ||||
| [[nodiscard]] auto set_request_path(auto &request, | ||||
|                                     const std::string &object_name) | ||||
|     -> repertory::api_error { | ||||
|   request.path = object_name; | ||||
|   if (request.path.substr(1U).size() > repertory::max_s3_object_name_length) { | ||||
|     return repertory::api_error::name_too_long; | ||||
| @@ -59,8 +59,9 @@ namespace repertory { | ||||
| s3_provider::s3_provider(app_config &config, i_http_comm &comm) | ||||
|     : base_provider(config, comm) {} | ||||
|  | ||||
| auto s3_provider::add_if_not_found( | ||||
|     api_file &file, const std::string &object_name) const -> api_error { | ||||
| auto s3_provider::add_if_not_found(api_file &file, | ||||
|                                    const std::string &object_name) const | ||||
|     -> api_error { | ||||
|   api_meta_map meta{}; | ||||
|   auto res{get_item_meta(file.api_path, meta)}; | ||||
|   if (res == api_error::item_not_found) { | ||||
| @@ -88,7 +89,7 @@ auto s3_provider::convert_api_date(std::string_view date) -> std::uint64_t { | ||||
|                 1000000UL, | ||||
|   }; | ||||
|  | ||||
|   struct tm tm1 {}; | ||||
|   struct tm tm1{}; | ||||
| #if defined(_WIN32) | ||||
|   utils::time::strptime(date_time.c_str(), "%Y-%m-%dT%T", &tm1); | ||||
|   return nanos + utils::time::windows_time_t_to_unix_time(_mkgmtime(&tm1)); | ||||
| @@ -157,8 +158,9 @@ auto s3_provider::create_directory_impl(const std::string &api_path, | ||||
|       utils::path::create_api_path(is_encrypted ? meta[META_KEY] : api_path)); | ||||
| } | ||||
|  | ||||
| auto s3_provider::create_directory_paths( | ||||
|     const std::string &api_path, const std::string &key) const -> api_error { | ||||
| auto s3_provider::create_directory_paths(const std::string &api_path, | ||||
|                                          const std::string &key) const | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   if (api_path == "/") { | ||||
| @@ -321,8 +323,9 @@ auto s3_provider::get_directory_item_count(const std::string &api_path) const | ||||
|   return 0U; | ||||
| } | ||||
|  | ||||
| auto s3_provider::get_directory_items_impl( | ||||
|     const std::string &api_path, directory_item_list &list) const -> api_error { | ||||
| auto s3_provider::get_directory_items_impl(const std::string &api_path, | ||||
|                                            directory_item_list &list) const | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   const auto &cfg{get_s3_config()}; | ||||
| @@ -480,8 +483,8 @@ auto s3_provider::get_directory_items_impl( | ||||
|   return api_error::success; | ||||
| } | ||||
|  | ||||
| auto s3_provider::get_file(const std::string &api_path, | ||||
|                            api_file &file) const -> api_error { | ||||
| auto s3_provider::get_file(const std::string &api_path, api_file &file) const | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   try { | ||||
| @@ -492,7 +495,19 @@ auto s3_provider::get_file(const std::string &api_path, | ||||
|         get_object_info(false, api_path, is_encrypted, object_name, result), | ||||
|     }; | ||||
|     if (res != api_error::success) { | ||||
|       return res; | ||||
|       if (res != api_error::item_not_found) { | ||||
|         return res; | ||||
|       } | ||||
|  | ||||
|       bool exists{}; | ||||
|       res = is_directory(api_path, exists); | ||||
|       if (res != api_error::success) { | ||||
|         utils::error::raise_api_path_error( | ||||
|             function_name, api_path, res, | ||||
|             "failed to determine if directory exists"); | ||||
|       } | ||||
|  | ||||
|       return exists ? api_error::directory_exists : api_error::item_not_found; | ||||
|     } | ||||
|  | ||||
|     file.api_path = api_path; | ||||
| @@ -521,8 +536,8 @@ auto s3_provider::get_file(const std::string &api_path, | ||||
|   return api_error::error; | ||||
| } | ||||
|  | ||||
| auto s3_provider::get_file_list(api_file_list &list, | ||||
|                                 std::string &marker) const -> api_error { | ||||
| auto s3_provider::get_file_list(api_file_list &list, std::string &marker) const | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   try { | ||||
| @@ -612,8 +627,9 @@ auto s3_provider::get_file_list(api_file_list &list, | ||||
|   return api_error::error; | ||||
| } | ||||
|  | ||||
| auto s3_provider::get_last_modified( | ||||
|     bool directory, const std::string &api_path) const -> std::uint64_t { | ||||
| auto s3_provider::get_last_modified(bool directory, | ||||
|                                     const std::string &api_path) const | ||||
|     -> std::uint64_t { | ||||
|   bool is_encrypted{}; | ||||
|   std::string object_name; | ||||
|   head_object_result result{}; | ||||
| @@ -623,9 +639,10 @@ auto s3_provider::get_last_modified( | ||||
|              : utils::time::get_time_now(); | ||||
| } | ||||
|  | ||||
| auto s3_provider::get_object_info( | ||||
|     bool directory, const std::string &api_path, bool &is_encrypted, | ||||
|     std::string &object_name, head_object_result &result) const -> api_error { | ||||
| auto s3_provider::get_object_info(bool directory, const std::string &api_path, | ||||
|                                   bool &is_encrypted, std::string &object_name, | ||||
|                                   head_object_result &result) const | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   try { | ||||
| @@ -685,10 +702,12 @@ auto s3_provider::get_object_info( | ||||
|   return api_error::error; | ||||
| } | ||||
|  | ||||
| auto s3_provider::get_object_list( | ||||
|     std::string &response_data, long &response_code, | ||||
|     std::optional<std::string> delimiter, std::optional<std::string> prefix, | ||||
|     std::optional<std::string> token) const -> bool { | ||||
| auto s3_provider::get_object_list(std::string &response_data, | ||||
|                                   long &response_code, | ||||
|                                   std::optional<std::string> delimiter, | ||||
|                                   std::optional<std::string> prefix, | ||||
|                                   std::optional<std::string> token) const | ||||
|     -> bool { | ||||
|   curl::requests::http_get get{}; | ||||
|   get.allow_timeout = true; | ||||
|   get.aws_service = "aws:amz:" + get_s3_config().region + ":s3"; | ||||
| @@ -716,8 +735,8 @@ auto s3_provider::get_total_drive_space() const -> std::uint64_t { | ||||
|   return std::numeric_limits<std::int64_t>::max() / std::int64_t(2); | ||||
| } | ||||
|  | ||||
| auto s3_provider::is_directory(const std::string &api_path, | ||||
|                                bool &exists) const -> api_error { | ||||
| auto s3_provider::is_directory(const std::string &api_path, bool &exists) const | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   try { | ||||
| @@ -745,8 +764,8 @@ auto s3_provider::is_directory(const std::string &api_path, | ||||
|   return api_error::error; | ||||
| } | ||||
|  | ||||
| auto s3_provider::is_file(const std::string &api_path, | ||||
|                           bool &exists) const -> api_error { | ||||
| auto s3_provider::is_file(const std::string &api_path, bool &exists) const | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   try { | ||||
| @@ -1004,8 +1023,8 @@ auto s3_provider::rename_file(const std::string & /* from_api_path */, | ||||
|   return api_error::not_implemented; | ||||
| } | ||||
|  | ||||
| auto s3_provider::set_meta_key(const std::string &api_path, | ||||
|                                api_meta_map &meta) -> api_error { | ||||
| auto s3_provider::set_meta_key(const std::string &api_path, api_meta_map &meta) | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   const auto &cfg{get_s3_config()}; | ||||
|   | ||||
| @@ -32,8 +32,8 @@ | ||||
| #include "providers/base_provider.hpp" | ||||
| #include "providers/s3/s3_provider.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/common.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
| #include "utils/polling.hpp" | ||||
| #include "utils/string.hpp" | ||||
| @@ -63,6 +63,54 @@ namespace repertory { | ||||
| sia_provider::sia_provider(app_config &config, i_http_comm &comm) | ||||
|     : base_provider(config, comm) {} | ||||
|  | ||||
| auto sia_provider::check_version(std::string &required_version, | ||||
|                                  std::string &returned_version) const -> bool { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   required_version = "2.0.0"; | ||||
|  | ||||
|   try { | ||||
|     curl::requests::http_get get{}; | ||||
|     get.allow_timeout = true; | ||||
|     get.path = "/api/bus/state"; | ||||
|  | ||||
|     nlohmann::json state_data; | ||||
|     std::string error_data; | ||||
|     get.response_handler = [&error_data, &state_data](auto &&data, | ||||
|                                                       long response_code) { | ||||
|       if (response_code == http_error_codes::ok) { | ||||
|         state_data = nlohmann::json::parse(data.begin(), data.end()); | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       error_data = std::string(data.begin(), data.end()); | ||||
|     }; | ||||
|  | ||||
|     long response_code{}; | ||||
|     stop_type stop_requested{}; | ||||
|     if (not get_comm().make_request(get, response_code, stop_requested)) { | ||||
|       utils::error::raise_error(function_name, response_code, | ||||
|                                 "failed to check state"); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (response_code != http_error_codes::ok) { | ||||
|       utils::error::raise_error( | ||||
|           function_name, response_code, | ||||
|           fmt::format("failed to check state|response|{}", error_data)); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     returned_version = state_data.at("version").get<std::string>().substr(1U); | ||||
|     return utils::compare_version_strings(returned_version, required_version) >= | ||||
|            0; | ||||
|   } catch (const std::exception &e) { | ||||
|     utils::error::raise_error(function_name, e, "failed to check version"); | ||||
|   } | ||||
|  | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| auto sia_provider::create_directory_impl(const std::string &api_path, | ||||
|                                          api_meta_map & /* meta */) | ||||
|     -> api_error { | ||||
| @@ -70,7 +118,7 @@ auto sia_provider::create_directory_impl(const std::string &api_path, | ||||
|  | ||||
|   curl::requests::http_put_file put_file{}; | ||||
|   put_file.allow_timeout = true; | ||||
|   put_file.path = "/api/worker/objects" + api_path + "/"; | ||||
|   put_file.path = "/api/worker/object" + api_path + "/"; | ||||
|   put_file.query["bucket"] = get_bucket(get_sia_config()); | ||||
|  | ||||
|   std::string error_data; | ||||
| @@ -112,10 +160,10 @@ auto sia_provider::get_directory_item_count(const std::string &api_path) const | ||||
|     } | ||||
|  | ||||
|     std::uint64_t item_count{}; | ||||
|     if (object_list.contains("entries")) { | ||||
|       for (const auto &entry : object_list.at("entries")) { | ||||
|     if (object_list.contains("objects")) { | ||||
|       for (const auto &entry : object_list.at("objects")) { | ||||
|         try { | ||||
|           auto name{entry.at("name").get<std::string>()}; | ||||
|           auto name{entry.at("key").get<std::string>()}; | ||||
|           auto entry_api_path{utils::path::create_api_path(name)}; | ||||
|           if (utils::string::ends_with(name, "/") && | ||||
|               (entry_api_path == api_path)) { | ||||
| @@ -149,10 +197,10 @@ auto sia_provider::get_directory_items_impl(const std::string &api_path, | ||||
|     return api_error::comm_error; | ||||
|   } | ||||
|  | ||||
|   if (object_list.contains("entries")) { | ||||
|     for (const auto &entry : object_list.at("entries")) { | ||||
|   if (object_list.contains("objects")) { | ||||
|     for (const auto &entry : object_list.at("objects")) { | ||||
|       try { | ||||
|         auto name{entry.at("name").get<std::string>()}; | ||||
|         auto name{entry.at("key").get<std::string>()}; | ||||
|         auto entry_api_path{utils::path::create_api_path(name)}; | ||||
|  | ||||
|         auto directory{utils::string::ends_with(name, "/")}; | ||||
| @@ -185,7 +233,6 @@ auto sia_provider::get_directory_items_impl(const std::string &api_path, | ||||
|         dir_item.api_path = file.api_path; | ||||
|         dir_item.directory = directory; | ||||
|         dir_item.meta = meta; | ||||
|         dir_item.resolved = true; | ||||
|         dir_item.size = file.file_size; | ||||
|         list.emplace_back(std::move(dir_item)); | ||||
|       } catch (const std::exception &e) { | ||||
| @@ -207,22 +254,28 @@ auto sia_provider::get_file(const std::string &api_path, api_file &file) const | ||||
|     json file_data{}; | ||||
|     auto res{get_object_info(api_path, file_data)}; | ||||
|     if (res != api_error::success) { | ||||
|       return res; | ||||
|       if (res != api_error::item_not_found) { | ||||
|         return res; | ||||
|       } | ||||
|  | ||||
|       bool exists{}; | ||||
|       res = is_directory(api_path, exists); | ||||
|       if (res != api_error::success) { | ||||
|         utils::error::raise_api_path_error( | ||||
|             function_name, api_path, res, | ||||
|             "failed to determine if directory exists"); | ||||
|       } | ||||
|  | ||||
|       return exists ? api_error::directory_exists : api_error::item_not_found; | ||||
|     } | ||||
|  | ||||
|     auto slabs{file_data["object"]["Slabs"]}; | ||||
|     auto size{ | ||||
|         std::accumulate( | ||||
|             slabs.begin(), slabs.end(), std::uint64_t(0U), | ||||
|             [](auto &&total_size, const json &slab) -> std::uint64_t { | ||||
|               return total_size + slab["Length"].get<std::uint64_t>(); | ||||
|             }), | ||||
|         file_data.at("size").get<std::uint64_t>(), | ||||
|     }; | ||||
|  | ||||
|     api_meta_map meta{}; | ||||
|     if (get_item_meta(api_path, meta) == api_error::item_not_found) { | ||||
|       file = create_api_file(api_path, "", size, | ||||
|                              get_last_modified(file_data["object"])); | ||||
|       file = create_api_file(api_path, "", size, get_last_modified(file_data)); | ||||
|       get_api_item_added()(false, file); | ||||
|     } else { | ||||
|       file = create_api_file(api_path, size, meta); | ||||
| @@ -250,9 +303,9 @@ auto sia_provider::get_file_list(api_file_list &list, | ||||
|         return api_error::comm_error; | ||||
|       } | ||||
|  | ||||
|       if (object_list.contains("entries")) { | ||||
|         for (const auto &entry : object_list.at("entries")) { | ||||
|           auto name{entry.at("name").get<std::string>()}; | ||||
|       if (object_list.contains("objects")) { | ||||
|         for (const auto &entry : object_list.at("objects")) { | ||||
|           auto name{entry.at("key").get<std::string>()}; | ||||
|           auto entry_api_path{utils::path::create_api_path(name)}; | ||||
|  | ||||
|           if (utils::string::ends_with(name, "/")) { | ||||
| @@ -313,8 +366,9 @@ auto sia_provider::get_object_info(const std::string &api_path, | ||||
|   try { | ||||
|     curl::requests::http_get get{}; | ||||
|     get.allow_timeout = true; | ||||
|     get.path = "/api/bus/objects" + api_path; | ||||
|     get.path = "/api/bus/object" + api_path; | ||||
|     get.query["bucket"] = get_bucket(get_sia_config()); | ||||
|     get.query["onlymetadata"] = "true"; | ||||
|  | ||||
|     std::string error_data; | ||||
|     get.response_handler = [&error_data, &object_info](auto &&data, | ||||
| @@ -362,6 +416,7 @@ auto sia_provider::get_object_list(const std::string &api_path, | ||||
|     get.allow_timeout = true; | ||||
|     get.path = "/api/bus/objects" + api_path + "/"; | ||||
|     get.query["bucket"] = get_bucket(get_sia_config()); | ||||
|     get.query["delimiter"] = "/"; | ||||
|  | ||||
|     std::string error_data; | ||||
|     get.response_handler = [&error_data, &object_list](auto &&data, | ||||
| @@ -405,7 +460,7 @@ auto sia_provider::get_total_drive_space() const -> std::uint64_t { | ||||
|   try { | ||||
|     curl::requests::http_get get{}; | ||||
|     get.allow_timeout = true; | ||||
|     get.path = "/api/autopilot/config"; | ||||
|     get.path = "/api/bus/autopilot"; | ||||
|     get.query["bucket"] = get_bucket(get_sia_config()); | ||||
|  | ||||
|     json config_data; | ||||
| @@ -455,17 +510,18 @@ auto sia_provider::is_directory(const std::string &api_path, bool &exists) const | ||||
|  | ||||
|     exists = false; | ||||
|  | ||||
|     json object_list{}; | ||||
|     if (not get_object_list(utils::path::get_parent_api_path(api_path), | ||||
|                             object_list)) { | ||||
|       return api_error::comm_error; | ||||
|     json file_data{}; | ||||
|     auto res{get_object_info(api_path + '/', file_data)}; | ||||
|     if (res == api_error::item_not_found) { | ||||
|       return api_error::success; | ||||
|     } | ||||
|  | ||||
|     exists = object_list.contains("entries") && | ||||
|              std::ranges::find_if(object_list.at("entries"), | ||||
|                                   [&api_path](auto &&entry) -> bool { | ||||
|                                     return entry.at("name") == (api_path + "/"); | ||||
|                                   }) != object_list.at("entries").end(); | ||||
|     if (res != api_error::success) { | ||||
|       return res; | ||||
|     } | ||||
|  | ||||
|     exists = | ||||
|         utils::string::ends_with(file_data.at("key").get<std::string>(), "/"); | ||||
|     return api_error::success; | ||||
|   } catch (const std::exception &e) { | ||||
|     utils::error::raise_api_path_error( | ||||
| @@ -481,6 +537,7 @@ auto sia_provider::is_file(const std::string &api_path, bool &exists) const | ||||
|  | ||||
|   try { | ||||
|     exists = false; | ||||
|  | ||||
|     if (api_path == "/") { | ||||
|       return api_error::success; | ||||
|     } | ||||
| @@ -495,7 +552,8 @@ auto sia_provider::is_file(const std::string &api_path, bool &exists) const | ||||
|       return res; | ||||
|     } | ||||
|  | ||||
|     exists = not file_data.contains("entries"); | ||||
|     exists = not utils::string::ends_with( | ||||
|         file_data.at("key").get<std::string>(), "/"); | ||||
|     return api_error::success; | ||||
|   } catch (const std::exception &e) { | ||||
|     utils::error::raise_api_path_error(function_name, api_path, e, | ||||
| @@ -559,8 +617,9 @@ auto sia_provider::read_file_bytes(const std::string &api_path, | ||||
|  | ||||
|   try { | ||||
|     curl::requests::http_get get{}; | ||||
|     get.path = "/api/worker/objects" + api_path; | ||||
|     get.path = "/api/worker/object" + api_path; | ||||
|     get.query["bucket"] = get_bucket(get_sia_config()); | ||||
|     get.headers["accept"] = "application/octet-stream"; | ||||
|     get.range = {{ | ||||
|         offset, | ||||
|         offset + size - 1U, | ||||
| @@ -577,6 +636,7 @@ auto sia_provider::read_file_bytes(const std::string &api_path, | ||||
|          ++idx) { | ||||
|       long response_code{}; | ||||
|       const auto notify_retry = [&]() { | ||||
|         fmt::println("{}", std::string(buffer.begin(), buffer.end())); | ||||
|         if (response_code == 0) { | ||||
|           utils::error::raise_api_path_error( | ||||
|               function_name, api_path, api_error::comm_error, | ||||
| @@ -622,7 +682,7 @@ auto sia_provider::remove_directory_impl(const std::string &api_path) | ||||
|  | ||||
|   curl::requests::http_delete del{}; | ||||
|   del.allow_timeout = true; | ||||
|   del.path = "/api/bus/objects" + api_path + "/"; | ||||
|   del.path = "/api/bus/object" + api_path + "/"; | ||||
|   del.query["bucket"] = get_bucket(get_sia_config()); | ||||
|  | ||||
|   std::string error_data; | ||||
| @@ -658,7 +718,7 @@ auto sia_provider::remove_file_impl(const std::string &api_path) -> api_error { | ||||
|  | ||||
|   curl::requests::http_delete del{}; | ||||
|   del.allow_timeout = true; | ||||
|   del.path = "/api/bus/objects" + api_path; | ||||
|   del.path = "/api/bus/object" + api_path; | ||||
|   del.query["bucket"] = get_bucket(get_sia_config()); | ||||
|  | ||||
|   std::string error_data; | ||||
| @@ -697,12 +757,12 @@ auto sia_provider::rename_file(const std::string &from_api_path, | ||||
|   try { | ||||
|     curl::requests::http_post post{}; | ||||
|     post.json = nlohmann::json({ | ||||
|         {"bucket", get_bucket(get_sia_config())}, | ||||
|         {"from", from_api_path}, | ||||
|         {"to", to_api_path}, | ||||
|         {"mode", "single"}, | ||||
|     }); | ||||
|     post.path = "/api/bus/objects/rename"; | ||||
|     post.query["bucket"] = get_bucket(get_sia_config()); | ||||
|  | ||||
|     std::string error_data; | ||||
|     post.response_handler = [&error_data](auto &&data, long response_code) { | ||||
| @@ -770,8 +830,9 @@ auto sia_provider::upload_file_impl(const std::string &api_path, | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   curl::requests::http_put_file put_file{}; | ||||
|   put_file.path = "/api/worker/objects" + api_path; | ||||
|   put_file.path = "/api/worker/object" + api_path; | ||||
|   put_file.query["bucket"] = get_bucket(get_sia_config()); | ||||
|   put_file.headers["content-type"] = "application/octet-stream"; | ||||
|   put_file.source_path = source_path; | ||||
|  | ||||
|   std::string error_data; | ||||
|   | ||||
| @@ -38,47 +38,58 @@ void polling::frequency_thread( | ||||
|     std::function<std::uint32_t()> get_frequency_seconds, frequency freq) { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   auto last_run = std::chrono::system_clock::time_point::min(); | ||||
|   while (not get_stop_requested()) { | ||||
|     unique_mutex_lock lock(mutex_); | ||||
|     auto futures = std::accumulate( | ||||
|         items_.begin(), items_.end(), std::deque<tasks::task_ptr>{}, | ||||
|         [this, &freq](auto &&list, auto &&item) -> auto { | ||||
|           if (item.second.freq != freq) { | ||||
|     auto elapsed = std::chrono::duration_cast<std::chrono::seconds>( | ||||
|         std::chrono::system_clock::now() - last_run); | ||||
|     auto max_elapsed = std::chrono::seconds(get_frequency_seconds()); | ||||
|  | ||||
|     if (last_run == std::chrono::system_clock::time_point::min() || | ||||
|         elapsed >= max_elapsed) { | ||||
|       unique_mutex_lock lock(mutex_); | ||||
|       auto futures = std::accumulate( | ||||
|           items_.begin(), items_.end(), std::deque<tasks::task_ptr>{}, | ||||
|           [this, &freq](auto &&list, auto &&item) -> auto { | ||||
|             if (item.second.freq != freq) { | ||||
|               return list; | ||||
|             } | ||||
|  | ||||
|             auto future = tasks::instance().schedule({ | ||||
|                 [this, &freq, item](auto &&task_stopped) { | ||||
|                   if (config_->get_event_level() == event_level::trace || | ||||
|                       freq != frequency::second) { | ||||
|                     event_system::instance().raise<polling_item_begin>( | ||||
|                         function_name, item.first); | ||||
|                   } | ||||
|                   item.second.action(task_stopped); | ||||
|                   if (config_->get_event_level() == event_level::trace || | ||||
|                       freq != frequency::second) { | ||||
|                     event_system::instance().raise<polling_item_end>( | ||||
|                         function_name, item.first); | ||||
|                   } | ||||
|                 }, | ||||
|             }); | ||||
|  | ||||
|             list.emplace_back(future); | ||||
|             return list; | ||||
|           } | ||||
|  | ||||
|           auto future = tasks::instance().schedule({ | ||||
|               [this, &freq, item](auto &&task_stopped) { | ||||
|                 if (config_->get_event_level() == event_level::trace || | ||||
|                     freq != frequency::second) { | ||||
|                   event_system::instance().raise<polling_item_begin>( | ||||
|                       function_name, item.first); | ||||
|                 } | ||||
|                 item.second.action(task_stopped); | ||||
|                 if (config_->get_event_level() == event_level::trace || | ||||
|                     freq != frequency::second) { | ||||
|                   event_system::instance().raise<polling_item_end>( | ||||
|                       function_name, item.first); | ||||
|                 } | ||||
|               }, | ||||
|           }); | ||||
|       lock.unlock(); | ||||
|  | ||||
|           list.emplace_back(future); | ||||
|           return list; | ||||
|         }); | ||||
|     lock.unlock(); | ||||
|       while (not futures.empty()) { | ||||
|         futures.front()->wait(); | ||||
|         futures.pop_front(); | ||||
|       } | ||||
|  | ||||
|     while (not futures.empty()) { | ||||
|       futures.front()->wait(); | ||||
|       futures.pop_front(); | ||||
|       last_run = std::chrono::system_clock::now(); | ||||
|       elapsed = std::chrono::seconds(0U); | ||||
|     } | ||||
|  | ||||
|     unique_mutex_lock lock(mutex_); | ||||
|     if (get_stop_requested()) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     lock.lock(); | ||||
|     notify_.wait_for(lock, std::chrono::seconds(get_frequency_seconds())); | ||||
|     notify_.wait_for(lock, max_elapsed - elapsed); | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -23,50 +23,38 @@ | ||||
| #define REPERTORY_INCLUDE_CLI_CHECK_VERSION_HPP_ | ||||
|  | ||||
| #include "app_config.hpp" | ||||
| #include "comm/curl/curl_comm.hpp" | ||||
| #include "providers/sia/sia_provider.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory::cli::actions { | ||||
| [[nodiscard]] inline auto | ||||
| check_version(std::vector<const char *> /* args */, | ||||
|               const std::string & /* data_directory */, | ||||
|               const provider_type & /* pt */, const std::string & /*unique_id*/, | ||||
|               std::string /*user*/, std::string /*password*/) -> exit_code { | ||||
|   auto ret = exit_code::success; | ||||
| [[nodiscard]] inline auto check_version(std::vector<const char *> /* args */, | ||||
|                                         const std::string &data_directory, | ||||
|                                         const provider_type &prov, | ||||
|                                         const std::string & /*unique_id*/, | ||||
|                                         std::string /*user*/, | ||||
|                                         std::string /*password*/) -> exit_code { | ||||
|   if (prov != provider_type::sia) { | ||||
|     fmt::println("Success:\n\tNo specific version is required for {} providers", | ||||
|                  app_config::get_provider_display_name(prov)); | ||||
|     return exit_code::success; | ||||
|   } | ||||
|  | ||||
|   // TODO need to updated way to check version | ||||
|   // if (not((pt == provider_type::remote) || (pt == provider_type::s3))) { | ||||
|   //   app_config config(pt, data_directory); | ||||
|   //   curl_comm comm(config); | ||||
|   //   json data, err; | ||||
|   // | ||||
|   //   if (comm.get("/daemon/version", data, err) == api_error::success) { | ||||
|   //     const auto res = utils::compare_version_strings( | ||||
|   //         data["version"].get<std::string>(), | ||||
|   //         app_config::get_provider_minimum_version(pt)); | ||||
|   //     if (res < 0) { | ||||
|   //       ret = exit_code::incompatible_version; | ||||
|   //       std::cerr << "Failed!" << std::endl; | ||||
|   //       std::cerr << "   Actual: " << data["version"].get<std::string>() | ||||
|   //                 << std::endl; | ||||
|   //       std::cerr << "  Minimum: " | ||||
|   //                 << app_config::get_provider_minimum_version(pt) << | ||||
|   //                 std::endl; | ||||
|   //     } else { | ||||
|   //       std::cout << "Success!" << std::endl; | ||||
|   //       std::cout << "   Actual: " << data["version"].get<std::string>() | ||||
|   //                 << std::endl; | ||||
|   //       std::cout << "  Minimum: " | ||||
|   //                 << app_config::get_provider_minimum_version(pt) << | ||||
|   //                 std::endl; | ||||
|   //     } | ||||
|   //   } else { | ||||
|   //     std::cerr << "Failed!" << std::endl; | ||||
|   //     std::cerr << err.dump(2) << std::endl; | ||||
|   //     ret = exit_code::communication_error; | ||||
|   //   } | ||||
|   // } | ||||
|   app_config config(prov, data_directory); | ||||
|   curl_comm comm(config.get_host_config()); | ||||
|   sia_provider provider(config, comm); | ||||
|  | ||||
|   return ret; | ||||
|   std::string required_version; | ||||
|   std::string returned_version; | ||||
|   if (provider.check_version(required_version, returned_version)) { | ||||
|     fmt::println("Success:\n\tRequired: {}\n\tActual: {}", required_version, | ||||
|                  returned_version); | ||||
|     return exit_code::success; | ||||
|   } | ||||
|  | ||||
|   fmt::println("Failed:\n\tRequired: {}\n\tActual: {}", required_version, | ||||
|                returned_version); | ||||
|   return exit_code::incompatible_version; | ||||
| } | ||||
| } // namespace repertory::cli::actions | ||||
|  | ||||
|   | ||||
| @@ -268,8 +268,8 @@ public: | ||||
|     return file_path; | ||||
|   } | ||||
|  | ||||
|   static auto create_file_and_test(std::string &file_name, | ||||
|                                    mode_t perms) -> std::string { | ||||
|   static auto create_file_and_test(std::string &file_name, mode_t perms) | ||||
|       -> std::string { | ||||
|     file_name += std::to_string(++provider_idx); | ||||
|     auto file_path = utils::path::combine(mount_location, {file_name}); | ||||
|  | ||||
| @@ -287,7 +287,7 @@ public: | ||||
|     EXPECT_TRUE(utils::file::file(file_path).exists()); | ||||
|     EXPECT_FALSE(utils::file::directory(file_path).exists()); | ||||
|  | ||||
|     struct stat64 unix_st {}; | ||||
|     struct stat64 unix_st{}; | ||||
|     EXPECT_EQ(0, stat64(file_path.c_str(), &unix_st)); | ||||
|     EXPECT_EQ(getgid(), unix_st.st_gid); | ||||
|     EXPECT_EQ(getuid(), unix_st.st_uid); | ||||
| @@ -299,8 +299,8 @@ public: | ||||
|     return create_file_and_test(file_name, ACCESSPERMS); | ||||
|   } | ||||
|  | ||||
|   static auto create_directory_and_test(std::string &dir_name, | ||||
|                                         mode_t perms) -> std::string { | ||||
|   static auto create_directory_and_test(std::string &dir_name, mode_t perms) | ||||
|       -> std::string { | ||||
|     dir_name += std::to_string(++provider_idx); | ||||
|  | ||||
|     auto dir_path = utils::path::combine(mount_location, {dir_name}); | ||||
| @@ -309,7 +309,7 @@ public: | ||||
|     EXPECT_TRUE(utils::file::directory(dir_path).exists()); | ||||
|     EXPECT_FALSE(utils::file::file(dir_path).exists()); | ||||
|  | ||||
|     struct stat64 unix_st {}; | ||||
|     struct stat64 unix_st{}; | ||||
|     EXPECT_EQ(0, stat64(dir_path.c_str(), &unix_st)); | ||||
|     EXPECT_EQ(getgid(), unix_st.st_gid); | ||||
|     EXPECT_EQ(getuid(), unix_st.st_uid); | ||||
| @@ -410,9 +410,9 @@ std::string fuse_test<provider_t>::mount_location; | ||||
| template <typename provider_t> | ||||
| std::string fuse_test<provider_t>::mount_location2; | ||||
|  | ||||
| using fuse_provider_types = ::testing::Types<local_s3, remote_s3>; | ||||
| // using fuse_provider_types = | ||||
| //     ::testing::Types<local_s3, remote_s3, local_sia, remote_sia>; | ||||
| // using fuse_provider_types = ::testing::Types<local_s3, remote_s3>; | ||||
| using fuse_provider_types = | ||||
|     ::testing::Types<local_s3, remote_s3, local_sia, remote_sia>; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // !defined(_WIN32) | ||||
|   | ||||
| @@ -36,6 +36,10 @@ private: | ||||
|   const bool allow_rename_; | ||||
|  | ||||
| public: | ||||
|   MOCK_METHOD(bool, check_version, | ||||
|               (std::string & required_version, std::string &returned_version), | ||||
|               (const, override)); | ||||
|  | ||||
|   MOCK_METHOD(api_error, create_directory, | ||||
|               (const std::string &api_path, api_meta_map &meta), (override)); | ||||
|  | ||||
|   | ||||
							
								
								
									
										763
									
								
								repertory/repertory_test/src/app_config_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										763
									
								
								repertory/repertory_test/src/app_config_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,763 @@ | ||||
| /* | ||||
|  Copyright <2018-2025> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   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 "app_config.hpp" | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config_test : public ::testing::Test { | ||||
| public: | ||||
|   static std::atomic<std::uint64_t> idx; | ||||
|  | ||||
|   std::string encrypt_directory; | ||||
|   std::string remote_directory; | ||||
|   std::string s3_directory; | ||||
|   std::string sia_directory; | ||||
|  | ||||
|   void SetUp() override { | ||||
|     encrypt_directory = utils::path::combine(test::get_test_output_dir(), | ||||
|                                              { | ||||
|                                                  "app_config_test", | ||||
|                                                  "encrypt", | ||||
|                                                  std::to_string(++idx), | ||||
|                                              }); | ||||
|  | ||||
|     remote_directory = utils::path::combine(test::get_test_output_dir(), | ||||
|                                             { | ||||
|                                                 "app_config_test", | ||||
|                                                 "remote", | ||||
|                                                 std::to_string(++idx), | ||||
|                                             }); | ||||
|  | ||||
|     s3_directory = utils::path::combine(test::get_test_output_dir(), | ||||
|                                         { | ||||
|                                             "app_config_test", | ||||
|                                             "s3", | ||||
|                                             std::to_string(++idx), | ||||
|                                         }); | ||||
|  | ||||
|     sia_directory = utils::path::combine(test::get_test_output_dir(), | ||||
|                                          { | ||||
|                                              "app_config_test", | ||||
|                                              "sia", | ||||
|                                              std::to_string(++idx), | ||||
|                                          }); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| static void remove_unused_types(auto &data, provider_type prov) { | ||||
|   switch (prov) { | ||||
|   case provider_type::encrypt: | ||||
|     data.erase(JSON_DOWNLOAD_TIMEOUT_SECS); | ||||
|     data.erase(JSON_ENABLE_DOWNLOAD_TIMEOUT); | ||||
|     data.erase(JSON_EVICTION_DELAY_MINS); | ||||
|     data.erase(JSON_EVICTION_USE_ACCESS_TIME); | ||||
|     data.erase(JSON_HOST_CONFIG); | ||||
|     data.erase(JSON_MAX_CACHE_SIZE_BYTES); | ||||
|     data.erase(JSON_MAX_UPLOAD_COUNT); | ||||
|     data.erase(JSON_ONLINE_CHECK_RETRY_SECS); | ||||
|     data.erase(JSON_PREFERRED_DOWNLOAD_TYPE); | ||||
|     data.erase(JSON_REMOTE_CONFIG); | ||||
|     data.erase(JSON_RETRY_READ_COUNT); | ||||
|     data.erase(JSON_RING_BUFFER_FILE_SIZE); | ||||
|     data.erase(JSON_S3_CONFIG); | ||||
|     data.erase(JSON_SIA_CONFIG); | ||||
|     break; | ||||
|  | ||||
|   case provider_type::remote: | ||||
|     data.erase(JSON_DATABASE_TYPE); | ||||
|     data.erase(JSON_DOWNLOAD_TIMEOUT_SECS); | ||||
|     data.erase(JSON_ENABLE_DOWNLOAD_TIMEOUT); | ||||
|     data.erase(JSON_ENCRYPT_CONFIG); | ||||
|     data.erase(JSON_EVICTION_DELAY_MINS); | ||||
|     data.erase(JSON_EVICTION_USE_ACCESS_TIME); | ||||
|     data.erase(JSON_HIGH_FREQ_INTERVAL_SECS); | ||||
|     data.erase(JSON_HOST_CONFIG); | ||||
|     data.erase(JSON_LOW_FREQ_INTERVAL_SECS); | ||||
|     data.erase(JSON_MAX_CACHE_SIZE_BYTES); | ||||
|     data.erase(JSON_MAX_UPLOAD_COUNT); | ||||
|     data.erase(JSON_MED_FREQ_INTERVAL_SECS); | ||||
|     data.erase(JSON_ONLINE_CHECK_RETRY_SECS); | ||||
|     data.erase(JSON_PREFERRED_DOWNLOAD_TYPE); | ||||
|     data.erase(JSON_REMOTE_MOUNT); | ||||
|     data.erase(JSON_RETRY_READ_COUNT); | ||||
|     data.erase(JSON_RING_BUFFER_FILE_SIZE); | ||||
|     data.erase(JSON_S3_CONFIG); | ||||
|     data.erase(JSON_SIA_CONFIG); | ||||
|     break; | ||||
|  | ||||
|   case provider_type::s3: | ||||
|     data.erase(JSON_ENCRYPT_CONFIG); | ||||
|     data.erase(JSON_HOST_CONFIG); | ||||
|     data.erase(JSON_REMOTE_CONFIG); | ||||
|     data.erase(JSON_SIA_CONFIG); | ||||
|     break; | ||||
|  | ||||
|   case provider_type::sia: | ||||
|     data.erase(JSON_ENCRYPT_CONFIG); | ||||
|     data.erase(JSON_REMOTE_CONFIG); | ||||
|     data.erase(JSON_S3_CONFIG); | ||||
|     break; | ||||
|  | ||||
|   default: | ||||
|     return; | ||||
|   } | ||||
| } | ||||
|  | ||||
| std::atomic<std::uint64_t> app_config_test::idx{0U}; | ||||
|  | ||||
| static void defaults_tests(const json &json_data, provider_type prov) { | ||||
|   json json_defaults = { | ||||
|       {JSON_API_PORT, app_config::default_rpc_port(prov)}, | ||||
|       {JSON_API_USER, std::string{REPERTORY}}, | ||||
|       {JSON_DOWNLOAD_TIMEOUT_SECS, default_download_timeout_secs}, | ||||
|       {JSON_DATABASE_TYPE, database_type::rocksdb}, | ||||
|       {JSON_ENABLE_DOWNLOAD_TIMEOUT, true}, | ||||
|       {JSON_ENABLE_DRIVE_EVENTS, false}, | ||||
| #if defined(_WIN32) | ||||
|       {JSON_ENABLE_MOUNT_MANAGER, false}, | ||||
| #endif // defined(_WIN32) | ||||
|       {JSON_ENCRYPT_CONFIG, encrypt_config{}}, | ||||
|       {JSON_EVENT_LEVEL, event_level::info}, | ||||
|       {JSON_EVICTION_DELAY_MINS, default_eviction_delay_mins}, | ||||
|       {JSON_EVICTION_USE_ACCESS_TIME, false}, | ||||
|       {JSON_HIGH_FREQ_INTERVAL_SECS, default_high_freq_interval_secs}, | ||||
|       {JSON_HOST_CONFIG, host_config{}}, | ||||
|       {JSON_LOW_FREQ_INTERVAL_SECS, default_low_freq_interval_secs}, | ||||
|       {JSON_MAX_CACHE_SIZE_BYTES, default_max_cache_size_bytes}, | ||||
|       {JSON_MAX_UPLOAD_COUNT, default_max_upload_count}, | ||||
|       {JSON_MED_FREQ_INTERVAL_SECS, default_med_freq_interval_secs}, | ||||
|       {JSON_ONLINE_CHECK_RETRY_SECS, default_online_check_retry_secs}, | ||||
|       {JSON_PREFERRED_DOWNLOAD_TYPE, download_type::default_}, | ||||
|       {JSON_REMOTE_CONFIG, remote::remote_config{}}, | ||||
|       {JSON_REMOTE_MOUNT, remote::remote_mount{}}, | ||||
|       {JSON_RETRY_READ_COUNT, default_retry_read_count}, | ||||
|       {JSON_RING_BUFFER_FILE_SIZE, default_ring_buffer_file_size}, | ||||
|       {JSON_S3_CONFIG, s3_config{}}, | ||||
|       {JSON_SIA_CONFIG, sia_config{}}, | ||||
|       {JSON_TASK_WAIT_MS, default_task_wait_ms}, | ||||
|       {JSON_VERSION, REPERTORY_CONFIG_VERSION}, | ||||
|   }; | ||||
|  | ||||
|   remove_unused_types(json_defaults, prov); | ||||
|  | ||||
|   switch (prov) { | ||||
|   case provider_type::encrypt: | ||||
|     json_defaults[JSON_REMOTE_MOUNT][JSON_API_PORT] = | ||||
|         app_config::default_remote_api_port(prov); | ||||
|     break; | ||||
|  | ||||
|     json_defaults[JSON_REMOTE_MOUNT][JSON_API_PORT] = | ||||
|         app_config::default_remote_api_port(prov); | ||||
|     break; | ||||
|  | ||||
|   case provider_type::sia: | ||||
|     json_defaults[JSON_HOST_CONFIG][JSON_API_PORT] = | ||||
|         app_config::default_api_port(prov); | ||||
|     json_defaults[JSON_HOST_CONFIG][JSON_AGENT_STRING] = | ||||
|         app_config::default_agent_name(prov); | ||||
|     json_defaults[JSON_REMOTE_MOUNT][JSON_API_PORT] = | ||||
|         app_config::default_remote_api_port(prov); | ||||
|     break; | ||||
|  | ||||
|   default: | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   fmt::println("testing default|{}-{}", app_config::get_provider_name(prov), | ||||
|                JSON_API_AUTH); | ||||
|   ASSERT_EQ(std::size_t(default_api_auth_size), | ||||
|             json_data.at(JSON_API_AUTH).get<std::string>().size()); | ||||
|   for (const auto &[key, value] : json_defaults.items()) { | ||||
|     fmt::println("testing default|{}-{}", app_config::get_provider_name(prov), | ||||
|                  key); | ||||
|     EXPECT_EQ(value, json_data.at(key)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| template <typename get_t, typename set_t, typename val_t> | ||||
| static void test_getter_setter(app_config &cfg, get_t getter, set_t setter, | ||||
|                                val_t val1, val_t val2, const std::string &key, | ||||
|                                const std::string &val_str) { | ||||
|   (cfg.*setter)(val1); | ||||
|   ASSERT_TRUE((cfg.*getter)() == val1); | ||||
|  | ||||
|   (cfg.*setter)(val2); | ||||
|   ASSERT_TRUE((cfg.*getter)() == val2); | ||||
|  | ||||
|   if (key.empty()) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   EXPECT_STREQ(val_str.c_str(), cfg.set_value_by_name(key, val_str).c_str()); | ||||
| } | ||||
|  | ||||
| static void common_tests(app_config &config, provider_type prov) { | ||||
|   ASSERT_EQ(config.get_provider_type(), prov); | ||||
|  | ||||
|   std::map<std::string_view, std::function<void(app_config &)>> methods{ | ||||
|       {JSON_API_AUTH, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_api_auth, | ||||
|                             &app_config::set_api_auth, "", "auth", | ||||
|                             JSON_API_AUTH, "auth2"); | ||||
|        }}, | ||||
|       {JSON_API_PORT, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_api_port, | ||||
|                             &app_config::set_api_port, std::uint16_t{0U}, | ||||
|                             std::uint16_t{1024U}, JSON_API_PORT, "1025"); | ||||
|        }}, | ||||
|       {JSON_API_USER, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_api_user, | ||||
|                             &app_config::set_api_user, "", "user", | ||||
|                             JSON_API_USER, "user2"); | ||||
|        }}, | ||||
|       {JSON_DOWNLOAD_TIMEOUT_SECS, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_download_timeout_secs, | ||||
|                             &app_config::set_download_timeout_secs, | ||||
|                             std::uint8_t{min_download_timeout_secs + 1U}, | ||||
|                             std::uint8_t{min_download_timeout_secs + 2U}, | ||||
|                             JSON_DOWNLOAD_TIMEOUT_SECS, | ||||
|                             std::to_string(min_download_timeout_secs + 2U)); | ||||
|  | ||||
|          cfg.set_download_timeout_secs(min_download_timeout_secs - 1U); | ||||
|          EXPECT_EQ(min_download_timeout_secs, cfg.get_download_timeout_secs()); | ||||
|        }}, | ||||
|       {JSON_DATABASE_TYPE, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_database_type, | ||||
|                             &app_config::set_database_type, | ||||
|                             database_type::rocksdb, database_type::sqlite, | ||||
|                             JSON_DATABASE_TYPE, "rocksdb"); | ||||
|        }}, | ||||
|       {JSON_ENABLE_DOWNLOAD_TIMEOUT, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_enable_download_timeout, | ||||
|                             &app_config::set_enable_download_timeout, true, | ||||
|                             false, JSON_ENABLE_DOWNLOAD_TIMEOUT, "1"); | ||||
|        }}, | ||||
|       {JSON_ENABLE_DRIVE_EVENTS, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_enable_drive_events, | ||||
|                             &app_config::set_enable_drive_events, true, false, | ||||
|                             JSON_ENABLE_DRIVE_EVENTS, "1"); | ||||
|        }}, | ||||
| #if defined(_WIN32) | ||||
|       {JSON_ENABLE_MOUNT_MANAGER, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_enable_mount_manager, | ||||
|                             &app_config::set_enable_mount_manager, true, false, | ||||
|                             JSON_ENABLE_MOUNT_MANAGER, "1"); | ||||
|        }}, | ||||
| #endif // defined(_WIN32) | ||||
|       {JSON_ENCRYPT_CONFIG, | ||||
|        [](app_config &cfg) { | ||||
|          encrypt_config cfg1{}; | ||||
|          cfg1.encryption_token = "1"; | ||||
|          cfg1.path = "2"; | ||||
|  | ||||
|          encrypt_config cfg2{}; | ||||
|          cfg2.encryption_token = "2"; | ||||
|          cfg2.path = "1"; | ||||
|  | ||||
|          ASSERT_NE(cfg1, cfg2); | ||||
|          test_getter_setter(cfg, &app_config::get_encrypt_config, | ||||
|                             &app_config::set_encrypt_config, cfg1, cfg2, "", | ||||
|                             ""); | ||||
|  | ||||
|          encrypt_config cfg3{}; | ||||
|          cfg3.encryption_token = "3"; | ||||
|          cfg3.path = "4"; | ||||
|  | ||||
|          auto value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_ENCRYPT_CONFIG, JSON_ENCRYPTION_TOKEN), | ||||
|              cfg3.encryption_token); | ||||
|          EXPECT_STREQ(cfg3.encryption_token.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_ENCRYPT_CONFIG, JSON_PATH), cfg3.path); | ||||
|          EXPECT_STREQ(cfg3.path.c_str(), value.c_str()); | ||||
|        }}, | ||||
|       {JSON_EVENT_LEVEL, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_event_level, | ||||
|                             &app_config::set_event_level, event_level::critical, | ||||
|                             event_level::debug, JSON_EVENT_LEVEL, "info"); | ||||
|        }}, | ||||
|       {JSON_EVICTION_DELAY_MINS, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_eviction_delay_mins, | ||||
|                             &app_config::set_eviction_delay_mins, | ||||
|                             std::uint32_t{0U}, std::uint32_t{1U}, | ||||
|                             JSON_EVICTION_DELAY_MINS, "2"); | ||||
|        }}, | ||||
|       {JSON_EVICTION_USE_ACCESS_TIME, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_eviction_uses_accessed_time, | ||||
|                             &app_config::set_eviction_uses_accessed_time, true, | ||||
|                             false, JSON_EVICTION_USE_ACCESS_TIME, "1"); | ||||
|        }}, | ||||
|       {JSON_HIGH_FREQ_INTERVAL_SECS, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter( | ||||
|              cfg, &app_config::get_high_frequency_interval_secs, | ||||
|              &app_config::set_high_frequency_interval_secs, | ||||
|              std::uint16_t{default_high_freq_interval_secs + 1U}, | ||||
|              std::uint16_t{default_high_freq_interval_secs + 2U}, | ||||
|              JSON_HIGH_FREQ_INTERVAL_SECS, | ||||
|              std::to_string(default_high_freq_interval_secs + 3U)); | ||||
|  | ||||
|          cfg.set_high_frequency_interval_secs(0U); | ||||
|          EXPECT_EQ(1U, cfg.get_high_frequency_interval_secs()); | ||||
|        }}, | ||||
|       {JSON_HOST_CONFIG, | ||||
|        [](app_config &cfg) { | ||||
|          host_config cfg1{}; | ||||
|          cfg1.agent_string = "1"; | ||||
|          cfg1.api_password = "2"; | ||||
|          cfg1.api_user = "3"; | ||||
|          cfg1.api_port = 4U; | ||||
|          cfg1.host_name_or_ip = "5"; | ||||
|          cfg1.path = "6"; | ||||
|          cfg1.protocol = "http"; | ||||
|          cfg1.timeout_ms = 8U; | ||||
|  | ||||
|          host_config cfg2{}; | ||||
|          cfg2.agent_string = "9"; | ||||
|          cfg2.api_password = "10"; | ||||
|          cfg2.api_user = "11"; | ||||
|          cfg2.api_port = 12U; | ||||
|          cfg2.host_name_or_ip = "13"; | ||||
|          cfg2.path = "14"; | ||||
|          cfg2.protocol = "https"; | ||||
|          cfg2.timeout_ms = 16U; | ||||
|  | ||||
|          ASSERT_NE(cfg1, cfg2); | ||||
|  | ||||
|          test_getter_setter(cfg, &app_config::get_host_config, | ||||
|                             &app_config::set_host_config, cfg1, cfg2, "", ""); | ||||
|  | ||||
|          host_config cfg3{}; | ||||
|          cfg3.agent_string = "17"; | ||||
|          cfg3.api_password = "18"; | ||||
|          cfg3.api_user = "19"; | ||||
|          cfg3.api_port = 20U; | ||||
|          cfg3.host_name_or_ip = "21"; | ||||
|          cfg3.path = "22"; | ||||
|          cfg3.protocol = "http"; | ||||
|          cfg3.timeout_ms = 24; | ||||
|  | ||||
|          auto value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_AGENT_STRING), | ||||
|              cfg3.agent_string); | ||||
|          EXPECT_STREQ(cfg3.agent_string.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_API_PASSWORD), | ||||
|              cfg3.api_password); | ||||
|          EXPECT_STREQ(cfg3.api_password.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_API_USER), | ||||
|              cfg3.api_user); | ||||
|          EXPECT_STREQ(cfg3.api_user.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_API_PORT), | ||||
|              std::to_string(cfg3.api_port)); | ||||
|          EXPECT_STREQ(std::to_string(cfg3.api_port).c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_HOST_NAME_OR_IP), | ||||
|              cfg3.host_name_or_ip); | ||||
|          EXPECT_STREQ(cfg3.host_name_or_ip.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_PATH), cfg3.path); | ||||
|          EXPECT_STREQ(cfg3.path.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_PROTOCOL), | ||||
|              cfg3.protocol); | ||||
|          EXPECT_STREQ(cfg3.protocol.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_HOST_CONFIG, JSON_TIMEOUT_MS), | ||||
|              std::to_string(cfg3.timeout_ms)); | ||||
|          EXPECT_STREQ(std::to_string(cfg3.timeout_ms).c_str(), value.c_str()); | ||||
|        }}, | ||||
|       {JSON_LOW_FREQ_INTERVAL_SECS, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter( | ||||
|              cfg, &app_config::get_low_frequency_interval_secs, | ||||
|              &app_config::set_low_frequency_interval_secs, | ||||
|              std::uint16_t{default_low_freq_interval_secs + 1U}, | ||||
|              std::uint16_t{default_low_freq_interval_secs + 2U}, | ||||
|              JSON_LOW_FREQ_INTERVAL_SECS, | ||||
|              std::to_string(default_low_freq_interval_secs + 3U)); | ||||
|  | ||||
|          cfg.set_low_frequency_interval_secs(0U); | ||||
|          EXPECT_EQ(1U, cfg.get_low_frequency_interval_secs()); | ||||
|        }}, | ||||
|       {JSON_MAX_CACHE_SIZE_BYTES, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter( | ||||
|              cfg, &app_config::get_max_cache_size_bytes, | ||||
|              &app_config::set_max_cache_size_bytes, min_cache_size_bytes + 1U, | ||||
|              min_cache_size_bytes + 2U, JSON_MAX_CACHE_SIZE_BYTES, | ||||
|              std::to_string(min_cache_size_bytes + 3U)); | ||||
|  | ||||
|          cfg.set_max_cache_size_bytes(min_cache_size_bytes - 1U); | ||||
|          EXPECT_EQ(min_cache_size_bytes, cfg.get_max_cache_size_bytes()); | ||||
|        }}, | ||||
|       {JSON_MAX_UPLOAD_COUNT, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_max_upload_count, | ||||
|                             &app_config::set_max_upload_count, std::uint8_t{1U}, | ||||
|                             std::uint8_t{2U}, JSON_MAX_UPLOAD_COUNT, "3"); | ||||
|  | ||||
|          cfg.set_max_upload_count(0U); | ||||
|          EXPECT_EQ(1U, cfg.get_max_upload_count()); | ||||
|        }}, | ||||
|       {JSON_MED_FREQ_INTERVAL_SECS, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter( | ||||
|              cfg, &app_config::get_med_frequency_interval_secs, | ||||
|              &app_config::set_med_frequency_interval_secs, | ||||
|              std::uint16_t{default_med_freq_interval_secs + 1U}, | ||||
|              std::uint16_t{default_med_freq_interval_secs + 2U}, | ||||
|              JSON_MED_FREQ_INTERVAL_SECS, | ||||
|              std::to_string(default_med_freq_interval_secs + 3U)); | ||||
|  | ||||
|          cfg.set_med_frequency_interval_secs(0U); | ||||
|          EXPECT_EQ(1U, cfg.get_med_frequency_interval_secs()); | ||||
|        }}, | ||||
|       {JSON_ONLINE_CHECK_RETRY_SECS, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_online_check_retry_secs, | ||||
|                             &app_config::set_online_check_retry_secs, | ||||
|                             std::uint16_t{min_online_check_retry_secs + 1U}, | ||||
|                             std::uint16_t{min_online_check_retry_secs + 2U}, | ||||
|                             JSON_ONLINE_CHECK_RETRY_SECS, | ||||
|                             std::to_string(min_online_check_retry_secs + 3U)); | ||||
|  | ||||
|          cfg.set_online_check_retry_secs(min_online_check_retry_secs - 1U); | ||||
|          EXPECT_EQ(min_online_check_retry_secs, | ||||
|                    cfg.get_online_check_retry_secs()); | ||||
|        }}, | ||||
|       {JSON_PREFERRED_DOWNLOAD_TYPE, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_preferred_download_type, | ||||
|                             &app_config::set_preferred_download_type, | ||||
|                             download_type::direct, download_type::default_, | ||||
|                             JSON_PREFERRED_DOWNLOAD_TYPE, "ring_buffer"); | ||||
|        }}, | ||||
|       {JSON_REMOTE_CONFIG, | ||||
|        [](app_config &cfg) { | ||||
|          remote::remote_config remote_cfg1{}; | ||||
|          remote_cfg1.api_port = 1U; | ||||
|          remote_cfg1.encryption_token = "2"; | ||||
|          remote_cfg1.host_name_or_ip = "3"; | ||||
|          remote_cfg1.max_connections = 4U; | ||||
|          remote_cfg1.recv_timeout_ms = 5U; | ||||
|          remote_cfg1.send_timeout_ms = 6U; | ||||
|  | ||||
|          remote::remote_config remote_cfg2{}; | ||||
|          remote_cfg1.api_port = 6U; | ||||
|          remote_cfg1.encryption_token = "5"; | ||||
|          remote_cfg1.host_name_or_ip = "4"; | ||||
|          remote_cfg1.max_connections = 3U; | ||||
|          remote_cfg1.recv_timeout_ms = 2U; | ||||
|          remote_cfg1.send_timeout_ms = 1U; | ||||
|  | ||||
|          ASSERT_NE(remote_cfg1, remote_cfg2); | ||||
|  | ||||
|          test_getter_setter(cfg, &app_config::get_remote_config, | ||||
|                             &app_config::set_remote_config, remote_cfg1, | ||||
|                             remote_cfg2, "", ""); | ||||
|  | ||||
|          remote::remote_config remote_cfg3{}; | ||||
|          remote_cfg1.api_port = 7U; | ||||
|          remote_cfg1.encryption_token = "8"; | ||||
|          remote_cfg1.host_name_or_ip = "9"; | ||||
|          remote_cfg1.max_connections = 10U; | ||||
|          remote_cfg1.recv_timeout_ms = 11U; | ||||
|          remote_cfg1.send_timeout_ms = 12U; | ||||
|  | ||||
|          auto value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_REMOTE_CONFIG, JSON_API_PORT), | ||||
|              std::to_string(remote_cfg3.api_port)); | ||||
|          EXPECT_STREQ(std::to_string(remote_cfg3.api_port).c_str(), | ||||
|                       value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_REMOTE_CONFIG, JSON_ENCRYPTION_TOKEN), | ||||
|              remote_cfg3.encryption_token); | ||||
|          EXPECT_STREQ(remote_cfg3.encryption_token.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_REMOTE_CONFIG, JSON_HOST_NAME_OR_IP), | ||||
|              remote_cfg3.host_name_or_ip); | ||||
|          EXPECT_STREQ(remote_cfg3.host_name_or_ip.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_REMOTE_CONFIG, JSON_MAX_CONNECTIONS), | ||||
|              std::to_string(remote_cfg3.max_connections)); | ||||
|          EXPECT_STREQ(std::to_string(remote_cfg3.max_connections).c_str(), | ||||
|                       value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_REMOTE_CONFIG, JSON_RECV_TIMEOUT_MS), | ||||
|              std::to_string(remote_cfg3.recv_timeout_ms)); | ||||
|          EXPECT_STREQ(std::to_string(remote_cfg3.recv_timeout_ms).c_str(), | ||||
|                       value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_REMOTE_CONFIG, JSON_SEND_TIMEOUT_MS), | ||||
|              std::to_string(remote_cfg3.send_timeout_ms)); | ||||
|          EXPECT_STREQ(std::to_string(remote_cfg3.send_timeout_ms).c_str(), | ||||
|                       value.c_str()); | ||||
|        }}, | ||||
|       {JSON_REMOTE_MOUNT, | ||||
|        [](app_config &cfg) { | ||||
|          remote::remote_mount mnt_cfg1{}; | ||||
|          mnt_cfg1.api_port = 1U; | ||||
|          mnt_cfg1.client_pool_size = 2U; | ||||
|          mnt_cfg1.enable = false; | ||||
|          mnt_cfg1.encryption_token = "3"; | ||||
|  | ||||
|          remote::remote_mount mnt_cfg2{}; | ||||
|          mnt_cfg2.api_port = 3U; | ||||
|          mnt_cfg2.client_pool_size = 4U; | ||||
|          mnt_cfg2.enable = true; | ||||
|          mnt_cfg2.encryption_token = "5"; | ||||
|  | ||||
|          ASSERT_NE(mnt_cfg1, mnt_cfg2); | ||||
|  | ||||
|          test_getter_setter(cfg, &app_config::get_remote_mount, | ||||
|                             &app_config::set_remote_mount, mnt_cfg1, mnt_cfg2, | ||||
|                             "", ""); | ||||
|  | ||||
|          remote::remote_mount mnt_cfg3{}; | ||||
|          mnt_cfg3.api_port = 9U; | ||||
|          mnt_cfg3.client_pool_size = 10U; | ||||
|          mnt_cfg3.enable = false; | ||||
|          mnt_cfg3.encryption_token = "11"; | ||||
|  | ||||
|          auto value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_REMOTE_MOUNT, JSON_API_PORT), | ||||
|              std::to_string(mnt_cfg3.api_port)); | ||||
|          EXPECT_STREQ(std::to_string(mnt_cfg3.api_port).c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_REMOTE_MOUNT, JSON_CLIENT_POOL_SIZE), | ||||
|              std::to_string(mnt_cfg3.client_pool_size)); | ||||
|          EXPECT_STREQ(std::to_string(mnt_cfg3.client_pool_size).c_str(), | ||||
|                       value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_REMOTE_MOUNT, JSON_ENABLE_REMOTE_MOUNT), | ||||
|              utils::string::from_bool(mnt_cfg3.enable)); | ||||
|          EXPECT_STREQ(utils::string::from_bool(mnt_cfg3.enable).c_str(), | ||||
|                       value.c_str()); | ||||
|        }}, | ||||
|       {JSON_RETRY_READ_COUNT, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_retry_read_count, | ||||
|                             &app_config::set_retry_read_count, | ||||
|                             std::uint16_t{min_retry_read_count + 1U}, | ||||
|                             std::uint16_t{min_retry_read_count + 2U}, | ||||
|                             JSON_RETRY_READ_COUNT, | ||||
|                             std::to_string(min_retry_read_count + 3U)); | ||||
|  | ||||
|          cfg.set_retry_read_count(min_retry_read_count - 1U); | ||||
|          EXPECT_EQ(min_retry_read_count, cfg.get_retry_read_count()); | ||||
|        }}, | ||||
|       {JSON_RING_BUFFER_FILE_SIZE, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter(cfg, &app_config::get_ring_buffer_file_size, | ||||
|                             &app_config::set_ring_buffer_file_size, | ||||
|                             std::uint16_t{min_ring_buffer_file_size + 1U}, | ||||
|                             std::uint16_t{min_ring_buffer_file_size + 2U}, | ||||
|                             JSON_RING_BUFFER_FILE_SIZE, | ||||
|                             std::to_string(min_ring_buffer_file_size + 3U)); | ||||
|  | ||||
|          cfg.set_ring_buffer_file_size(min_ring_buffer_file_size - 1U); | ||||
|          EXPECT_EQ(min_ring_buffer_file_size, cfg.get_ring_buffer_file_size()); | ||||
|  | ||||
|          cfg.set_ring_buffer_file_size(max_ring_buffer_file_size + 1U); | ||||
|          EXPECT_EQ(max_ring_buffer_file_size, cfg.get_ring_buffer_file_size()); | ||||
|        }}, | ||||
|       {JSON_S3_CONFIG, | ||||
|        [](auto &&cfg) { | ||||
|          s3_config cfg1{}; | ||||
|          cfg1.access_key = "1"; | ||||
|          cfg1.bucket = "2"; | ||||
|          cfg1.encryption_token = "3"; | ||||
|          cfg1.region = "4"; | ||||
|          cfg1.secret_key = "5"; | ||||
|          cfg1.timeout_ms = 6U; | ||||
|          cfg1.url = "7"; | ||||
|          cfg1.use_path_style = false; | ||||
|          cfg1.use_region_in_url = false; | ||||
|  | ||||
|          s3_config cfg2{}; | ||||
|          cfg2.access_key = "8"; | ||||
|          cfg2.bucket = "9"; | ||||
|          cfg2.encryption_token = "10"; | ||||
|          cfg2.region = "11"; | ||||
|          cfg2.secret_key = "12"; | ||||
|          cfg2.timeout_ms = 13U; | ||||
|          cfg2.url = "14"; | ||||
|          cfg2.use_path_style = true; | ||||
|          cfg2.use_region_in_url = true; | ||||
|  | ||||
|          ASSERT_NE(cfg1, cfg2); | ||||
|  | ||||
|          test_getter_setter(cfg, &app_config::get_s3_config, | ||||
|                             &app_config::set_s3_config, cfg1, cfg2, "", ""); | ||||
|  | ||||
|          s3_config cfg3{}; | ||||
|          cfg3.access_key = "8"; | ||||
|          cfg3.bucket = "9"; | ||||
|          cfg3.encryption_token = "10"; | ||||
|          cfg3.region = "11"; | ||||
|          cfg3.secret_key = "12"; | ||||
|          cfg3.timeout_ms = 13U; | ||||
|          cfg3.url = "14"; | ||||
|          cfg3.use_path_style = true; | ||||
|          cfg3.use_region_in_url = true; | ||||
|  | ||||
|          auto value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_S3_CONFIG, JSON_ACCESS_KEY), | ||||
|              cfg3.access_key); | ||||
|          EXPECT_STREQ(cfg3.access_key.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_S3_CONFIG, JSON_BUCKET), cfg3.bucket); | ||||
|          EXPECT_STREQ(cfg3.bucket.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_S3_CONFIG, JSON_ENCRYPTION_TOKEN), | ||||
|              cfg3.encryption_token); | ||||
|          EXPECT_STREQ(cfg3.encryption_token.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_S3_CONFIG, JSON_REGION), cfg3.region); | ||||
|          EXPECT_STREQ(cfg3.region.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_S3_CONFIG, JSON_SECRET_KEY), | ||||
|              cfg3.secret_key); | ||||
|          EXPECT_STREQ(cfg3.secret_key.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_S3_CONFIG, JSON_TIMEOUT_MS), | ||||
|              std::to_string(cfg3.timeout_ms)); | ||||
|          EXPECT_STREQ(std::to_string(cfg3.timeout_ms).c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_S3_CONFIG, JSON_URL), cfg3.url); | ||||
|          EXPECT_STREQ(cfg3.url.c_str(), value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_S3_CONFIG, JSON_USE_PATH_STYLE), | ||||
|              utils::string::from_bool(cfg3.use_path_style)); | ||||
|          EXPECT_STREQ(utils::string::from_bool(cfg3.use_path_style).c_str(), | ||||
|                       value.c_str()); | ||||
|  | ||||
|          value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_S3_CONFIG, JSON_USE_REGION_IN_URL), | ||||
|              utils::string::from_bool(cfg3.use_region_in_url)); | ||||
|          EXPECT_STREQ(utils::string::from_bool(cfg3.use_region_in_url).c_str(), | ||||
|                       value.c_str()); | ||||
|        }}, | ||||
|       {JSON_SIA_CONFIG, | ||||
|        [](app_config &cfg) { | ||||
|          sia_config cfg1{}; | ||||
|          cfg1.bucket = "1"; | ||||
|  | ||||
|          sia_config cfg2{}; | ||||
|          cfg2.bucket = "2"; | ||||
|  | ||||
|          ASSERT_NE(cfg1, cfg2); | ||||
|  | ||||
|          test_getter_setter(cfg, &app_config::get_sia_config, | ||||
|                             &app_config::set_sia_config, cfg1, cfg2, "", ""); | ||||
|  | ||||
|          sia_config cfg3{}; | ||||
|          cfg3.bucket = "3"; | ||||
|  | ||||
|          auto value = cfg.set_value_by_name( | ||||
|              fmt::format("{}.{}", JSON_SIA_CONFIG, JSON_BUCKET), cfg3.bucket); | ||||
|          EXPECT_STREQ(cfg3.bucket.c_str(), value.c_str()); | ||||
|        }}, | ||||
|       {JSON_TASK_WAIT_MS, | ||||
|        [](app_config &cfg) { | ||||
|          test_getter_setter( | ||||
|              cfg, &app_config::get_task_wait_ms, &app_config::set_task_wait_ms, | ||||
|              std::uint16_t{min_task_wait_ms + 1U}, | ||||
|              std::uint16_t{min_task_wait_ms + 2U}, JSON_TASK_WAIT_MS, | ||||
|              std::to_string(min_task_wait_ms + 3U)); | ||||
|  | ||||
|          cfg.set_task_wait_ms(min_task_wait_ms - 1U); | ||||
|          EXPECT_EQ(min_task_wait_ms, cfg.get_task_wait_ms()); | ||||
|        }}, | ||||
|   }; | ||||
|  | ||||
|   remove_unused_types(methods, prov); | ||||
|  | ||||
|   for (const auto &[key, test_function] : methods) { | ||||
|     fmt::println("testing setting|{}-{}", app_config::get_provider_name(prov), | ||||
|                  key); | ||||
|     test_function(config); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(app_config_test, encrypt_config) { | ||||
|   app_config config(provider_type::encrypt, encrypt_directory); | ||||
|   defaults_tests(config.get_json(), provider_type::encrypt); | ||||
|   common_tests(config, provider_type::encrypt); | ||||
| } | ||||
|  | ||||
| TEST_F(app_config_test, remote_config) { | ||||
|   app_config config(provider_type::remote, remote_directory); | ||||
|   defaults_tests(config.get_json(), provider_type::remote); | ||||
|   common_tests(config, provider_type::remote); | ||||
| } | ||||
|  | ||||
| TEST_F(app_config_test, s3_config) { | ||||
|   app_config config(provider_type::s3, s3_directory); | ||||
|   defaults_tests(config.get_json(), provider_type::s3); | ||||
|   common_tests(config, provider_type::s3); | ||||
| } | ||||
|  | ||||
| TEST_F(app_config_test, sia_config) { | ||||
|   app_config config(provider_type::sia, sia_directory); | ||||
|   defaults_tests(config.get_json(), provider_type::sia); | ||||
|   common_tests(config, provider_type::sia); | ||||
| } | ||||
| } // namespace repertory | ||||
| @@ -24,7 +24,7 @@ | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| TEST(atomic, atomic_primitive) { | ||||
| TEST(atomic_test, atomic_primitive) { | ||||
|   atomic<std::uint16_t> value; | ||||
|   value = 5U; | ||||
|   EXPECT_EQ(5U, static_cast<std::uint16_t>(value)); | ||||
| @@ -35,7 +35,7 @@ TEST(atomic, atomic_primitive) { | ||||
|   EXPECT_EQ(6U, value.load()); | ||||
| } | ||||
|  | ||||
| TEST(atomic, atomic_primitive_equality) { | ||||
| TEST(atomic_test, atomic_primitive_equality) { | ||||
|   atomic<std::uint16_t> value1{5U}; | ||||
|   atomic<std::uint16_t> value2{5U}; | ||||
|   EXPECT_EQ(value1, value1); | ||||
| @@ -45,7 +45,7 @@ TEST(atomic, atomic_primitive_equality) { | ||||
|   EXPECT_EQ(static_cast<std::uint16_t>(value2), 5U); | ||||
| } | ||||
|  | ||||
| TEST(atomic, atomic_primitive_inequality) { | ||||
| TEST(atomic_test, atomic_primitive_inequality) { | ||||
|   atomic<std::uint16_t> value1{5U}; | ||||
|   atomic<std::uint16_t> value2{6U}; | ||||
|   EXPECT_NE(value1, value2); | ||||
| @@ -53,7 +53,7 @@ TEST(atomic, atomic_primitive_inequality) { | ||||
|   EXPECT_NE(static_cast<std::uint16_t>(value2), 5U); | ||||
| } | ||||
|  | ||||
| TEST(atomic, atomic_struct) { | ||||
| TEST(atomic_test, atomic_struct) { | ||||
|   atomic<encrypt_config> value{ | ||||
|       encrypt_config{ | ||||
|           .encryption_token = "token", | ||||
|   | ||||
| @@ -1,696 +0,0 @@ | ||||
| /* | ||||
|  Copyright <2018-2025> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   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 "app_config.hpp" | ||||
| #include "events/event_system.hpp" | ||||
| #include "utils/common.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class config_test : public ::testing::Test { | ||||
| public: | ||||
|   console_consumer cs; | ||||
|  | ||||
|   static std::atomic<std::uint64_t> idx; | ||||
|  | ||||
|   std::string s3_directory; | ||||
|   std::string sia_directory; | ||||
|  | ||||
|   void SetUp() override { | ||||
|     s3_directory = utils::path::combine(test::get_test_output_dir(), | ||||
|                                         { | ||||
|                                             "config_test", | ||||
|                                             "s3", | ||||
|                                             std::to_string(++idx), | ||||
|                                         }); | ||||
|  | ||||
|     sia_directory = utils::path::combine(test::get_test_output_dir(), | ||||
|                                          { | ||||
|                                              "config_test", | ||||
|                                              "sia", | ||||
|                                              std::to_string(++idx), | ||||
|                                          }); | ||||
|     event_system::instance().start(); | ||||
|   } | ||||
|  | ||||
|   void TearDown() override { | ||||
|     event_system::instance().stop(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| std::atomic<std::uint64_t> config_test::idx{0U}; | ||||
|  | ||||
| TEST_F(config_test, api_path) { | ||||
|   std::string original_value; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_api_auth(); | ||||
|     EXPECT_EQ(48U, original_value.size()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, api_auth) { | ||||
|   std::string original_value; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_api_auth(); | ||||
|     config.set_api_auth(original_value.substr(0, 20)); | ||||
|     EXPECT_EQ(original_value.substr(0, 20), config.get_api_auth()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value.substr(0, 20), config.get_api_auth()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, api_port) { | ||||
|   std::uint16_t original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_api_port(); | ||||
|     config.set_api_port(original_value + 5); | ||||
|     EXPECT_EQ(original_value + 5, config.get_api_port()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value + 5, config.get_api_port()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, api_user) { | ||||
|   std::string original_value; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_api_user(); | ||||
|     config.set_api_user(original_value.substr(0, 2)); | ||||
|     EXPECT_EQ(original_value.substr(0, 2), config.get_api_user()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value.substr(0, 2), config.get_api_user()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, download_timeout_secs) { | ||||
|   std::uint8_t original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_download_timeout_secs(); | ||||
|     config.set_download_timeout_secs(original_value + 5); | ||||
|     EXPECT_EQ(original_value + 5, config.get_download_timeout_secs()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value + 5, config.get_download_timeout_secs()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, enable_download_timeout) { | ||||
|   bool original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_enable_download_timeout(); | ||||
|     config.set_enable_download_timeout(not original_value); | ||||
|     EXPECT_EQ(not original_value, config.get_enable_download_timeout()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(not original_value, config.get_enable_download_timeout()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, enable_drive_events) { | ||||
|   bool original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_enable_drive_events(); | ||||
|     config.set_enable_drive_events(not original_value); | ||||
|     EXPECT_EQ(not original_value, config.get_enable_drive_events()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(not original_value, config.get_enable_drive_events()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| TEST_F(config_test, enable_mount_manager) { | ||||
|   bool original_value; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_enable_mount_manager(); | ||||
|     config.set_enable_mount_manager(not original_value); | ||||
|     EXPECT_EQ(not original_value, config.get_enable_mount_manager()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(not original_value, config.get_enable_mount_manager()); | ||||
|   } | ||||
| } | ||||
| #endif | ||||
| TEST_F(config_test, event_level) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_event_level(event_level::debug); | ||||
|     EXPECT_EQ(event_level::debug, config.get_event_level()); | ||||
|     config.set_event_level(event_level::warn); | ||||
|     EXPECT_EQ(event_level::warn, config.get_event_level()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(event_level::warn, config.get_event_level()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, eviction_delay_mins) { | ||||
|   std::uint32_t original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_eviction_delay_mins(); | ||||
|     config.set_eviction_delay_mins(original_value + 5); | ||||
|     EXPECT_EQ(original_value + 5, config.get_eviction_delay_mins()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value + 5, config.get_eviction_delay_mins()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, eviction_uses_accessed_time) { | ||||
|   bool original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_eviction_uses_accessed_time(); | ||||
|     config.set_eviction_uses_accessed_time(not original_value); | ||||
|     EXPECT_EQ(not original_value, config.get_eviction_uses_accessed_time()); | ||||
|   } | ||||
|  | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(not original_value, config.get_eviction_uses_accessed_time()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, high_frequency_interval_secs) { | ||||
|   std::uint16_t original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_high_frequency_interval_secs(); | ||||
|     config.set_high_frequency_interval_secs(original_value + 5U); | ||||
|     EXPECT_EQ(original_value + 5U, config.get_high_frequency_interval_secs()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value + 5U, config.get_high_frequency_interval_secs()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, low_frequency_interval_secs) { | ||||
|   std::uint16_t original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_low_frequency_interval_secs(); | ||||
|     config.set_low_frequency_interval_secs(original_value + 5U); | ||||
|     EXPECT_EQ(original_value + 5U, config.get_low_frequency_interval_secs()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value + 5U, config.get_low_frequency_interval_secs()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, med_frequency_interval_secs) { | ||||
|   std::uint16_t original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_med_frequency_interval_secs(); | ||||
|     config.set_med_frequency_interval_secs(original_value + 5U); | ||||
|     EXPECT_EQ(original_value + 5U, config.get_med_frequency_interval_secs()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value + 5U, config.get_med_frequency_interval_secs()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, max_cache_size_bytes) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_max_cache_size_bytes(100 * 1024 * 1024); | ||||
|     EXPECT_EQ(100U * 1024 * 1024, config.get_max_cache_size_bytes()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(100U * 1024 * 1024, config.get_max_cache_size_bytes()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, max_upload_count) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_max_upload_count(8U); | ||||
|     EXPECT_EQ(std::uint8_t(8U), config.get_max_upload_count()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(std::uint8_t(8U), config.get_max_upload_count()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_max_upload_count(0U); | ||||
|     EXPECT_EQ(std::uint8_t(1U), config.get_max_upload_count()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, online_check_retry_secs) { | ||||
|   std::uint16_t original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_online_check_retry_secs(); | ||||
|     config.set_online_check_retry_secs(original_value + 1); | ||||
|     EXPECT_EQ(original_value + 1, config.get_online_check_retry_secs()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value + 1, config.get_online_check_retry_secs()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, online_check_retry_secs_minimum_value) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_online_check_retry_secs(14); | ||||
|     EXPECT_EQ(15, config.get_online_check_retry_secs()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, orphaned_file_retention_days) { | ||||
|   std::uint16_t original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_orphaned_file_retention_days(); | ||||
|     config.set_orphaned_file_retention_days(original_value + 1); | ||||
|     EXPECT_EQ(original_value + 1, config.get_orphaned_file_retention_days()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value + 1, config.get_orphaned_file_retention_days()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, orphaned_file_retention_days_minimum_value) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_orphaned_file_retention_days(0); | ||||
|     EXPECT_EQ(1, config.get_orphaned_file_retention_days()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, orphaned_file_retention_days_maximum_value) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_orphaned_file_retention_days(32); | ||||
|     EXPECT_EQ(31, config.get_orphaned_file_retention_days()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, get_cache_directory) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_STREQ(utils::path::combine(sia_directory, {"cache"}).c_str(), | ||||
|                  config.get_cache_directory().c_str()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, get_config_file_path) { | ||||
|   { | ||||
|     const auto config_file = utils::path::absolute( | ||||
|         utils::path::combine(sia_directory, {"config.json"})); | ||||
|  | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_STREQ(config_file.c_str(), config.get_config_file_path().c_str()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, get_data_directory) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_STREQ(sia_directory.c_str(), config.get_data_directory().c_str()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, get_log_directory) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_STREQ(utils::path::combine(sia_directory, {"logs"}).c_str(), | ||||
|                  config.get_log_directory().c_str()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, ring_buffer_file_size) { | ||||
|   std::uint16_t original_value; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_ring_buffer_file_size(); | ||||
|     config.set_ring_buffer_file_size(original_value + 5u); | ||||
|     EXPECT_EQ(original_value + 5u, config.get_ring_buffer_file_size()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value + 5u, config.get_ring_buffer_file_size()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, ring_buffer_file_size_minimum_size) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_ring_buffer_file_size(63u); | ||||
|     EXPECT_EQ(64u, config.get_ring_buffer_file_size()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(64u, config.get_ring_buffer_file_size()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, ring_buffer_file_size_maximum_size) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_ring_buffer_file_size(1025u); | ||||
|     EXPECT_EQ(1024u, config.get_ring_buffer_file_size()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(1024u, config.get_ring_buffer_file_size()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, preferred_download_type) { | ||||
|   download_type original_value; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_preferred_download_type(); | ||||
|     config.set_preferred_download_type(download_type::ring_buffer); | ||||
|     EXPECT_NE(original_value, config.get_preferred_download_type()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_NE(original_value, config.get_preferred_download_type()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, default_agent_name) { | ||||
|   EXPECT_STREQ("Sia-Agent", | ||||
|                app_config::default_agent_name(provider_type::sia).c_str()); | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, default_api_port) { | ||||
|   EXPECT_EQ(9980U, app_config::default_api_port(provider_type::sia)); | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, default_data_directory) { | ||||
|   const std::array<std::string, 1U> data_directory = { | ||||
|       app_config::default_data_directory(provider_type::sia), | ||||
|   }; | ||||
|  | ||||
| #if defined(_WIN32) | ||||
|   const auto local_app_data = utils::get_environment_variable("localappdata"); | ||||
| #endif | ||||
| #if defined(__linux__) | ||||
|   const auto local_app_data = | ||||
|       utils::path::combine(utils::get_environment_variable("HOME"), {".local"}); | ||||
| #endif | ||||
| #if defined(__APPLE__) | ||||
|   const auto local_app_data = utils::path::combine( | ||||
|       utils::get_environment_variable("HOME"), {"Library/Application Support"}); | ||||
| #endif | ||||
|   auto expected_directory = | ||||
|       utils::path::combine(local_app_data, {"/repertory2/sia"}); | ||||
|   EXPECT_STREQ(expected_directory.c_str(), data_directory[0].c_str()); | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, default_rpc_port) { | ||||
|   EXPECT_EQ(10000U, app_config::default_rpc_port(provider_type::sia)); | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, get_provider_display_name) { | ||||
|   EXPECT_STREQ( | ||||
|       "Sia", app_config::get_provider_display_name(provider_type::sia).c_str()); | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, get_provider_name) { | ||||
|   EXPECT_STREQ("sia", | ||||
|                app_config::get_provider_name(provider_type::sia).c_str()); | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, get_version) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(REPERTORY_CONFIG_VERSION, config.get_version()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| // TEST_F(config_test, enable_remote_mount) { | ||||
| //   bool original_value{}; | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     original_value = config.get_enable_remote_mount(); | ||||
| //     config.set_enable_remote_mount(not original_value); | ||||
| //     EXPECT_EQ(not original_value, config.get_enable_remote_mount()); | ||||
| //   } | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     EXPECT_EQ(not original_value, config.get_enable_remote_mount()); | ||||
| //   } | ||||
| // } | ||||
|  | ||||
| // TEST_F(config_test, is_remote_mount) { | ||||
| //   bool original_value{}; | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     original_value = config.get_is_remote_mount(); | ||||
| //     config.set_is_remote_mount(not original_value); | ||||
| //     EXPECT_EQ(not original_value, config.get_is_remote_mount()); | ||||
| //   } | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     EXPECT_EQ(not original_value, config.get_is_remote_mount()); | ||||
| //   } | ||||
| // } | ||||
|  | ||||
| // TEST_F(config_test, enable_remote_mount_fails_if_remote_mount_is_true) { | ||||
| //   app_config config(provider_type::sia, sia_directory); | ||||
| //   config.set_is_remote_mount(true); | ||||
| //   config.set_enable_remote_mount(true); | ||||
| //   EXPECT_FALSE(config.get_enable_remote_mount()); | ||||
| //   EXPECT_TRUE(config.get_is_remote_mount()); | ||||
| // } | ||||
|  | ||||
| // TEST_F(config_test, set_is_remote_mount_fails_if_enable_remote_mount_is_true) | ||||
| // { | ||||
| //   app_config config(provider_type::sia, sia_directory); | ||||
| //   config.set_enable_remote_mount(true); | ||||
| //   config.set_is_remote_mount(true); | ||||
| //   EXPECT_FALSE(config.get_is_remote_mount()); | ||||
| //   EXPECT_TRUE(config.get_enable_remote_mount()); | ||||
| // } | ||||
|  | ||||
| // TEST_F(config_test, remote_host_name_or_ip) { | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     config.set_remote_host_name_or_ip("my.host.name"); | ||||
| //     EXPECT_STREQ("my.host.name", | ||||
| //     config.get_remote_host_name_or_ip().c_str()); | ||||
| //   } | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     EXPECT_STREQ("my.host.name", | ||||
| //     config.get_remote_host_name_or_ip().c_str()); | ||||
| //   } | ||||
| // } | ||||
|  | ||||
| // TEST_F(config_test, remote_api_port) { | ||||
| //   std::uint16_t original_value{}; | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     original_value = config.get_remote_api_port(); | ||||
| //     config.set_remote_api_port(original_value + 5); | ||||
| //     EXPECT_EQ(original_value + 5, config.get_remote_api_port()); | ||||
| //   } | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     EXPECT_EQ(original_value + 5, config.get_remote_api_port()); | ||||
| //   } | ||||
| // } | ||||
|  | ||||
| // TEST_F(config_test, remote_receive_timeout_secs) { | ||||
| //   std::uint16_t original_value{}; | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     original_value = config.get_remote_receive_timeout_secs(); | ||||
| //     config.set_remote_receive_timeout_secs(original_value + 5); | ||||
| //     EXPECT_EQ(original_value + 5, config.get_remote_receive_timeout_secs()); | ||||
| //   } | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     EXPECT_EQ(original_value + 5, config.get_remote_receive_timeout_secs()); | ||||
| //   } | ||||
| // } | ||||
|  | ||||
| // TEST_F(config_test, remote_send_timeout_secs) { | ||||
| //   std::uint16_t original_value{}; | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     original_value = config.get_remote_send_timeout_secs(); | ||||
| //     config.set_remote_send_timeout_secs(original_value + 5); | ||||
| //     EXPECT_EQ(original_value + 5, config.get_remote_send_timeout_secs()); | ||||
| //   } | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     EXPECT_EQ(original_value + 5, config.get_remote_send_timeout_secs()); | ||||
| //   } | ||||
| // } | ||||
|  | ||||
| // TEST_F(config_test, remote_encryption_token) { | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     config.set_remote_encryption_token("myToken"); | ||||
| //     EXPECT_STREQ("myToken", config.get_remote_encryption_token().c_str()); | ||||
| //   } | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     EXPECT_STREQ("myToken", config.get_remote_encryption_token().c_str()); | ||||
| //   } | ||||
| // } | ||||
| // | ||||
| // TEST_F(config_test, remote_client_pool_size) { | ||||
| //   std::uint8_t original_value{}; | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     original_value = config.get_remote_client_pool_size(); | ||||
| //     config.set_remote_client_pool_size(original_value + 5); | ||||
| //     EXPECT_EQ(original_value + 5, config.get_remote_client_pool_size()); | ||||
| //   } | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     EXPECT_EQ(original_value + 5, config.get_remote_client_pool_size()); | ||||
| //   } | ||||
| // } | ||||
| // | ||||
| // TEST_F(config_test, remote_client_pool_size_minimum_value) { | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     config.set_remote_client_pool_size(0); | ||||
| //     EXPECT_EQ(5, config.get_remote_client_pool_size()); | ||||
| //   } | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     EXPECT_EQ(5, config.get_remote_client_pool_size()); | ||||
| //   } | ||||
| // } | ||||
|  | ||||
| // TEST_F(config_test, remote_max_connections) { | ||||
| //   std::uint8_t original_value{}; | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     original_value = config.get_remote_max_connections(); | ||||
| //     config.set_remote_max_connections(original_value + 5); | ||||
| //     EXPECT_EQ(original_value + 5, config.get_remote_max_connections()); | ||||
| //   } | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     EXPECT_EQ(original_value + 5, config.get_remote_max_connections()); | ||||
| //   } | ||||
| // } | ||||
|  | ||||
| // TEST_F(config_test, remote_max_connections_minimum_value) { | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     config.set_remote_max_connections(0); | ||||
| //     EXPECT_EQ(1, config.get_remote_max_connections()); | ||||
| //   } | ||||
| //   { | ||||
| //     app_config config(provider_type::sia, sia_directory); | ||||
| //     EXPECT_EQ(1, config.get_remote_max_connections()); | ||||
| //   } | ||||
| // } | ||||
|  | ||||
| TEST_F(config_test, retry_read_count) { | ||||
|   std::uint16_t original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_retry_read_count(); | ||||
|     config.set_retry_read_count(original_value + 1); | ||||
|     EXPECT_EQ(original_value + 1, config.get_retry_read_count()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value + 1, config.get_retry_read_count()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, retry_read_count_minimum_value) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_retry_read_count(1); | ||||
|     EXPECT_EQ(2, config.get_retry_read_count()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, task_wait_ms) { | ||||
|   std::uint16_t original_value{}; | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     original_value = config.get_task_wait_ms(); | ||||
|     config.set_task_wait_ms(original_value + 1U); | ||||
|     EXPECT_EQ(original_value + 1U, config.get_task_wait_ms()); | ||||
|   } | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     EXPECT_EQ(original_value + 1U, config.get_task_wait_ms()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, task_wait_ms_minimum_value) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_task_wait_ms(1U); | ||||
|     EXPECT_EQ(50U, config.get_task_wait_ms()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_F(config_test, can_set_database_type) { | ||||
|   { | ||||
|     app_config config(provider_type::sia, sia_directory); | ||||
|     config.set_database_type(database_type::rocksdb); | ||||
|     EXPECT_EQ(database_type::rocksdb, config.get_database_type()); | ||||
|  | ||||
|     config.set_database_type(database_type::sqlite); | ||||
|     EXPECT_EQ(database_type::sqlite, config.get_database_type()); | ||||
|  | ||||
|     config.set_database_type(database_type::rocksdb); | ||||
|     EXPECT_EQ(database_type::rocksdb, config.get_database_type()); | ||||
|   } | ||||
| } | ||||
| } // namespace repertory | ||||
| @@ -25,7 +25,7 @@ | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| TEST(curl_comm, can_create_s3_host_config) { | ||||
| TEST(curl_comm_test, can_create_s3_host_config) { | ||||
|   s3_config config{}; | ||||
|   config.bucket = "repertory"; | ||||
|   config.url = "https://s3.test.com"; | ||||
| @@ -37,7 +37,7 @@ TEST(curl_comm, can_create_s3_host_config) { | ||||
|   EXPECT_TRUE(hc.path.empty()); | ||||
| } | ||||
|  | ||||
| TEST(curl_comm, can_create_s3_host_config_with_path_style) { | ||||
| TEST(curl_comm_test, can_create_s3_host_config_with_path_style) { | ||||
|   s3_config config{}; | ||||
|   config.bucket = "repertory"; | ||||
|   config.url = "https://s3.test.com"; | ||||
| @@ -49,7 +49,7 @@ TEST(curl_comm, can_create_s3_host_config_with_path_style) { | ||||
|   EXPECT_STREQ("/repertory", hc.path.c_str()); | ||||
| } | ||||
|  | ||||
| TEST(curl_comm, can_create_s3_host_config_with_region) { | ||||
| TEST(curl_comm_test, can_create_s3_host_config_with_region) { | ||||
|   s3_config config{}; | ||||
|   config.bucket = "repertory"; | ||||
|   config.url = "https://s3.test.com"; | ||||
| @@ -62,7 +62,7 @@ TEST(curl_comm, can_create_s3_host_config_with_region) { | ||||
|   EXPECT_TRUE(hc.path.empty()); | ||||
| } | ||||
|  | ||||
| TEST(curl_comm, can_create_s3_host_config_with_region_and_path_style) { | ||||
| TEST(curl_comm_test, can_create_s3_host_config_with_region_and_path_style) { | ||||
|   s3_config config{}; | ||||
|   config.bucket = "repertory"; | ||||
|   config.url = "https://s3.test.com"; | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| TEST(json_serialize, can_handle_directory_item) { | ||||
| TEST(json_serialize_test, can_handle_directory_item) { | ||||
|   directory_item cfg{ | ||||
|       "api", "parent", true, 2U, {{META_DIRECTORY, "true"}}, | ||||
|   }; | ||||
| @@ -47,7 +47,7 @@ TEST(json_serialize, can_handle_directory_item) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST(json_serialize, can_handle_encrypt_config) { | ||||
| TEST(json_serialize_test, can_handle_encrypt_config) { | ||||
|   encrypt_config cfg{ | ||||
|       "token", | ||||
|       "path", | ||||
| @@ -65,7 +65,7 @@ TEST(json_serialize, can_handle_encrypt_config) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST(json_serialize, can_handle_host_config) { | ||||
| TEST(json_serialize_test, can_handle_host_config) { | ||||
|   host_config cfg{ | ||||
|       "agent", "pwd", "user", 1024U, "host", "path", "http", 11U, | ||||
|   }; | ||||
| @@ -94,7 +94,7 @@ TEST(json_serialize, can_handle_host_config) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST(json_serialize, can_handle_remote_config) { | ||||
| TEST(json_serialize_test, can_handle_remote_config) { | ||||
|   remote::remote_config cfg{ | ||||
|       1024U, "token", "host", 11U, 20U, 21U, | ||||
|   }; | ||||
| @@ -120,7 +120,7 @@ TEST(json_serialize, can_handle_remote_config) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST(json_serialize, can_handle_remote_mount) { | ||||
| TEST(json_serialize_test, can_handle_remote_mount) { | ||||
|   remote::remote_mount cfg{1024U, 21U, true, "token"}; | ||||
|  | ||||
|   json data(cfg); | ||||
| @@ -139,7 +139,7 @@ TEST(json_serialize, can_handle_remote_mount) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST(json_serialize, can_handle_s3_config) { | ||||
| TEST(json_serialize_test, can_handle_s3_config) { | ||||
|   s3_config cfg{ | ||||
|       "access", "bucket", "token", "region", "secret", 31U, "url", true, false, | ||||
|   }; | ||||
| @@ -170,7 +170,7 @@ TEST(json_serialize, can_handle_s3_config) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST(json_serialize, can_handle_sia_config) { | ||||
| TEST(json_serialize_test, can_handle_sia_config) { | ||||
|   sia_config cfg{ | ||||
|       "bucket", | ||||
|   }; | ||||
| @@ -184,7 +184,7 @@ TEST(json_serialize, can_handle_sia_config) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST(json_serialize, can_handle_atomic) { | ||||
| TEST(json_serialize_test, can_handle_atomic) { | ||||
|   atomic<sia_config> cfg({ | ||||
|       "bucket", | ||||
|   }); | ||||
| @@ -198,7 +198,7 @@ TEST(json_serialize, can_handle_atomic) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST(json_serialize, can_handle_database_type) { | ||||
| TEST(json_serialize_test, can_handle_database_type) { | ||||
|   json data(database_type::rocksdb); | ||||
|   EXPECT_EQ(database_type::rocksdb, data.get<database_type>()); | ||||
|   EXPECT_STREQ("rocksdb", data.get<std::string>().c_str()); | ||||
| @@ -208,7 +208,7 @@ TEST(json_serialize, can_handle_database_type) { | ||||
|   EXPECT_STREQ("sqlite", data.get<std::string>().c_str()); | ||||
| } | ||||
|  | ||||
| TEST(json_serialize, can_handle_download_type) { | ||||
| TEST(json_serialize_test, can_handle_download_type) { | ||||
|   json data(download_type::direct); | ||||
|   EXPECT_EQ(download_type::direct, data.get<download_type>()); | ||||
|   EXPECT_STREQ("direct", data.get<std::string>().c_str()); | ||||
| @@ -222,7 +222,33 @@ TEST(json_serialize, can_handle_download_type) { | ||||
|   EXPECT_STREQ("ring_buffer", data.get<std::string>().c_str()); | ||||
| } | ||||
|  | ||||
| TEST(json_serialize, can_handle_atomic_database_type) { | ||||
| TEST(json_serialize_test, can_handle_event_level) { | ||||
|   json data(event_level{event_level::critical}); | ||||
|   EXPECT_EQ(event_level::critical, data.get<event_level>()); | ||||
|   EXPECT_STREQ("critical", data.get<std::string>().c_str()); | ||||
|  | ||||
|   data = event_level(event_level::error); | ||||
|   EXPECT_EQ(event_level::error, data.get<event_level>()); | ||||
|   EXPECT_STREQ("error", data.get<std::string>().c_str()); | ||||
|  | ||||
|   data = event_level(event_level::warn); | ||||
|   EXPECT_EQ(event_level::warn, data.get<event_level>()); | ||||
|   EXPECT_STREQ("warn", data.get<std::string>().c_str()); | ||||
|  | ||||
|   data = event_level(event_level::info); | ||||
|   EXPECT_EQ(event_level::info, data.get<event_level>()); | ||||
|   EXPECT_STREQ("info", data.get<std::string>().c_str()); | ||||
|  | ||||
|   data = event_level(event_level::debug); | ||||
|   EXPECT_EQ(event_level::debug, data.get<event_level>()); | ||||
|   EXPECT_STREQ("debug", data.get<std::string>().c_str()); | ||||
|  | ||||
|   data = event_level(event_level::trace); | ||||
|   EXPECT_EQ(event_level::trace, data.get<event_level>()); | ||||
|   EXPECT_STREQ("trace", data.get<std::string>().c_str()); | ||||
| } | ||||
|  | ||||
| TEST(json_serialize_test, can_handle_atomic_database_type) { | ||||
|   json data(atomic<database_type>{database_type::rocksdb}); | ||||
|   EXPECT_EQ(database_type::rocksdb, data.get<atomic<database_type>>()); | ||||
|   EXPECT_STREQ("rocksdb", data.get<std::string>().c_str()); | ||||
| @@ -232,7 +258,7 @@ TEST(json_serialize, can_handle_atomic_database_type) { | ||||
|   EXPECT_STREQ("sqlite", data.get<std::string>().c_str()); | ||||
| } | ||||
|  | ||||
| TEST(json_serialize, can_handle_atomic_download_type) { | ||||
| TEST(json_serialize_test, can_handle_atomic_download_type) { | ||||
|   json data(atomic<download_type>{download_type::direct}); | ||||
|   EXPECT_EQ(download_type::direct, data.get<atomic<download_type>>()); | ||||
|   EXPECT_STREQ("direct", data.get<std::string>().c_str()); | ||||
| @@ -245,4 +271,30 @@ TEST(json_serialize, can_handle_atomic_download_type) { | ||||
|   EXPECT_EQ(download_type::ring_buffer, data.get<atomic<download_type>>()); | ||||
|   EXPECT_STREQ("ring_buffer", data.get<std::string>().c_str()); | ||||
| } | ||||
|  | ||||
| TEST(json_serialize_test, can_handle_atomic_event_level) { | ||||
|   json data(atomic<event_level>{event_level::critical}); | ||||
|   EXPECT_EQ(event_level::critical, data.get<atomic<event_level>>()); | ||||
|   EXPECT_STREQ("critical", data.get<std::string>().c_str()); | ||||
|  | ||||
|   data = atomic<event_level>(event_level::error); | ||||
|   EXPECT_EQ(event_level::error, data.get<atomic<event_level>>()); | ||||
|   EXPECT_STREQ("error", data.get<std::string>().c_str()); | ||||
|  | ||||
|   data = atomic<event_level>(event_level::warn); | ||||
|   EXPECT_EQ(event_level::warn, data.get<atomic<event_level>>()); | ||||
|   EXPECT_STREQ("warn", data.get<std::string>().c_str()); | ||||
|  | ||||
|   data = atomic<event_level>(event_level::info); | ||||
|   EXPECT_EQ(event_level::info, data.get<atomic<event_level>>()); | ||||
|   EXPECT_STREQ("info", data.get<std::string>().c_str()); | ||||
|  | ||||
|   data = atomic<event_level>(event_level::debug); | ||||
|   EXPECT_EQ(event_level::debug, data.get<atomic<event_level>>()); | ||||
|   EXPECT_STREQ("debug", data.get<std::string>().c_str()); | ||||
|  | ||||
|   data = atomic<event_level>(event_level::trace); | ||||
|   EXPECT_EQ(event_level::trace, data.get<atomic<event_level>>()); | ||||
|   EXPECT_STREQ("trace", data.get<std::string>().c_str()); | ||||
| } | ||||
| } // namespace repertory | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
| #include "platform/platform.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| TEST(lock_data, lock_and_unlock) { | ||||
| TEST(lock_data_test, lock_and_unlock) { | ||||
|   { | ||||
|     lock_data l(provider_type::sia, "1"); | ||||
|     EXPECT_EQ(lock_result::success, l.grab_lock()); | ||||
| @@ -50,7 +50,7 @@ TEST(lock_data, lock_and_unlock) { | ||||
| } | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| TEST(lock_data, set_and_unset_mount_state) { | ||||
| TEST(lock_data_test, set_and_unset_mount_state) { | ||||
|   lock_data l(provider_type::sia, "1"); | ||||
|   EXPECT_TRUE(l.set_mount_state(true, "C:", 99)); | ||||
|  | ||||
| @@ -83,7 +83,7 @@ TEST(lock_data, set_and_unset_mount_state) { | ||||
|                mount_state["Remote2"].dump().c_str()); | ||||
| } | ||||
| #else | ||||
| TEST(lock_data, set_and_unset_mount_state) { | ||||
| TEST(lock_data_test, set_and_unset_mount_state) { | ||||
|   lock_data l(provider_type::sia, "1"); | ||||
|   EXPECT_TRUE(l.set_mount_state(true, "/mnt/1", 99)); | ||||
|  | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
| #include "comm/packet/packet.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| TEST(packet, encrypt_and_decrypt) { | ||||
| TEST(packet_test, encrypt_and_decrypt) { | ||||
|   packet test_packet; | ||||
|   test_packet.encode("test"); | ||||
|   test_packet.encrypt("moose"); | ||||
|   | ||||
| @@ -19,8 +19,6 @@ | ||||
|   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|   SOFTWARE. | ||||
| */ | ||||
| #if 0 | ||||
|  | ||||
| #include "test_common.hpp" | ||||
|  | ||||
| #include "comm/curl/curl_comm.hpp" | ||||
| @@ -99,8 +97,6 @@ const auto create_directory = [](repertory::i_provider &provider, | ||||
|       repertory::utils::string::to_bool(meta2[repertory::META_PINNED])); | ||||
|   EXPECT_EQ(std::uint64_t(0U), | ||||
|             repertory::utils::string::to_uint64(meta2[repertory::META_SIZE])); | ||||
|   EXPECT_STREQ((api_path + "_src").c_str(), | ||||
|                meta2[repertory::META_SOURCE].c_str()); | ||||
|   EXPECT_EQ(getuid(), static_cast<uid_t>(repertory::utils::string::to_uint32( | ||||
|                           meta2[repertory::META_UID]))); | ||||
|   EXPECT_EQ(date + 4U, repertory::utils::string::to_uint64( | ||||
| @@ -178,6 +174,9 @@ const auto decrypt_parts = [](const repertory::app_config &cfg, | ||||
|  | ||||
| namespace repertory { | ||||
| static void can_create_and_remove_directory(i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.is_read_only()) { | ||||
|     api_meta_map meta{}; | ||||
|     EXPECT_EQ(api_error::not_implemented, | ||||
| @@ -196,6 +195,9 @@ static void can_create_and_remove_directory(i_provider &provider) { | ||||
| } | ||||
|  | ||||
| static void create_directory_fails_if_already_exists(i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.is_read_only()) { | ||||
|     return; | ||||
|   } | ||||
| @@ -210,6 +212,9 @@ static void create_directory_fails_if_already_exists(i_provider &provider) { | ||||
|  | ||||
| static void | ||||
| create_directory_fails_if_file_already_exists(i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.is_read_only()) { | ||||
|     return; | ||||
|   } | ||||
| @@ -223,6 +228,9 @@ create_directory_fails_if_file_already_exists(i_provider &provider) { | ||||
| } | ||||
|  | ||||
| static void create_directory_clone_source_meta(i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.is_read_only()) { | ||||
|     EXPECT_EQ(api_error::not_implemented, | ||||
|               provider.create_directory_clone_source_meta("/moose", "/moose")); | ||||
| @@ -257,6 +265,9 @@ static void create_directory_clone_source_meta(i_provider &provider) { | ||||
|  | ||||
| static void create_directory_clone_source_meta_fails_if_already_exists( | ||||
|     i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.is_read_only()) { | ||||
|     return; | ||||
|   } | ||||
| @@ -272,6 +283,9 @@ static void create_directory_clone_source_meta_fails_if_already_exists( | ||||
|  | ||||
| static void create_directory_clone_source_meta_fails_if_directory_not_found( | ||||
|     i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.is_read_only()) { | ||||
|     return; | ||||
|   } | ||||
| @@ -282,6 +296,9 @@ static void create_directory_clone_source_meta_fails_if_directory_not_found( | ||||
|  | ||||
| static void create_directory_clone_source_meta_fails_if_file_already_exists( | ||||
|     i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.is_read_only()) { | ||||
|     return; | ||||
|   } | ||||
| @@ -297,6 +314,9 @@ static void create_directory_clone_source_meta_fails_if_file_already_exists( | ||||
| } | ||||
|  | ||||
| static void can_create_and_remove_file(i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.is_read_only()) { | ||||
|     api_meta_map meta{}; | ||||
|     EXPECT_EQ(api_error::not_implemented, | ||||
| @@ -317,6 +337,9 @@ static void can_create_and_remove_file(i_provider &provider) { | ||||
| } | ||||
|  | ||||
| static void create_file_fails_if_already_exists(i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.is_read_only()) { | ||||
|     return; | ||||
|   } | ||||
| @@ -331,6 +354,9 @@ static void create_file_fails_if_already_exists(i_provider &provider) { | ||||
|  | ||||
| static void | ||||
| create_file_fails_if_directory_already_exists(i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.is_read_only()) { | ||||
|     return; | ||||
|   } | ||||
| @@ -345,9 +371,12 @@ create_file_fails_if_directory_already_exists(i_provider &provider) { | ||||
|  | ||||
| static void get_api_path_from_source(const app_config &cfg, | ||||
|                                      i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.get_provider_type() == provider_type::encrypt) { | ||||
|     const auto source_path = | ||||
|         utils::path::combine("./test_date/encrypt", {"test.txt"}); | ||||
|     auto source_path = | ||||
|         utils::path::combine("./test_input/encrypt", {"test.txt"}); | ||||
|  | ||||
|     std::string api_path{}; | ||||
|     EXPECT_EQ(api_error::success, | ||||
| @@ -376,6 +405,9 @@ static void get_api_path_from_source(const app_config &cfg, | ||||
| static void | ||||
| get_api_path_from_source_fails_if_file_not_found(const app_config &cfg, | ||||
|                                                  i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   std::string source_path{}; | ||||
|   if (provider.get_provider_type() == provider_type::encrypt) { | ||||
|     source_path = utils::path::combine(cfg.get_encrypt_config().path, | ||||
| @@ -391,28 +423,50 @@ get_api_path_from_source_fails_if_file_not_found(const app_config &cfg, | ||||
|   EXPECT_TRUE(api_path.empty()); | ||||
| } | ||||
|  | ||||
| static void get_directory_item_count(const app_config &cfg, | ||||
| static void get_directory_item_count(const app_config & /* cfg */, | ||||
|                                      i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.get_provider_type() == provider_type::encrypt) { | ||||
|     EXPECT_EQ(std::size_t(2U), provider.get_directory_item_count("/")); | ||||
|     EXPECT_EQ(std::size_t(0U), provider.get_directory_item_count("/not_found")); | ||||
|  | ||||
|     const auto source_path = | ||||
|     auto source_path = | ||||
|         utils::path::combine(test::get_test_input_dir(), {"encrypt", "sub10"}); | ||||
|  | ||||
|     std::string api_path{}; | ||||
|     EXPECT_EQ(api_error::success, | ||||
|               provider.get_api_path_from_source(source_path, api_path)); | ||||
|     EXPECT_EQ(std::size_t(1U), provider.get_directory_item_count(api_path)); | ||||
|     return; | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void get_directory_items(const app_config &cfg, i_provider &provider) { | ||||
|   create_file(provider, "/pt01.txt"); | ||||
|   create_file(provider, "/pt02.txt"); | ||||
|   create_directory(provider, "/dir01"); | ||||
|   create_directory(provider, "/dir02"); | ||||
|  | ||||
|   directory_item_list list{}; | ||||
|   EXPECT_EQ(api_error::success, provider.get_directory_items("/", list)); | ||||
|   check_forced_dirs(list); | ||||
|   EXPECT_GE(list.size(), std::size_t(6U)); | ||||
|  | ||||
|   EXPECT_EQ(api_error::success, provider.remove_file("/pt01.txt")); | ||||
|   EXPECT_EQ(api_error::success, provider.remove_file("/pt02.txt")); | ||||
|   EXPECT_EQ(api_error::success, provider.remove_directory("/dir01")); | ||||
|   EXPECT_EQ(api_error::success, provider.remove_directory("/dir02")); | ||||
| } | ||||
|  | ||||
| static void get_directory_items(const app_config &cfg, i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.get_provider_type() == provider_type::encrypt) { | ||||
|     directory_item_list list{}; | ||||
|     EXPECT_EQ(api_error::success, provider.get_directory_items("/", list)); | ||||
|     check_forced_dirs(list); | ||||
|  | ||||
|     EXPECT_EQ(std::size_t(4U), list.size()); | ||||
|  | ||||
|     directory_item_list list_decrypted{list.begin() + 2U, list.end()}; | ||||
| @@ -443,7 +497,7 @@ static void get_directory_items(const app_config &cfg, i_provider &provider) { | ||||
|     EXPECT_EQ(std::size_t(46U), file->size); | ||||
| #endif | ||||
|  | ||||
|     const auto source_path = | ||||
|     auto source_path = | ||||
|         utils::path::combine(cfg.get_encrypt_config().path, {"sub10"}); | ||||
|     std::string api_path{}; | ||||
|     EXPECT_EQ(api_error::success, | ||||
| @@ -472,11 +526,58 @@ static void get_directory_items(const app_config &cfg, i_provider &provider) { | ||||
| #else | ||||
|     EXPECT_EQ(std::size_t(45U), file2->size); | ||||
| #endif | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   create_file(provider, "/pt01.txt"); | ||||
|   create_file(provider, "/pt02.txt"); | ||||
|   create_directory(provider, "/dir01"); | ||||
|   create_directory(provider, "/dir02"); | ||||
|  | ||||
|   directory_item_list list{}; | ||||
|   EXPECT_EQ(api_error::success, provider.get_directory_items("/", list)); | ||||
|   check_forced_dirs(list); | ||||
|   EXPECT_GE(list.size(), std::size_t(6U)); | ||||
|  | ||||
|   auto iter = std::ranges::find_if( | ||||
|       list, [](auto &&item) -> bool { return item.api_path == "/pt01.txt"; }); | ||||
|   EXPECT_NE(iter, list.end()); | ||||
|   EXPECT_STREQ("/", (*iter).api_parent.c_str()); | ||||
|   EXPECT_FALSE((*iter).directory); | ||||
|   EXPECT_EQ(std::uint64_t{0U}, (*iter).size); | ||||
|  | ||||
|   iter = std::ranges::find_if( | ||||
|       list, [](auto &&item) -> bool { return item.api_path == "/pt02.txt"; }); | ||||
|   EXPECT_NE(iter, list.end()); | ||||
|   EXPECT_STREQ("/", (*iter).api_parent.c_str()); | ||||
|   EXPECT_FALSE((*iter).directory); | ||||
|   EXPECT_EQ(std::uint64_t{0U}, (*iter).size); | ||||
|  | ||||
|   iter = std::ranges::find_if( | ||||
|       list, [](auto &&item) -> bool { return item.api_path == "/dir01"; }); | ||||
|   EXPECT_NE(iter, list.end()); | ||||
|   EXPECT_STREQ("/", (*iter).api_parent.c_str()); | ||||
|   EXPECT_TRUE((*iter).directory); | ||||
|   EXPECT_EQ(std::uint64_t{0U}, (*iter).size); | ||||
|  | ||||
|   iter = std::ranges::find_if( | ||||
|       list, [](auto &&item) -> bool { return item.api_path == "/dir02"; }); | ||||
|   EXPECT_NE(iter, list.end()); | ||||
|   EXPECT_STREQ("/", (*iter).api_parent.c_str()); | ||||
|   EXPECT_TRUE((*iter).directory); | ||||
|   EXPECT_EQ(std::uint64_t{0U}, (*iter).size); | ||||
|  | ||||
|   EXPECT_EQ(api_error::success, provider.remove_file("/pt01.txt")); | ||||
|   EXPECT_EQ(api_error::success, provider.remove_file("/pt02.txt")); | ||||
|   EXPECT_EQ(api_error::success, provider.remove_directory("/dir01")); | ||||
|   EXPECT_EQ(api_error::success, provider.remove_directory("/dir02")); | ||||
| } | ||||
|  | ||||
| static void | ||||
| get_directory_items_fails_if_directory_not_found(i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   directory_item_list list{}; | ||||
|   EXPECT_EQ(api_error::directory_not_found, | ||||
|             provider.get_directory_items("/not_found", list)); | ||||
| @@ -485,8 +586,11 @@ get_directory_items_fails_if_directory_not_found(i_provider &provider) { | ||||
|  | ||||
| static void get_directory_items_fails_if_item_is_file(const app_config &cfg, | ||||
|                                                       i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.get_provider_type() == provider_type::encrypt) { | ||||
|     const auto source_path = | ||||
|     auto source_path = | ||||
|         utils::path::combine(cfg.get_encrypt_config().path, {"test.txt"}); | ||||
|  | ||||
|     std::string api_path{}; | ||||
| @@ -497,12 +601,24 @@ static void get_directory_items_fails_if_item_is_file(const app_config &cfg, | ||||
|     EXPECT_EQ(api_error::item_exists, | ||||
|               provider.get_directory_items(api_path, list)); | ||||
|     EXPECT_TRUE(list.empty()); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   create_file(provider, "/pt01.txt"); | ||||
|  | ||||
|   directory_item_list list{}; | ||||
|   EXPECT_EQ(api_error::item_exists, | ||||
|             provider.get_directory_items("/pt01.txt", list)); | ||||
|  | ||||
|   EXPECT_EQ(api_error::success, provider.remove_file("/pt01.txt")); | ||||
| } | ||||
|  | ||||
| static void get_file(const app_config &cfg, i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.get_provider_type() == provider_type::encrypt) { | ||||
|     const auto source_path = | ||||
|     auto source_path = | ||||
|         utils::path::combine(cfg.get_encrypt_config().path, {"test.txt"}); | ||||
|  | ||||
|     std::string api_path{}; | ||||
| @@ -522,18 +638,43 @@ static void get_file(const app_config &cfg, i_provider &provider) { | ||||
|     EXPECT_EQ(std::size_t(46U), file.file_size); | ||||
| #endif | ||||
|     EXPECT_STREQ(source_path.c_str(), file.source_path.c_str()); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   create_file(provider, "/pt01.txt"); | ||||
|  | ||||
|   api_file file{}; | ||||
|   EXPECT_EQ(api_error::success, provider.get_file("/pt01.txt", file)); | ||||
|  | ||||
|   EXPECT_STREQ("/pt01.txt", file.api_path.c_str()); | ||||
|   EXPECT_STREQ("/", file.api_parent.c_str()); | ||||
|   EXPECT_LT(utils::time::get_time_now() - (utils::time::NANOS_PER_SECOND * 5U), | ||||
|             file.accessed_date); | ||||
|   EXPECT_LT(utils::time::get_time_now() - (utils::time::NANOS_PER_SECOND * 5U), | ||||
|             file.changed_date); | ||||
|   EXPECT_LT(utils::time::get_time_now() - (utils::time::NANOS_PER_SECOND * 5U), | ||||
|             file.creation_date); | ||||
|   EXPECT_LT(utils::time::get_time_now() - (utils::time::NANOS_PER_SECOND * 5U), | ||||
|             file.modified_date); | ||||
|  | ||||
|   EXPECT_EQ(api_error::success, provider.remove_file("/pt01.txt")); | ||||
| } | ||||
|  | ||||
| static void get_file_fails_if_file_not_found(i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   api_file file{}; | ||||
|   EXPECT_EQ(api_error::item_not_found, provider.get_file("/not_found", file)); | ||||
| } | ||||
|  | ||||
| static void get_file_fails_if_item_is_directory(const app_config &cfg, | ||||
|                                                 i_provider &provider) { | ||||
|   fmt::println("testing|{}|{}", | ||||
|                app_config::get_provider_name(provider.get_provider_type()), | ||||
|                __FUNCTION__); | ||||
|   if (provider.get_provider_type() == provider_type::encrypt) { | ||||
|     const auto source_path = | ||||
|     auto source_path = | ||||
|         utils::path::combine(cfg.get_encrypt_config().path, {"sub10"}); | ||||
|  | ||||
|     std::string api_path{}; | ||||
| @@ -542,7 +683,15 @@ static void get_file_fails_if_item_is_directory(const app_config &cfg, | ||||
|  | ||||
|     api_file file{}; | ||||
|     EXPECT_EQ(api_error::directory_exists, provider.get_file(api_path, file)); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   create_directory(provider, "/dir01"); | ||||
|  | ||||
|   api_file file{}; | ||||
|   EXPECT_EQ(api_error::directory_exists, provider.get_file("/dir01", file)); | ||||
|  | ||||
|   EXPECT_EQ(api_error::success, provider.remove_directory("/dir01")); | ||||
| } | ||||
|  | ||||
| static void get_file_list(const app_config &cfg, i_provider &provider) { | ||||
| @@ -593,7 +742,6 @@ static void run_tests(const app_config &cfg, i_provider &provider) { | ||||
|   get_api_path_from_source(cfg, provider); | ||||
|   get_api_path_from_source_fails_if_file_not_found(cfg, provider); | ||||
|  | ||||
|   // TODO: continue here | ||||
|   get_directory_items(cfg, provider); | ||||
|   get_directory_items_fails_if_directory_not_found(provider); | ||||
|   get_directory_items_fails_if_item_is_file(cfg, provider); | ||||
| @@ -629,17 +777,16 @@ static void run_tests(const app_config &cfg, i_provider &provider) { | ||||
|   upload_file(provider); */ | ||||
| } | ||||
|  | ||||
| TEST(providers, encrypt_provider) { | ||||
|   const auto config_path = | ||||
|       utils::path::combine(test::get_test_output_dir(), {"encrypt_provider"}); | ||||
|  | ||||
| TEST(providers_test, encrypt_provider) { | ||||
|   auto config_path = utils::path::combine(test::get_test_output_dir(), | ||||
|                                           {"provider", "encrypt"}); | ||||
|   console_consumer consumer{}; | ||||
|   event_system::instance().start(); | ||||
|  | ||||
|   { | ||||
|     app_config cfg(provider_type::encrypt, config_path); | ||||
|  | ||||
|     const auto encrypt_path = | ||||
|     auto encrypt_path = | ||||
|         utils::path::combine(test::get_test_input_dir(), {"encrypt"}); | ||||
|  | ||||
|     EXPECT_STREQ( | ||||
| @@ -673,9 +820,9 @@ TEST(providers, encrypt_provider) { | ||||
|   event_system::instance().stop(); | ||||
| } | ||||
|  | ||||
| TEST(providers, s3_provider) { | ||||
|   const auto config_path = | ||||
|       utils::path::combine(test::get_test_output_dir(), {"s3_provider"}); | ||||
| TEST(providers_test, s3_provider) { | ||||
|   auto config_path = | ||||
|       utils::path::combine(test::get_test_output_dir(), {"provider", "s3"}); | ||||
|  | ||||
|   console_consumer consumer{}; | ||||
|   event_system::instance().start(); | ||||
| @@ -685,7 +832,7 @@ TEST(providers, s3_provider) { | ||||
|     { | ||||
|       app_config src_cfg( | ||||
|           provider_type::s3, | ||||
|           utils::path::combine(test::get_test_config_dir(), {"storj"})); | ||||
|           utils::path::combine(test::get_test_config_dir(), {"s3"})); | ||||
|       cfg.set_s3_config(src_cfg.get_s3_config()); | ||||
|     } | ||||
|  | ||||
| @@ -713,9 +860,9 @@ TEST(providers, s3_provider) { | ||||
|   event_system::instance().stop(); | ||||
| } | ||||
|  | ||||
| TEST(providers, sia_provider) { | ||||
|   const auto config_path = | ||||
|       utils::path::combine(test::get_test_output_dir(), {"sia_provider"}); | ||||
| TEST(providers_test, sia_provider) { | ||||
|   auto config_path = | ||||
|       utils::path::combine(test::get_test_output_dir(), {"sia", "provider"}); | ||||
|  | ||||
|   console_consumer consumer{}; | ||||
|   event_system::instance().start(); | ||||
| @@ -753,5 +900,3 @@ TEST(providers, sia_provider) { | ||||
|   event_system::instance().stop(); | ||||
| } | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // 0 | ||||
|   | ||||
| @@ -29,7 +29,7 @@ | ||||
| namespace repertory { | ||||
| static constexpr const std::size_t test_chunk_size{1024U}; | ||||
|  | ||||
| TEST(upload, can_upload_a_valid_file) { | ||||
| TEST(upload_test, can_upload_a_valid_file) { | ||||
|   console_consumer con; | ||||
|  | ||||
|   event_system::instance().start(); | ||||
| @@ -71,7 +71,7 @@ TEST(upload, can_upload_a_valid_file) { | ||||
|   event_system::instance().stop(); | ||||
| } | ||||
|  | ||||
| TEST(upload, can_cancel_upload) { | ||||
| TEST(upload_test, can_cancel_upload) { | ||||
|   console_consumer con; | ||||
|  | ||||
|   event_system::instance().start(); | ||||
| @@ -135,7 +135,7 @@ TEST(upload, can_cancel_upload) { | ||||
|   event_system::instance().stop(); | ||||
| } | ||||
|  | ||||
| TEST(upload, can_stop_upload) { | ||||
| TEST(upload_test, can_stop_upload) { | ||||
|   console_consumer con; | ||||
|  | ||||
|   event_system::instance().start(); | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
| #include "utils/file.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| TEST(utils, convert_api_date) { | ||||
| TEST(utils_test, convert_api_date) { | ||||
| #if defined(_WIN32) | ||||
|   auto file_time = utils::time::unix_time_to_filetime( | ||||
|       s3_provider::convert_api_date("2009-10-12T17:50:30.111Z")); | ||||
| @@ -63,7 +63,7 @@ TEST(utils, convert_api_date) { | ||||
| #endif // defined(_WIN32) | ||||
| } | ||||
|  | ||||
| TEST(utils, generate_sha256) { | ||||
| TEST(utils_test, generate_sha256) { | ||||
|   auto res = utils::file::file{__FILE__}.sha256(); | ||||
|   EXPECT_TRUE(res.has_value()); | ||||
|   if (res.has_value()) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user