initial commit
This commit is contained in:
155
tests/aws_s3_comm_test.cpp
Normal file
155
tests/aws_s3_comm_test.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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.
|
||||
*/
|
||||
#if defined(REPERTORY_ENABLE_S3_TESTING)
|
||||
|
||||
#include "comm/aws_s3/aws_s3_comm.hpp"
|
||||
#include "common.hpp"
|
||||
#include "fixtures/aws_s3_comm_fixture.hpp"
|
||||
#include "test_common.hpp"
|
||||
|
||||
namespace repertory {
|
||||
TEST_F(aws_s3_comm_test, upload_file) {
|
||||
auto ret = s3_comm_->upload_file(
|
||||
"/repertory/test.txt", __FILE__, "", []() -> std::string { return ""; },
|
||||
[](const std::string &) -> api_error { return api_error::success; }, false);
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
|
||||
ret = s3_comm_->upload_file(
|
||||
"/repertory/subdir/test2.txt", __FILE__, "", []() -> std::string { return ""; },
|
||||
[](const std::string &) -> api_error { return api_error::success; }, false);
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
}
|
||||
|
||||
TEST_F(aws_s3_comm_test, get_directory_items) {
|
||||
directory_item_list list{};
|
||||
auto ret = s3_comm_->get_directory_items(
|
||||
"/repertory/subdir", [](directory_item &, const bool &) {}, list);
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
}
|
||||
|
||||
TEST_F(aws_s3_comm_test, list_files) {
|
||||
api_file_list list{};
|
||||
auto ret = s3_comm_->get_file_list(
|
||||
[](const std::string &) -> std::string { return ""; },
|
||||
[](const std::string &, const std::string &object_name) -> std::string {
|
||||
return object_name;
|
||||
},
|
||||
list);
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
}
|
||||
|
||||
TEST_F(aws_s3_comm_test, read_file_bytes) {
|
||||
bool stop_requested = false;
|
||||
std::vector<char> data;
|
||||
auto ret = s3_comm_->read_file_bytes(
|
||||
"/repertory/test.txt", 2, 0, data, []() -> std::string { return ""; },
|
||||
[]() -> std::uint64_t { return 0ull; }, []() -> std::string { return ""; }, stop_requested);
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
}
|
||||
|
||||
TEST_F(aws_s3_comm_test, exists) {
|
||||
EXPECT_TRUE(s3_comm_->exists("/repertory/test.txt", []() -> std::string { return ""; }));
|
||||
EXPECT_FALSE(s3_comm_->exists("/repertory/subdir/test.txt", []() -> std::string { return ""; }));
|
||||
}
|
||||
|
||||
TEST_F(aws_s3_comm_test, get_file) {
|
||||
api_file file{};
|
||||
auto ret = s3_comm_->get_file(
|
||||
"/repertory/test.txt", []() -> std::string { return ""; },
|
||||
[](const std::string &, const std::string &object_name) -> std::string {
|
||||
return object_name;
|
||||
},
|
||||
[]() -> std::string { return ""; }, file);
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
}
|
||||
|
||||
TEST_F(aws_s3_comm_test, remove_file) {
|
||||
auto ret = s3_comm_->remove_file("/repertory/test.txt", []() -> std::string { return ""; });
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
ret = s3_comm_->remove_file("/repertory/subdir/test2.txt", []() -> std::string { return ""; });
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
}
|
||||
|
||||
TEST_F(aws_s3_comm_test, rename_file) {
|
||||
auto ret = s3_comm_->upload_file(
|
||||
"/repertory/test_r1.txt", __FILE__, "", []() -> std::string { return ""; },
|
||||
[](const std::string &) -> api_error { return api_error::success; }, false);
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
s3_comm_->remove_file("/repertory/test_r2.txt", []() -> std::string { return ""; });
|
||||
|
||||
ret = s3_comm_->rename_file("/repertory/test_r1.txt", "/repertory/test_r2.txt");
|
||||
EXPECT_EQ(api_error::not_implemented, ret);
|
||||
EXPECT_TRUE(s3_comm_->exists("/repertory/test_r1.txt", []() -> std::string { return ""; }));
|
||||
EXPECT_FALSE(s3_comm_->exists("/repertory/test_r2.txt", []() -> std::string { return ""; }));
|
||||
}
|
||||
|
||||
TEST_F(aws_s3_comm_test, create_bucket_and_remove_bucket) {
|
||||
auto ret = s3_comm_->create_bucket("/repertory2");
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
|
||||
ret = s3_comm_->remove_bucket("/repertory2");
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
}
|
||||
|
||||
TEST_F(aws_s3_comm_test, upload_file_encrypted) {
|
||||
const auto source_file_path = generate_test_file_name("./", "awscomm");
|
||||
auto file_size = 2u * utils::encryption::encrypting_reader::get_data_chunk_size() + 3u;
|
||||
auto source_file = create_random_file(source_file_path, file_size);
|
||||
|
||||
auto stop_requested = false;
|
||||
std::string key;
|
||||
auto ret = s3_comm_->upload_file(
|
||||
"/repertory/test.txt", source_file_path, "test", []() -> std::string { return ""; },
|
||||
[&key](const std::string &k) -> api_error {
|
||||
key = k;
|
||||
std::cout << "key:" << key << std::endl;
|
||||
return api_error::success;
|
||||
},
|
||||
stop_requested);
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
|
||||
std::uint64_t offset = 0u;
|
||||
auto remain = file_size;
|
||||
while ((ret == api_error::success) && remain) {
|
||||
std::vector<char> data;
|
||||
ret = s3_comm_->read_file_bytes(
|
||||
"/repertory/test.txt",
|
||||
std::min(remain, utils::encryption::encrypting_reader::get_data_chunk_size()), offset, data,
|
||||
[&key]() -> std::string { return key; },
|
||||
[&file_size]() -> std::uint64_t { return file_size; },
|
||||
[]() -> std::string { return "test"; }, stop_requested);
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
|
||||
std::vector<char> data2(data.size());
|
||||
std::size_t bytes_read{};
|
||||
source_file->read_bytes(&data2[0u], data2.size(), offset, bytes_read);
|
||||
|
||||
EXPECT_EQ(0, std::memcmp(&data2[0u], &data[0u], data2.size()));
|
||||
remain -= data.size();
|
||||
offset += data.size();
|
||||
}
|
||||
|
||||
source_file->close();
|
||||
utils::file::delete_file(source_file_path);
|
||||
|
||||
s3_comm_->remove_file("/repertory/test.txt", [&key]() -> std::string { return key; });
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_ENABLE_S3_TESTING
|
944
tests/config_test.cpp
Normal file
944
tests/config_test.cpp
Normal file
@ -0,0 +1,944 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "app_config.hpp"
|
||||
#include "test_common.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class config_test : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./data"));
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./data"));
|
||||
}
|
||||
};
|
||||
|
||||
const auto DEFAULT_SIA_CONFIG = "{\n"
|
||||
" \"ApiAuth\": \"\",\n"
|
||||
" \"ApiPort\": 11101,\n"
|
||||
" \"ApiUser\": \"repertory\",\n"
|
||||
" \"ChunkDownloaderTimeoutSeconds\": 30,\n"
|
||||
" \"EnableChunkDownloaderTimeout\": true,\n"
|
||||
" \"EnableCommDurationEvents\": false,\n"
|
||||
" \"EnableDriveEvents\": false,\n"
|
||||
" \"EnableMaxCacheSize\": true,\n"
|
||||
#ifdef _WIN32
|
||||
" \"EnableMountManager\": false,\n"
|
||||
#endif
|
||||
" \"EventLevel\": \"normal\",\n"
|
||||
" \"EvictionDelayMinutes\": 30,\n"
|
||||
" \"EvictionUsesAccessedTime\": false,\n"
|
||||
" \"HighFreqIntervalSeconds\": 30,\n"
|
||||
" \"HostConfig\": {\n"
|
||||
" \"AgentString\": \"Sia-Agent\",\n"
|
||||
" \"ApiPassword\": \"\",\n"
|
||||
" \"ApiPort\": 9980,\n"
|
||||
" \"HostNameOrIp\": \"localhost\",\n"
|
||||
" \"TimeoutMs\": 60000\n"
|
||||
" },\n"
|
||||
" \"LowFreqIntervalSeconds\": 3600,\n"
|
||||
" \"MaxCacheSizeBytes\": 21474836480,\n"
|
||||
" \"MinimumRedundancy\": 2.5,\n"
|
||||
" \"OnlineCheckRetrySeconds\": 60,\n"
|
||||
" \"OrphanedFileRetentionDays\": 15,\n"
|
||||
" \"PreferredDownloadType\": \"fallback\",\n"
|
||||
" \"ReadAheadCount\": 4,\n"
|
||||
" \"RemoteMount\": {\n"
|
||||
" \"EnableRemoteMount\": false,\n"
|
||||
" \"IsRemoteMount\": false,\n"
|
||||
" \"RemoteClientPoolSize\": 10,\n"
|
||||
" \"RemoteHostNameOrIp\": \"\",\n"
|
||||
" \"RemoteMaxConnections\": 20,\n"
|
||||
" \"RemotePort\": 20000,\n"
|
||||
" \"RemoteReceiveTimeoutSeconds\": 120,\n"
|
||||
" \"RemoteSendTimeoutSeconds\": 30,\n"
|
||||
" \"RemoteToken\": \"\"\n"
|
||||
" },\n"
|
||||
" \"RetryReadCount\": 6,\n"
|
||||
" \"RingBufferFileSize\": 512,\n"
|
||||
" \"StorageByteMonth\": \"0\",\n"
|
||||
" \"Version\": " +
|
||||
std::to_string(REPERTORY_CONFIG_VERSION) +
|
||||
"\n"
|
||||
"}";
|
||||
|
||||
const auto DEFAULT_S3_CONFIG = "{\n"
|
||||
" \"ApiAuth\": \"\",\n"
|
||||
" \"ApiPort\": 11103,\n"
|
||||
" \"ApiUser\": \"repertory\",\n"
|
||||
" \"ChunkDownloaderTimeoutSeconds\": 30,\n"
|
||||
" \"EnableChunkDownloaderTimeout\": true,\n"
|
||||
" \"EnableCommDurationEvents\": false,\n"
|
||||
" \"EnableDriveEvents\": false,\n"
|
||||
" \"EnableMaxCacheSize\": true,\n"
|
||||
#ifdef _WIN32
|
||||
" \"EnableMountManager\": false,\n"
|
||||
#endif
|
||||
" \"EventLevel\": \"normal\",\n"
|
||||
" \"EvictionDelayMinutes\": 30,\n"
|
||||
" \"EvictionUsesAccessedTime\": false,\n"
|
||||
" \"HighFreqIntervalSeconds\": 30,\n"
|
||||
" \"LowFreqIntervalSeconds\": 3600,\n"
|
||||
" \"MaxCacheSizeBytes\": 21474836480,\n"
|
||||
" \"MaxUploadCount\": 5,\n"
|
||||
" \"OnlineCheckRetrySeconds\": 60,\n"
|
||||
" \"OrphanedFileRetentionDays\": 15,\n"
|
||||
" \"PreferredDownloadType\": \"fallback\",\n"
|
||||
" \"ReadAheadCount\": 4,\n"
|
||||
" \"RemoteMount\": {\n"
|
||||
" \"EnableRemoteMount\": false,\n"
|
||||
" \"IsRemoteMount\": false,\n"
|
||||
" \"RemoteClientPoolSize\": 10,\n"
|
||||
" \"RemoteHostNameOrIp\": \"\",\n"
|
||||
" \"RemoteMaxConnections\": 20,\n"
|
||||
" \"RemotePort\": 20002,\n"
|
||||
" \"RemoteReceiveTimeoutSeconds\": 120,\n"
|
||||
" \"RemoteSendTimeoutSeconds\": 30,\n"
|
||||
" \"RemoteToken\": \"\"\n"
|
||||
" },\n"
|
||||
" \"RetryReadCount\": 6,\n"
|
||||
" \"RingBufferFileSize\": 512,\n"
|
||||
" \"S3Config\": {\n"
|
||||
" \"AccessKey\": \"\",\n"
|
||||
" \"Bucket\": \"\",\n"
|
||||
" \"CacheTimeoutSeconds\": 60,\n"
|
||||
" \"EncryptionToken\": \"\",\n"
|
||||
" \"Region\": \"any\",\n"
|
||||
" \"SecretKey\": \"\",\n"
|
||||
" \"TimeoutMs\": 60000,\n"
|
||||
" \"URL\": \"\"\n"
|
||||
" },\n"
|
||||
" \"Version\": " +
|
||||
std::to_string(REPERTORY_CONFIG_VERSION) +
|
||||
"\n"
|
||||
"}";
|
||||
|
||||
const auto DEFAULT_SKYNET_CONFIG = "{\n"
|
||||
" \"ApiAuth\": \"\",\n"
|
||||
" \"ApiPort\": 11104,\n"
|
||||
" \"ApiUser\": \"repertory\",\n"
|
||||
" \"ChunkDownloaderTimeoutSeconds\": 30,\n"
|
||||
" \"EnableChunkDownloaderTimeout\": true,\n"
|
||||
" \"EnableCommDurationEvents\": false,\n"
|
||||
" \"EnableDriveEvents\": false,\n"
|
||||
" \"EnableMaxCacheSize\": true,\n"
|
||||
#ifdef _WIN32
|
||||
" \"EnableMountManager\": false,\n"
|
||||
#endif
|
||||
" \"EventLevel\": \"normal\",\n"
|
||||
" \"EvictionDelayMinutes\": 30,\n"
|
||||
" \"EvictionUsesAccessedTime\": false,\n"
|
||||
" \"HighFreqIntervalSeconds\": 30,\n"
|
||||
" \"LowFreqIntervalSeconds\": 3600,\n"
|
||||
" \"MaxCacheSizeBytes\": 21474836480,\n"
|
||||
" \"MaxUploadCount\": 5,\n"
|
||||
" \"OnlineCheckRetrySeconds\": 60,\n"
|
||||
" \"PreferredDownloadType\": \"fallback\",\n"
|
||||
" \"ReadAheadCount\": 4,\n"
|
||||
" \"RemoteMount\": {\n"
|
||||
" \"EnableRemoteMount\": false,\n"
|
||||
" \"IsRemoteMount\": false,\n"
|
||||
" \"RemoteClientPoolSize\": 10,\n"
|
||||
" \"RemoteHostNameOrIp\": \"\",\n"
|
||||
" \"RemoteMaxConnections\": 20,\n"
|
||||
" \"RemotePort\": 20003,\n"
|
||||
" \"RemoteReceiveTimeoutSeconds\": 120,\n"
|
||||
" \"RemoteSendTimeoutSeconds\": 30,\n"
|
||||
" \"RemoteToken\": \"\"\n"
|
||||
" },\n"
|
||||
" \"RetryReadCount\": 6,\n"
|
||||
" \"RingBufferFileSize\": 512,\n"
|
||||
" \"SkynetConfig\": {\n"
|
||||
" \"EncryptionToken\": \"\",\n"
|
||||
" \"PortalList\": [\n"
|
||||
" {\n"
|
||||
" \"AgentString\": \"\",\n"
|
||||
" \"ApiPassword\": \"\",\n"
|
||||
" \"ApiPort\": 443,\n"
|
||||
" \"AuthPassword\": \"\",\n"
|
||||
" \"AuthURL\": \"" +
|
||||
DEFAULT_SKYNET_URLS[1u] +
|
||||
"\",\n"
|
||||
" \"AuthUser\": \"\",\n"
|
||||
" \"HostNameOrIp\": \"" +
|
||||
DEFAULT_SKYNET_URLS[0u] +
|
||||
"\",\n"
|
||||
" \"Path\": \"\",\n"
|
||||
" \"Protocol\": \"https\",\n"
|
||||
" \"TimeoutMs\": 60000\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" },\n"
|
||||
" \"Version\": " +
|
||||
std::to_string(REPERTORY_CONFIG_VERSION) +
|
||||
"\n"
|
||||
"}";
|
||||
|
||||
TEST_F(config_test, sia_default_settings) {
|
||||
const auto config_file =
|
||||
utils::path::absolute(utils::path::combine("./data/sia", {"config.json"}));
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
app_config config(provider_type::sia, "./data");
|
||||
config.set_remote_token("");
|
||||
config.set_api_auth("");
|
||||
config.set_value_by_name("HostConfig.ApiPassword", "");
|
||||
json data;
|
||||
utils::file::read_json_file(config_file, data);
|
||||
EXPECT_STREQ(DEFAULT_SIA_CONFIG.c_str(), data.dump(2).c_str());
|
||||
EXPECT_TRUE(utils::file::is_directory("./data/sia/cache"));
|
||||
EXPECT_TRUE(utils::file::is_directory("./data/sia/logs"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, s3_default_settings) {
|
||||
const auto config_file =
|
||||
utils::path::absolute(utils::path::combine("./data/s3", {"config.json"}));
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
app_config config(provider_type::s3, "./data/s3");
|
||||
config.set_remote_token("");
|
||||
config.set_api_auth("");
|
||||
json data;
|
||||
utils::file::read_json_file(config_file, data);
|
||||
EXPECT_STREQ(DEFAULT_S3_CONFIG.c_str(), data.dump(2).c_str());
|
||||
EXPECT_TRUE(utils::file::is_directory("./data/s3/cache"));
|
||||
EXPECT_TRUE(utils::file::is_directory("./data/s3/logs"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, skynet_default_settings) {
|
||||
const auto config_file =
|
||||
utils::path::absolute(utils::path::combine("./data/skynet", {"config.json"}));
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
app_config config(provider_type::skynet, "./data");
|
||||
config.set_remote_token("");
|
||||
config.set_api_auth("");
|
||||
json data;
|
||||
utils::file::read_json_file(config_file, data);
|
||||
EXPECT_STREQ(DEFAULT_SKYNET_CONFIG.c_str(), data.dump(2).c_str());
|
||||
EXPECT_TRUE(utils::file::is_directory("./data/skynet/cache"));
|
||||
EXPECT_TRUE(utils::file::is_directory("./data/skynet/logs"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, api_path) {
|
||||
std::string original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
EXPECT_EQ(original_value.substr(0, 2), config.get_api_user());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, chunk_downloader_timeout_secs) {
|
||||
std::uint8_t original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
original_value = config.get_chunk_downloader_timeout_secs();
|
||||
config.set_chunk_downloader_timeout_secs(original_value + 5);
|
||||
EXPECT_EQ(original_value + 5, config.get_chunk_downloader_timeout_secs());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_EQ(original_value + 5, config.get_chunk_downloader_timeout_secs());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, enable_chunk_download_timeout) {
|
||||
bool original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
original_value = config.get_enable_chunk_download_timeout();
|
||||
config.set_enable_chunk_downloader_timeout(not original_value);
|
||||
EXPECT_EQ(not original_value, config.get_enable_chunk_download_timeout());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_EQ(not original_value, config.get_enable_chunk_download_timeout());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, enable_comm_duration_events) {
|
||||
bool original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
original_value = config.get_enable_comm_duration_events();
|
||||
config.set_enable_comm_duration_events(not original_value);
|
||||
EXPECT_EQ(not original_value, config.get_enable_comm_duration_events());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_EQ(not original_value, config.get_enable_comm_duration_events());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, enable_drive_events) {
|
||||
bool original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
EXPECT_EQ(not original_value, config.get_enable_drive_events());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, enable_max_cache_size) {
|
||||
bool original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
original_value = config.get_enable_max_cache_size();
|
||||
config.set_enable_max_cache_size(not original_value);
|
||||
EXPECT_EQ(not original_value, config.get_enable_max_cache_size());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_EQ(not original_value, config.get_enable_max_cache_size());
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
TEST_F(config_test, enable_mount_manager) {
|
||||
bool original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
EXPECT_EQ(not original_value, config.get_enable_mount_manager());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
TEST_F(config_test, event_level) {
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
EXPECT_EQ(not original_value, config.get_eviction_uses_accessed_time());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, high_frequency_interval_secs) {
|
||||
std::uint8_t original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
original_value = config.get_high_frequency_interval_secs();
|
||||
config.set_high_frequency_interval_secs(original_value + 5);
|
||||
EXPECT_EQ(original_value + 5, config.get_high_frequency_interval_secs());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_EQ(original_value + 5, config.get_high_frequency_interval_secs());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, low_frequency_interval_secs) {
|
||||
std::uint32_t original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
original_value = config.get_low_frequency_interval_secs();
|
||||
config.set_low_frequency_interval_secs(original_value + 5);
|
||||
EXPECT_EQ(original_value + 5, config.get_low_frequency_interval_secs());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_EQ(original_value + 5, config.get_low_frequency_interval_secs());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, max_cache_size_bytes) {
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
EXPECT_EQ(100u * 1024 * 1024, config.get_max_cache_size_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, max_upload_count) {
|
||||
{
|
||||
app_config config(provider_type::skynet, "./data");
|
||||
config.set_max_upload_count(8u);
|
||||
EXPECT_EQ(std::uint8_t(8u), config.get_max_upload_count());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::skynet, "./data");
|
||||
EXPECT_EQ(std::uint8_t(8u), config.get_max_upload_count());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::skynet, "./data");
|
||||
config.set_max_upload_count(0u);
|
||||
EXPECT_EQ(std::uint8_t(1u), config.get_max_upload_count());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, minimum_redundancy) {
|
||||
double original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
original_value = config.get_minimum_redundancy();
|
||||
config.set_minimum_redundancy(original_value + 0.1);
|
||||
EXPECT_EQ(original_value + 0.1, config.get_minimum_redundancy());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_EQ(original_value + 0.1, config.get_minimum_redundancy());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, online_check_retry_secs) {
|
||||
std::uint16_t original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
config.set_orphaned_file_retention_days(32);
|
||||
EXPECT_EQ(31, config.get_orphaned_file_retention_days());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, read_ahead_count) {
|
||||
std::uint8_t original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
original_value = config.get_read_ahead_count();
|
||||
config.set_read_ahead_count(original_value + 5);
|
||||
EXPECT_EQ(original_value + 5, config.get_read_ahead_count());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_EQ(original_value + 5, config.get_read_ahead_count());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, storage_byte_month) {
|
||||
api_currency original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
original_value = config.get_storage_byte_month();
|
||||
config.set_storage_byte_month(original_value + 5);
|
||||
EXPECT_EQ(original_value + 5, config.get_storage_byte_month());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_EQ(original_value + 5, config.get_storage_byte_month());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, get_cache_directory) {
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_STREQ(utils::path::absolute("./data/sia/cache").c_str(),
|
||||
config.get_cache_directory().c_str());
|
||||
}
|
||||
|
||||
{
|
||||
app_config config(provider_type::skynet, "./data");
|
||||
EXPECT_STREQ(utils::path::absolute("./data/skynet/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("./data/sia", {"config.json"}));
|
||||
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_STREQ(config_file.c_str(), config.get_config_file_path().c_str());
|
||||
}
|
||||
|
||||
{
|
||||
const auto config_file =
|
||||
utils::path::absolute(utils::path::combine("./data/skynet", {"config.json"}));
|
||||
|
||||
app_config config(provider_type::skynet, "./data");
|
||||
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, "./data");
|
||||
EXPECT_STREQ(utils::path::absolute("./data/sia").c_str(), config.get_data_directory().c_str());
|
||||
}
|
||||
|
||||
{
|
||||
app_config config(provider_type::skynet, "./data");
|
||||
EXPECT_STREQ(utils::path::absolute("./data/skynet").c_str(),
|
||||
config.get_data_directory().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, get_log_directory) {
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_STREQ(utils::path::absolute("./data/sia/logs").c_str(),
|
||||
config.get_log_directory().c_str());
|
||||
}
|
||||
|
||||
{
|
||||
app_config config(provider_type::skynet, "./data");
|
||||
EXPECT_STREQ(utils::path::absolute("./data/skynet/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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
config.set_ring_buffer_file_size(63u);
|
||||
EXPECT_EQ(64u, config.get_ring_buffer_file_size());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
config.set_ring_buffer_file_size(1025u);
|
||||
EXPECT_EQ(1024u, config.get_ring_buffer_file_size());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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::string data_directory[] = {
|
||||
app_config::default_data_directory(provider_type::sia),
|
||||
app_config::default_data_directory(provider_type::skynet),
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
const auto local_app_data = utils::get_environment_variable("localappdata");
|
||||
#endif
|
||||
#if __linux__
|
||||
const auto local_app_data =
|
||||
utils::path::combine(utils::get_environment_variable("HOME"), {".local"});
|
||||
#endif
|
||||
#ifdef __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());
|
||||
expected_directory = utils::path::combine(local_app_data, {"/repertory2/skynet"});
|
||||
EXPECT_STREQ(expected_directory.c_str(), data_directory[1].c_str());
|
||||
}
|
||||
|
||||
TEST_F(config_test, default_rpc_port) {
|
||||
EXPECT_EQ(11101u, 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());
|
||||
EXPECT_STREQ("Skynet", app_config::get_provider_display_name(provider_type::skynet).c_str());
|
||||
}
|
||||
|
||||
TEST_F(config_test, get_provider_minimum_version) {
|
||||
EXPECT_STREQ(MIN_SIA_VERSION,
|
||||
app_config::get_provider_minimum_version(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());
|
||||
EXPECT_STREQ("skynet", app_config::get_provider_name(provider_type::skynet).c_str());
|
||||
}
|
||||
|
||||
TEST_F(config_test, get_provider_path_name) {
|
||||
EXPECT_STREQ("siapath", app_config::get_provider_path_name(provider_type::sia).c_str());
|
||||
}
|
||||
|
||||
TEST_F(config_test, get_version) {
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_EQ(REPERTORY_CONFIG_VERSION, config.get_version());
|
||||
}
|
||||
|
||||
{
|
||||
app_config config(provider_type::skynet, "./data");
|
||||
EXPECT_EQ(REPERTORY_CONFIG_VERSION, config.get_version());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, enable_remote_mount) {
|
||||
bool original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
EXPECT_STREQ("my.host.name", config.get_remote_host_name_or_ip().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, remote_port) {
|
||||
std::uint16_t original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
original_value = config.get_remote_port();
|
||||
config.set_remote_port(original_value + 5);
|
||||
EXPECT_EQ(original_value + 5, config.get_remote_port());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_EQ(original_value + 5, config.get_remote_port());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, remote_receive_timeout_secs) {
|
||||
std::uint16_t original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
EXPECT_EQ(original_value + 5, config.get_remote_send_timeout_secs());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, remote_token) {
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
config.set_remote_token("myToken");
|
||||
EXPECT_STREQ("myToken", config.get_remote_token().c_str());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
EXPECT_STREQ("myToken", config.get_remote_token().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, remote_client_pool_size) {
|
||||
std::uint8_t original_value;
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
config.set_remote_client_pool_size(0);
|
||||
EXPECT_EQ(5, config.get_remote_client_pool_size());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
config.set_remote_max_connections(0);
|
||||
EXPECT_EQ(1, config.get_remote_max_connections());
|
||||
}
|
||||
{
|
||||
app_config config(provider_type::sia, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
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, "./data");
|
||||
config.set_retry_read_count(1);
|
||||
EXPECT_EQ(2, config.get_retry_read_count());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(config_test, cache_timeout_seconds_minimum_value) {
|
||||
{
|
||||
app_config config(provider_type::s3, "./data");
|
||||
config.set_value_by_name("S3Config.CacheTimeoutSeconds", "1");
|
||||
EXPECT_EQ(std::uint16_t(5u), config.get_s3_config().cache_timeout_secs);
|
||||
}
|
||||
}
|
||||
} // namespace repertory
|
315
tests/directory_db_test.cpp
Normal file
315
tests/directory_db_test.cpp
Normal file
@ -0,0 +1,315 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "fixtures/directory_db_fixture.hpp"
|
||||
#include "test_common.hpp"
|
||||
|
||||
namespace repertory {
|
||||
static const auto dirs = {"/",
|
||||
"/root",
|
||||
"/root/sub1",
|
||||
"/root/sub2",
|
||||
"/root/sub2/sub2_sub1",
|
||||
"/root/sub2/sub2_sub2",
|
||||
"/root/sub2/sub2_sub2/sub2_sub2_sub1",
|
||||
"/root/sub3"};
|
||||
|
||||
TEST_F(directory_db_test, is_directory) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_TRUE(db_->is_directory(dir));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_directory) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->remove_directory("/root/sub2/sub2_sub1"));
|
||||
EXPECT_FALSE(db_->is_directory("/root/sub2/sub2_sub1"));
|
||||
EXPECT_EQ(1u, db_->get_sub_directory_count("/root/sub2"));
|
||||
EXPECT_TRUE(db_->is_directory("/root/sub2/sub2_sub2"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, get_sub_directory_count) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
EXPECT_EQ(1u, db_->get_sub_directory_count("/"));
|
||||
EXPECT_EQ(3u, db_->get_sub_directory_count("/root"));
|
||||
EXPECT_EQ(0u, db_->get_sub_directory_count("/root/sub1"));
|
||||
EXPECT_EQ(2u, db_->get_sub_directory_count("/root/sub2"));
|
||||
EXPECT_EQ(0u, db_->get_sub_directory_count("/root/sub2/sub2_sub1"));
|
||||
EXPECT_EQ(1u, db_->get_sub_directory_count("/root/sub2/sub2_sub2"));
|
||||
EXPECT_EQ(0u, db_->get_sub_directory_count("/root/sub3"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, populate_sub_directories) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
directory_item_list list{};
|
||||
const auto dump_directory_list = [&]() {
|
||||
for (const auto &di : list) {
|
||||
std::cout << di.to_json().dump(2) << std::endl;
|
||||
}
|
||||
list.clear();
|
||||
};
|
||||
|
||||
std::cout << "/" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/", [](directory_item &, const bool &) {}, list);
|
||||
EXPECT_EQ(1u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root", [](directory_item &, const bool &) {}, list);
|
||||
EXPECT_EQ(3u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root/sub1" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root/sub1", [](directory_item &, const bool &) {}, list);
|
||||
EXPECT_EQ(0u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root/sub2" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root/sub2", [](directory_item &, const bool &) {}, list);
|
||||
EXPECT_EQ(2u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root/sub2/sub2_sub1" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root/sub2/sub2_sub1", [](directory_item &, const bool &) {}, list);
|
||||
EXPECT_EQ(0u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root/sub2/sub2_sub2" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root/sub2/sub2_sub2", [](directory_item &, const bool &) {}, list);
|
||||
EXPECT_EQ(1u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root/sub3" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root/sub3", [](directory_item &, const bool &) {}, list);
|
||||
EXPECT_EQ(0u, list.size());
|
||||
dump_directory_list();
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, is_file) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_TRUE(db_->is_file("/cow.txt"));
|
||||
EXPECT_FALSE(db_->is_directory("/cow.txt"));
|
||||
EXPECT_EQ(api_error::file_exists, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::file_exists, db_->create_directory("/cow.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_file) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::item_is_file, db_->remove_directory("/cow.txt"));
|
||||
EXPECT_TRUE(db_->remove_file("/cow.txt"));
|
||||
EXPECT_FALSE(db_->is_file("/cow.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, get_directory_item_count) {
|
||||
db_->create_directory("/");
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow2.txt"));
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/cow"));
|
||||
EXPECT_EQ(3u, db_->get_directory_item_count("/"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, get_file) {
|
||||
db_->create_directory("/");
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
|
||||
api_file file{};
|
||||
EXPECT_EQ(api_error::success, db_->get_file("/cow.txt", file, [](api_file &file) {
|
||||
EXPECT_STREQ("/cow.txt", file.api_path.c_str());
|
||||
}));
|
||||
EXPECT_STREQ("/cow.txt", file.api_path.c_str());
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, get_file_list) {
|
||||
db_->create_directory("/");
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow2.txt"));
|
||||
|
||||
api_file_list list;
|
||||
int i = 0;
|
||||
EXPECT_EQ(api_error::success, db_->get_file_list(list, [&i](api_file &file) {
|
||||
if (i++ == 0) {
|
||||
EXPECT_STREQ("/cow.txt", file.api_path.c_str());
|
||||
} else {
|
||||
EXPECT_STREQ("/cow2.txt", file.api_path.c_str());
|
||||
}
|
||||
}));
|
||||
|
||||
EXPECT_EQ(std::size_t(2u), list.size());
|
||||
EXPECT_STREQ("/cow.txt", list[0u].api_path.c_str());
|
||||
EXPECT_STREQ("/cow2.txt", list[1u].api_path.c_str());
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, get_total_item_count) {
|
||||
db_->create_directory("/");
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow2.txt"));
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/cow"));
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/cow/moose"));
|
||||
|
||||
EXPECT_EQ(std::uint64_t(5), db_->get_total_item_count());
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, populate_directory_files) {
|
||||
db_->create_directory("/");
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow2.txt"));
|
||||
|
||||
directory_item_list list;
|
||||
int i = 0;
|
||||
db_->populate_directory_files(
|
||||
"/",
|
||||
[&i](directory_item &di, const bool &) {
|
||||
di.meta[META_SIZE] = utils::string::from_int32(i + 1);
|
||||
EXPECT_FALSE(di.directory);
|
||||
if (i++ == 0) {
|
||||
EXPECT_STREQ("/cow.txt", &di.api_path[0]);
|
||||
} else {
|
||||
EXPECT_STREQ("/cow2.txt", &di.api_path[0]);
|
||||
}
|
||||
},
|
||||
list);
|
||||
|
||||
EXPECT_EQ(std::size_t(2u), list.size());
|
||||
|
||||
EXPECT_EQ(1u, list[0].size);
|
||||
EXPECT_STREQ("/cow.txt", &list[0].api_path[0]);
|
||||
|
||||
EXPECT_EQ(2u, list[1].size);
|
||||
EXPECT_STREQ("/cow2.txt", &list[1].api_path[0]);
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, create_directory_fails_if_directory_exists) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::directory_exists, db_->create_file("/root/sub1"));
|
||||
EXPECT_TRUE(db_->is_directory("/root/sub1"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, create_file_fails_if_file_exists) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::file_exists, db_->create_directory("/cow.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, create_file_fails_if_parent_does_not_exist) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::directory_not_found, db_->create_file("/moose/cow.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, create_directory_fails_if_parent_does_not_exist) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::directory_not_found, db_->create_file("/cow/moose"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_file_fails_if_directory_exists) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(db_->remove_file("/root/sub1"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_directory_fails_if_file_exists) {
|
||||
for (const auto &dir : dirs) {
|
||||
db_->create_directory(dir);
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::item_is_file, db_->remove_directory("/cow.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_directory_fails_if_sub_directories_exist) {
|
||||
db_->create_directory("/");
|
||||
db_->create_directory("/sub");
|
||||
db_->create_directory("/sub/sub2");
|
||||
|
||||
EXPECT_EQ(api_error::directory_not_empty, db_->remove_directory("/sub"));
|
||||
EXPECT_TRUE(db_->is_directory("/sub"));
|
||||
EXPECT_TRUE(db_->is_directory("/sub/sub2"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_directory_fails_if_files_exist) {
|
||||
db_->create_directory("/");
|
||||
db_->create_directory("/sub");
|
||||
db_->create_file("/sub/test.txt");
|
||||
|
||||
EXPECT_EQ(api_error::directory_not_empty, db_->remove_directory("/sub"));
|
||||
EXPECT_TRUE(db_->is_directory("/sub"));
|
||||
EXPECT_TRUE(db_->is_file("/sub/test.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_directory_fails_for_root_directory_by_default) {
|
||||
db_->create_directory("/");
|
||||
|
||||
EXPECT_EQ(api_error::access_denied, db_->remove_directory("/"));
|
||||
EXPECT_TRUE(db_->is_directory("/"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test,
|
||||
remove_directory_succeeds_for_root_directory_if_allow_remove_root_is_true) {
|
||||
db_->create_directory("/");
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->remove_directory("/", true));
|
||||
EXPECT_FALSE(db_->is_directory("/"));
|
||||
}
|
||||
} // namespace repertory
|
689
tests/download_manager_test.cpp
Normal file
689
tests/download_manager_test.cpp
Normal file
@ -0,0 +1,689 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "app_config.hpp"
|
||||
#include "download/download_manager.hpp"
|
||||
#include "events/consumers/console_consumer.hpp"
|
||||
#include "mocks/mock_open_file_table.hpp"
|
||||
#include "test_common.hpp"
|
||||
#include "utils/encrypting_reader.hpp"
|
||||
#include "utils/event_capture.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
static std::string get_source_file_name() {
|
||||
return generate_test_file_name("./", "downloader_manager");
|
||||
}
|
||||
|
||||
TEST(downloader_manager, no_hanging_on_download_fail) {
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./chunk_data");
|
||||
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
|
||||
event_capture ec({"download_begin", "download_end"}, {"download_timeout"});
|
||||
const auto test_source = get_source_file_name();
|
||||
utils::file::delete_file(test_source);
|
||||
|
||||
const auto chunk_size = utils::encryption::encrypting_reader::get_data_chunk_size();
|
||||
const auto file_size = (chunk_size * 5u) + 2u;
|
||||
const auto test_dest = get_source_file_name();
|
||||
utils::file::delete_file(test_dest);
|
||||
|
||||
auto nf = create_random_file(test_source, file_size);
|
||||
EXPECT_NE(nf, nullptr);
|
||||
if (nf) {
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &,
|
||||
const std::uint64_t &, std::vector<char> &,
|
||||
const bool &) -> api_error {
|
||||
#ifdef _WIN32
|
||||
::SetLastError(ERROR_ACCESS_DENIED);
|
||||
#else
|
||||
utils::set_last_error_code(EACCES);
|
||||
#endif
|
||||
return api_error::os_error;
|
||||
};
|
||||
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/test_chunk";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
fsi.source_path = test_dest;
|
||||
fsi.size = file_size;
|
||||
|
||||
download_manager dm(config, api_reader, true);
|
||||
mock_open_file_table oft(&dm, &fsi);
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(1ull));
|
||||
dm.start(&oft);
|
||||
|
||||
EXPECT_EQ(api_error::os_error, dm.download_file(1, fsi));
|
||||
|
||||
dm.stop();
|
||||
EXPECT_EQ(0u, dm.get_download_count());
|
||||
nf->close();
|
||||
|
||||
utils::file::delete_file(fsi.source_path);
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_source);
|
||||
event_system::instance().stop();
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
}
|
||||
|
||||
TEST(downloader_manager, single_chunk_no_offset) {
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./chunk_data");
|
||||
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
|
||||
event_capture ec({"download_begin", "download_end", "download_progress"}, {"DownloadTimeout"});
|
||||
const auto test_source = get_source_file_name();
|
||||
utils::file::delete_file(test_source);
|
||||
|
||||
const auto chunk_size = utils::encryption::encrypting_reader::get_data_chunk_size();
|
||||
const auto file_size = (chunk_size * 5u);
|
||||
auto nf = create_random_file(test_source, file_size);
|
||||
EXPECT_NE(nf, nullptr);
|
||||
if (nf) {
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
std::size_t bytes_read{};
|
||||
auto ret = nf->read_bytes(&data[0u], data.size(), offset, bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/test_chunk";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
fsi.source_path = test_source + "0";
|
||||
fsi.size = file_size;
|
||||
|
||||
download_manager dm(config, api_reader, true);
|
||||
mock_open_file_table oft(&dm, &fsi);
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(1ull));
|
||||
dm.start(&oft);
|
||||
|
||||
std::vector<char> read_buffer;
|
||||
EXPECT_EQ(api_error::success, dm.read_bytes(1, fsi, chunk_size, 0, read_buffer));
|
||||
EXPECT_EQ(chunk_size, read_buffer.size());
|
||||
|
||||
std::size_t bytes_read{};
|
||||
std::vector<char> source_buffer;
|
||||
source_buffer.resize(chunk_size);
|
||||
EXPECT_TRUE(nf->read_bytes(&source_buffer[0u], source_buffer.size(), 0, bytes_read));
|
||||
EXPECT_EQ(read_buffer.size(), bytes_read);
|
||||
EXPECT_EQ(read_buffer.size(), source_buffer.size());
|
||||
if (read_buffer.size() == source_buffer.size()) {
|
||||
EXPECT_EQ(0, memcmp(&read_buffer[0u], &source_buffer[0u], read_buffer.size()));
|
||||
}
|
||||
|
||||
dm.stop();
|
||||
EXPECT_EQ(0u, dm.get_download_count());
|
||||
nf->close();
|
||||
|
||||
utils::file::delete_file(fsi.source_path);
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_source);
|
||||
event_system::instance().stop();
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
}
|
||||
|
||||
TEST(downloader_manager, single_chunk_offset_overlap) {
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./chunk_data");
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
|
||||
event_capture ec(
|
||||
{
|
||||
"download_begin",
|
||||
"download_end",
|
||||
"download_progress",
|
||||
},
|
||||
{"download_timeout"});
|
||||
const auto test_source = get_source_file_name();
|
||||
utils::file::delete_file(test_source);
|
||||
const auto chunk_size = utils::encryption::encrypting_reader::get_data_chunk_size();
|
||||
const auto file_size = (chunk_size * 5u);
|
||||
auto nf = create_random_file(test_source, file_size);
|
||||
EXPECT_NE(nf, nullptr);
|
||||
if (nf) {
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
std::size_t bytes_read{};
|
||||
auto ret = nf->read_bytes(&data[0u], data.size(), offset, bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/test_chunk";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
fsi.source_path = test_source + "0";
|
||||
fsi.size = file_size;
|
||||
|
||||
download_manager dm(config, api_reader, true);
|
||||
mock_open_file_table oft(&dm, &fsi);
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(1ull));
|
||||
dm.start(&oft);
|
||||
|
||||
std::vector<char> read_buffer;
|
||||
EXPECT_EQ(api_error::success, dm.read_bytes(1, fsi, chunk_size, chunk_size / 2, read_buffer));
|
||||
EXPECT_EQ(chunk_size, read_buffer.size());
|
||||
|
||||
std::size_t bytes_read{};
|
||||
std::vector<char> source_buffer;
|
||||
source_buffer.resize(chunk_size);
|
||||
EXPECT_TRUE(
|
||||
nf->read_bytes(&source_buffer[0u], source_buffer.size(), chunk_size / 2, bytes_read));
|
||||
EXPECT_EQ(read_buffer.size(), bytes_read);
|
||||
EXPECT_EQ(read_buffer.size(), source_buffer.size());
|
||||
if (read_buffer.size() == source_buffer.size()) {
|
||||
EXPECT_EQ(0, memcmp(&read_buffer[0u], &source_buffer[0u], read_buffer.size()));
|
||||
}
|
||||
|
||||
dm.stop();
|
||||
EXPECT_EQ(0, dm.get_download_count());
|
||||
nf->close();
|
||||
|
||||
utils::file::delete_file(fsi.source_path);
|
||||
|
||||
utils::file::delete_file(test_source);
|
||||
event_system::instance().stop();
|
||||
}
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
}
|
||||
|
||||
TEST(downloader_manager, check_no_overflow_on_read_greater_than_file_size) {
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./chunk_data");
|
||||
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
|
||||
event_capture ec({}, {
|
||||
"download_begin",
|
||||
"download_end",
|
||||
"download_timeout",
|
||||
});
|
||||
const auto test_source = get_source_file_name();
|
||||
utils::file::delete_file(test_source);
|
||||
|
||||
const auto chunk_size = utils::encryption::encrypting_reader::get_data_chunk_size();
|
||||
const auto file_size = (chunk_size * 5u);
|
||||
auto nf = create_random_file(test_source, file_size);
|
||||
EXPECT_NE(nf, nullptr);
|
||||
if (nf) {
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
std::size_t bytes_read{};
|
||||
auto ret = nf->read_bytes(&data[0u], data.size(), offset, bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/test_chunk";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
fsi.source_path = test_source + "0";
|
||||
fsi.size = file_size;
|
||||
download_manager dm(config, api_reader, true);
|
||||
mock_open_file_table oft(&dm, &fsi);
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(1ull));
|
||||
dm.start(&oft);
|
||||
|
||||
std::vector<char> data;
|
||||
EXPECT_EQ(api_error::success, dm.read_bytes(1, fsi, file_size * 2, file_size, data));
|
||||
EXPECT_EQ(0, data.size());
|
||||
|
||||
dm.stop();
|
||||
EXPECT_EQ(0, dm.get_download_count());
|
||||
nf->close();
|
||||
|
||||
utils::file::delete_file(fsi.source_path);
|
||||
|
||||
utils::file::delete_file(test_source);
|
||||
event_system::instance().stop();
|
||||
}
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
}
|
||||
|
||||
TEST(downloader_manager, check_read_size_greater_than_file_size) {
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./chunk_data");
|
||||
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
|
||||
event_capture ec(
|
||||
{
|
||||
"download_begin",
|
||||
"download_end",
|
||||
"download_progress",
|
||||
},
|
||||
{"download_timeout"});
|
||||
const auto test_source = get_source_file_name();
|
||||
utils::file::delete_file(test_source);
|
||||
|
||||
const auto chunk_size = utils::encryption::encrypting_reader::get_data_chunk_size();
|
||||
const auto file_size = (chunk_size * 5u);
|
||||
auto nf = create_random_file(test_source, file_size);
|
||||
EXPECT_NE(nf, nullptr);
|
||||
if (nf) {
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
std::size_t bytes_read{};
|
||||
auto ret = nf->read_bytes(&data[0u], data.size(), offset, bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/test_chunk";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
fsi.source_path = test_source + "0";
|
||||
fsi.size = file_size;
|
||||
|
||||
download_manager dm(config, api_reader, true);
|
||||
mock_open_file_table oft(&dm, &fsi);
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(1ull));
|
||||
dm.start(&oft);
|
||||
|
||||
std::vector<char> data;
|
||||
EXPECT_EQ(api_error::success, dm.read_bytes(1, fsi, file_size * 2, 0, data));
|
||||
EXPECT_EQ(file_size, data.size());
|
||||
|
||||
dm.stop();
|
||||
EXPECT_EQ(0, dm.get_download_count());
|
||||
nf->close();
|
||||
|
||||
utils::file::delete_file(fsi.source_path);
|
||||
|
||||
utils::file::delete_file(test_source);
|
||||
event_system::instance().stop();
|
||||
}
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
}
|
||||
|
||||
TEST(downloader_manager, download_file) {
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./chunk_data");
|
||||
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
|
||||
event_capture ec(
|
||||
{
|
||||
"download_begin",
|
||||
"download_end",
|
||||
"download_progress",
|
||||
},
|
||||
{"download_timeout"});
|
||||
const auto test_source = get_source_file_name();
|
||||
utils::file::delete_file(test_source);
|
||||
|
||||
const auto chunk_size = utils::encryption::encrypting_reader::get_data_chunk_size();
|
||||
const auto file_size = (chunk_size * 5u + 8u);
|
||||
const auto test_dest = get_source_file_name();
|
||||
utils::file::delete_file(test_dest);
|
||||
|
||||
auto nf = create_random_file(test_source, file_size);
|
||||
EXPECT_NE(nf, nullptr);
|
||||
if (nf) {
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
std::size_t bytes_read{};
|
||||
auto ret = nf->read_bytes(&data[0u], data.size(), offset, bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/test_chunk";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
fsi.source_path = test_dest;
|
||||
fsi.size = file_size;
|
||||
|
||||
download_manager dm(config, api_reader, true);
|
||||
mock_open_file_table oft(&dm, &fsi);
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(1ull));
|
||||
dm.start(&oft);
|
||||
|
||||
EXPECT_EQ(api_error::success, dm.download_file(1, fsi));
|
||||
|
||||
std::uint64_t source_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(test_source, source_size));
|
||||
std::uint64_t current_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(fsi.source_path, current_size));
|
||||
EXPECT_EQ(source_size, current_size);
|
||||
|
||||
EXPECT_STRCASEEQ(utils::file::generate_sha256(test_source).c_str(),
|
||||
utils::file::generate_sha256(fsi.source_path).c_str());
|
||||
|
||||
dm.stop();
|
||||
EXPECT_EQ(0, dm.get_download_count());
|
||||
nf->close();
|
||||
|
||||
utils::file::delete_file(fsi.source_path);
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_source);
|
||||
event_system::instance().stop();
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
}
|
||||
|
||||
TEST(downloader_manager, download_timeout) {
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./chunk_data");
|
||||
config.set_chunk_downloader_timeout_secs(5);
|
||||
config.set_enable_chunk_downloader_timeout(true);
|
||||
|
||||
event_capture ec({
|
||||
"filesystem_item_closed",
|
||||
"download_timeout",
|
||||
"download_begin",
|
||||
"download_end",
|
||||
});
|
||||
const auto test_source = get_source_file_name();
|
||||
utils::file::delete_file(test_source);
|
||||
|
||||
const auto chunk_size = utils::encryption::encrypting_reader::get_data_chunk_size();
|
||||
const auto file_size = (chunk_size * 5u) + 2;
|
||||
const auto test_dest = get_source_file_name();
|
||||
utils::file::delete_file(test_dest);
|
||||
|
||||
auto nf = create_random_file(test_source, file_size);
|
||||
EXPECT_NE(nf, nullptr);
|
||||
if (nf) {
|
||||
filesystem_item *pfsi = nullptr;
|
||||
auto sent = false;
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &,
|
||||
const std::uint64_t &, std::vector<char> &,
|
||||
const bool &stop_requested) -> api_error {
|
||||
if (not sent) {
|
||||
sent = true;
|
||||
event_system::instance().raise<filesystem_item_closed>(pfsi->api_path, pfsi->source_path,
|
||||
false, false);
|
||||
}
|
||||
while (not stop_requested) {
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
return api_error::download_failed;
|
||||
};
|
||||
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/test_chunk";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
fsi.source_path = test_dest;
|
||||
fsi.size = file_size;
|
||||
pfsi = &fsi;
|
||||
|
||||
download_manager dm(config, api_reader, true);
|
||||
mock_open_file_table oft;
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(0ull));
|
||||
dm.start(&oft);
|
||||
|
||||
EXPECT_EQ(api_error::download_timeout, dm.download_file(1, fsi));
|
||||
|
||||
dm.stop();
|
||||
EXPECT_EQ(0, dm.get_download_count());
|
||||
nf->close();
|
||||
|
||||
utils::file::delete_file(fsi.source_path);
|
||||
|
||||
utils::file::delete_file(test_source);
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
}
|
||||
|
||||
TEST(downloader_manager, download_pause_resume) {
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./chunk_data");
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
|
||||
event_capture ec(
|
||||
{
|
||||
"download_begin",
|
||||
"download_end",
|
||||
"download_progress",
|
||||
"download_paused",
|
||||
"download_resumed",
|
||||
},
|
||||
{"download_timeout"});
|
||||
const auto test_source = get_source_file_name();
|
||||
utils::file::delete_file(test_source);
|
||||
|
||||
const auto chunk_size = utils::encryption::encrypting_reader::get_data_chunk_size();
|
||||
const auto file_size = (chunk_size * 50u);
|
||||
const auto test_dest = get_source_file_name();
|
||||
utils::file::delete_file(test_dest);
|
||||
|
||||
auto nf = create_random_file(test_source, file_size);
|
||||
EXPECT_NE(nf, nullptr);
|
||||
if (nf) {
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
std::size_t bytes_read{};
|
||||
auto ret = nf->read_bytes(&data[0u], data.size(), offset, bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/test_chunk";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
fsi.source_path = test_dest;
|
||||
fsi.size = file_size;
|
||||
|
||||
download_manager dm(config, api_reader, true);
|
||||
mock_open_file_table oft(&dm, &fsi);
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(1ull));
|
||||
dm.start(&oft);
|
||||
|
||||
std::thread th([&]() { EXPECT_EQ(api_error::success, dm.download_file(1, fsi)); });
|
||||
EXPECT_TRUE(ec.wait_for_event("download_begin"));
|
||||
EXPECT_TRUE(dm.pause_download(fsi.api_path));
|
||||
|
||||
dm.rename_download(fsi.api_path, fsi.api_path + "_cow");
|
||||
|
||||
fsi.api_path += "_cow";
|
||||
dm.resume_download(fsi.api_path);
|
||||
th.join();
|
||||
|
||||
std::uint64_t source_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(test_source, source_size));
|
||||
std::uint64_t current_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(fsi.source_path, current_size));
|
||||
EXPECT_EQ(source_size, current_size);
|
||||
|
||||
EXPECT_STRCASEEQ(utils::file::generate_sha256(test_source).c_str(),
|
||||
utils::file::generate_sha256(fsi.source_path).c_str());
|
||||
|
||||
dm.stop();
|
||||
EXPECT_EQ(0, dm.get_download_count());
|
||||
nf->close();
|
||||
|
||||
utils::file::delete_file(fsi.source_path);
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_source);
|
||||
event_system::instance().stop();
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
}
|
||||
|
||||
TEST(downloader_manager, store_and_resume_incomplete_download_after_write) {
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./chunk_data");
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
|
||||
const auto test_source = get_source_file_name();
|
||||
utils::file::delete_file(test_source);
|
||||
|
||||
const auto chunk_size = utils::encryption::encrypting_reader::get_data_chunk_size();
|
||||
const auto file_size = (chunk_size * 10u);
|
||||
const auto test_dest = utils::path::absolute("./test_chunk_dest");
|
||||
utils::file::delete_file(test_dest);
|
||||
|
||||
auto nf = create_random_file(test_source, file_size);
|
||||
EXPECT_NE(nf, nullptr);
|
||||
if (nf) {
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
std::size_t bytes_read{};
|
||||
auto ret = nf->read_bytes(&data[0u], data.size(), offset, bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
std::this_thread::sleep_for(2s);
|
||||
return ret;
|
||||
};
|
||||
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/test_chunk";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
fsi.source_path = test_dest;
|
||||
fsi.size = file_size;
|
||||
|
||||
download_manager dm(config, api_reader, true);
|
||||
|
||||
mock_open_file_table oft(&dm, &fsi);
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(0ull));
|
||||
filesystem_item fsi2{};
|
||||
EXPECT_CALL(oft, force_schedule_upload(_)).WillOnce(DoAll(SaveArg<0>(&fsi2), Return()));
|
||||
EXPECT_CALL(oft, open(_, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(1u), Return(api_error::success)));
|
||||
EXPECT_CALL(oft, close(1u)).WillOnce(Return());
|
||||
|
||||
{
|
||||
event_capture ec({
|
||||
"download_begin",
|
||||
"download_end",
|
||||
"download_progress",
|
||||
"download_stored",
|
||||
});
|
||||
|
||||
dm.start(&oft);
|
||||
|
||||
std::size_t bytes_written{};
|
||||
EXPECT_EQ(api_error::success,
|
||||
dm.write_bytes(1, fsi, chunk_size - 2u, {'a', 'a', 'a', 'a'}, bytes_written));
|
||||
|
||||
dm.stop();
|
||||
ec.wait_for_event("download_stored");
|
||||
}
|
||||
{
|
||||
event_capture ec({
|
||||
"download_begin",
|
||||
"download_end",
|
||||
"download_progress",
|
||||
"download_restored",
|
||||
});
|
||||
|
||||
dm.start(&oft);
|
||||
|
||||
ec.wait_for_event("download_restored");
|
||||
ec.wait_for_event("download_end");
|
||||
|
||||
dm.stop();
|
||||
}
|
||||
|
||||
nf->close();
|
||||
|
||||
utils::file::delete_file(fsi.source_path);
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_source);
|
||||
event_system::instance().stop();
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./chunk_data"));
|
||||
}
|
||||
} // namespace repertory
|
221
tests/download_test.cpp
Normal file
221
tests/download_test.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "app_config.hpp"
|
||||
#include "download/download.hpp"
|
||||
#include "mocks/mock_open_file_table.hpp"
|
||||
#include "test_common.hpp"
|
||||
#include "utils/event_capture.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
static const std::size_t READ_SIZE = 1024u * 1024u;
|
||||
|
||||
static std::string get_source_file_name() { return generate_test_file_name("./", "download"); }
|
||||
|
||||
static void write_and_test(download &d, const std::vector<char> &buffer, const bool &to_end) {
|
||||
if (to_end) {
|
||||
std::size_t bytes_written{};
|
||||
EXPECT_EQ(api_error::success, d.write_bytes(0u, 20u * READ_SIZE, buffer, bytes_written,
|
||||
[](std::uint64_t, std::uint64_t, bool) {}));
|
||||
|
||||
std::vector<char> data;
|
||||
EXPECT_EQ(api_error::success, d.read_bytes(0u, buffer.size(), 20u * READ_SIZE, data));
|
||||
EXPECT_EQ(std::vector<char>(buffer), data);
|
||||
} else {
|
||||
std::size_t bytes_written{};
|
||||
EXPECT_EQ(api_error::success,
|
||||
d.write_bytes(0u, READ_SIZE + READ_SIZE - 2u, buffer, bytes_written,
|
||||
[](std::uint64_t, std::uint64_t, bool) {}));
|
||||
|
||||
std::vector<char> data;
|
||||
EXPECT_EQ(api_error::success, d.read_bytes(0u, 4u, READ_SIZE + READ_SIZE - 2u, data));
|
||||
EXPECT_EQ(std::vector<char>(buffer), data);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(download, write_non_cached_file) {
|
||||
mock_open_file_table oft;
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./download_data"));
|
||||
|
||||
const auto source_file_path = get_source_file_name();
|
||||
const auto source_file_size = 20u * READ_SIZE;
|
||||
utils::file::delete_file(source_file_path);
|
||||
auto source_file = create_random_file(source_file_path, source_file_size);
|
||||
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(0ull));
|
||||
filesystem_item fsi2{};
|
||||
EXPECT_CALL(oft, force_schedule_upload(_))
|
||||
.Times(2)
|
||||
.WillRepeatedly(DoAll(SaveArg<0>(&fsi2), Return()));
|
||||
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
const auto chunk = (offset / READ_SIZE);
|
||||
if (chunk < 1u || (chunk > 2u)) {
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
|
||||
std::size_t bytes_read{};
|
||||
auto ret = source_file->read_bytes(&data[0u], data.size(), offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
if (ret != api_error::success) {
|
||||
std::cout << utils::get_last_error_code() << std::endl;
|
||||
}
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/Test.dat";
|
||||
fsi.size = source_file_size;
|
||||
fsi.api_parent = "/";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
|
||||
{
|
||||
event_capture ec({"download_begin", "download_end", "download_progress"});
|
||||
app_config config(provider_type::sia, "./download_data");
|
||||
|
||||
{
|
||||
download d(config, fsi, api_reader, READ_SIZE, oft);
|
||||
|
||||
write_and_test(d, {'a', 'a', 'a', 'a'}, false);
|
||||
ec.wait_for_event("download_end");
|
||||
|
||||
const auto new_source_file_path = d.get_source_path();
|
||||
EXPECT_TRUE(utils::file::is_file(new_source_file_path));
|
||||
EXPECT_STRNE(source_file_path.c_str(), new_source_file_path.c_str());
|
||||
EXPECT_STREQ(new_source_file_path.c_str(), fsi2.source_path.c_str());
|
||||
EXPECT_STREQ(fsi.api_path.c_str(), fsi2.api_path.c_str());
|
||||
EXPECT_FALSE(fsi2.source_path_changed);
|
||||
EXPECT_FALSE(fsi2.changed);
|
||||
write_and_test(d, {'b', 'b', 'b', 'b'}, false);
|
||||
|
||||
filesystem_item fsi3{};
|
||||
boost::dynamic_bitset<> read_state, write_state;
|
||||
std::size_t chunk_size{}, last_chunk_size{};
|
||||
d.get_state_information(fsi3, chunk_size, last_chunk_size, read_state, write_state);
|
||||
EXPECT_STREQ(fsi2.source_path.c_str(), fsi3.source_path.c_str());
|
||||
EXPECT_FALSE(write_state[0]);
|
||||
EXPECT_TRUE(write_state[1]);
|
||||
EXPECT_TRUE(write_state[2]);
|
||||
for (std::size_t i = 3u; i < write_state.size(); i++) {
|
||||
EXPECT_FALSE(write_state[i]);
|
||||
}
|
||||
EXPECT_TRUE(read_state.all());
|
||||
}
|
||||
}
|
||||
source_file->close();
|
||||
|
||||
event_system::instance().stop();
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./download_data"));
|
||||
utils::file::delete_file(source_file_path);
|
||||
}
|
||||
|
||||
TEST(Download, write_non_cached_file_and_grow_size) {
|
||||
mock_open_file_table oft;
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./download_data"));
|
||||
|
||||
const auto source_file_path = get_source_file_name();
|
||||
const auto source_file_size = 20u * READ_SIZE;
|
||||
utils::file::delete_file(source_file_path);
|
||||
auto sourceFile = create_random_file(source_file_path, source_file_size);
|
||||
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(0ull));
|
||||
filesystem_item fsi2{};
|
||||
EXPECT_CALL(oft, force_schedule_upload(_)).WillOnce(DoAll(SaveArg<0>(&fsi2), Return()));
|
||||
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
const auto chunk = (offset / READ_SIZE);
|
||||
if (chunk < 20u) {
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
|
||||
std::size_t bytes_read{};
|
||||
auto ret = sourceFile->read_bytes(&data[0u], data.size(), offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
if (ret != api_error::success) {
|
||||
std::cout << utils::get_last_error_code() << std::endl;
|
||||
}
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/Test.dat";
|
||||
fsi.size = source_file_size;
|
||||
fsi.api_parent = "/";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
|
||||
{
|
||||
event_capture ec({"download_begin", "download_end", "download_progress"});
|
||||
app_config config(provider_type::sia, "./download_data");
|
||||
{
|
||||
download d(config, fsi, api_reader, READ_SIZE, oft);
|
||||
|
||||
write_and_test(d, {'a', 'a', 'a', 'a'}, true);
|
||||
ec.wait_for_event("download_end");
|
||||
|
||||
const auto new_source_file_path = d.get_source_path();
|
||||
EXPECT_TRUE(utils::file::is_file(new_source_file_path));
|
||||
EXPECT_STRNE(source_file_path.c_str(), new_source_file_path.c_str());
|
||||
EXPECT_STREQ(new_source_file_path.c_str(), fsi2.source_path.c_str());
|
||||
EXPECT_STREQ(fsi.api_path.c_str(), fsi2.api_path.c_str());
|
||||
EXPECT_FALSE(fsi2.source_path_changed);
|
||||
EXPECT_FALSE(fsi2.changed);
|
||||
EXPECT_EQ(source_file_size + 4u, fsi2.size);
|
||||
|
||||
filesystem_item fsi3{};
|
||||
boost::dynamic_bitset<> read_state, write_state;
|
||||
std::size_t chunk_size{}, last_chunk_size{};
|
||||
d.get_state_information(fsi3, chunk_size, last_chunk_size, read_state, write_state);
|
||||
EXPECT_STREQ(fsi2.source_path.c_str(), fsi3.source_path.c_str());
|
||||
EXPECT_EQ(21u, write_state.size());
|
||||
EXPECT_EQ(write_state.size(), read_state.size());
|
||||
EXPECT_EQ(source_file_size + 4u, fsi3.size);
|
||||
|
||||
for (std::size_t i = 0u; i < write_state.size() - 1u; i++) {
|
||||
EXPECT_FALSE(write_state[i]);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(write_state[20u]);
|
||||
EXPECT_TRUE(read_state.all());
|
||||
}
|
||||
}
|
||||
sourceFile->close();
|
||||
|
||||
event_system::instance().stop();
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./download_data"));
|
||||
utils::file::delete_file(source_file_path);
|
||||
}
|
||||
} // namespace repertory
|
429
tests/downloaders_test.cpp
Normal file
429
tests/downloaders_test.cpp
Normal file
@ -0,0 +1,429 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "app_config.hpp"
|
||||
#include "download/direct_download.hpp"
|
||||
#include "download/download.hpp"
|
||||
#include "download/ring_download.hpp"
|
||||
#include "mocks/mock_open_file_table.hpp"
|
||||
#include "test_common.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
static const std::size_t READ_SIZE = 1024u * 1024u;
|
||||
static const std::int32_t DOWNLOADER_COUNT = 3;
|
||||
|
||||
static std::string get_source_file_name() { return generate_test_file_name("./", "downloaders"); }
|
||||
|
||||
static std::shared_ptr<i_download> create_download(const std::int32_t &index, app_config &config,
|
||||
filesystem_item &fsi,
|
||||
api_reader_callback &api_reader,
|
||||
i_open_file_table &oft) {
|
||||
return (index == 0) ? std::dynamic_pointer_cast<i_download>(std::make_shared<ring_download>(
|
||||
config, fsi, api_reader, 0, READ_SIZE, 6u * READ_SIZE))
|
||||
: (index == 1) ? std::dynamic_pointer_cast<i_download>(
|
||||
std::make_shared<direct_download>(config, fsi, api_reader, 0))
|
||||
: std::dynamic_pointer_cast<i_download>(std::make_shared<download>(
|
||||
config, fsi, api_reader, 6u * READ_SIZE, oft));
|
||||
}
|
||||
|
||||
static void run_full_file_test(const std::size_t &max_read_size,
|
||||
const std::size_t &source_file_size) {
|
||||
const auto source_file_path = get_source_file_name();
|
||||
{
|
||||
console_consumer c;
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./downloaders_data"));
|
||||
app_config config(provider_type::sia, "./downloaders_data");
|
||||
|
||||
utils::file::delete_file(source_file_path);
|
||||
|
||||
auto source_file = create_random_file(source_file_path, source_file_size);
|
||||
EXPECT_NE(source_file, nullptr);
|
||||
if (source_file) {
|
||||
api_reader_callback api_reader =
|
||||
[&source_file](const std::string &, const std::size_t &size, const std::uint64_t &offset,
|
||||
std::vector<char> &data, const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
std::size_t bytes_read{};
|
||||
auto ret = source_file->read_bytes(&data[0u], data.size(), offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
if (ret != api_error::success) {
|
||||
std::cout << utils::get_last_error_code() << std::endl;
|
||||
}
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
event_system::instance().start();
|
||||
for (auto i = 0; i < DOWNLOADER_COUNT; i++) {
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/Test.dat";
|
||||
fsi.size = source_file_size;
|
||||
fsi.api_parent = "/";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
|
||||
mock_open_file_table oft;
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(1ull));
|
||||
auto download = create_download(i, config, fsi, api_reader, oft);
|
||||
|
||||
auto size_remain = source_file_size;
|
||||
auto result_code = api_error::success;
|
||||
auto offset = 0ull;
|
||||
auto total_read = 0ull;
|
||||
while ((result_code == api_error::success) && (size_remain > 0)) {
|
||||
const auto read_size = std::min(max_read_size, static_cast<std::size_t>(size_remain));
|
||||
std::vector<char> data;
|
||||
if ((result_code = download->read_bytes(0u, read_size, offset, data)) ==
|
||||
api_error::success) {
|
||||
total_read += data.size();
|
||||
EXPECT_EQ(read_size, data.size());
|
||||
if (data.size() == read_size) {
|
||||
std::size_t bytes_read = 0;
|
||||
std::vector<char> data2(data.size());
|
||||
result_code = source_file->read_bytes(&data2[0u], data2.size(), offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(data.size(), data2.size());
|
||||
EXPECT_EQ(api_error::success, result_code);
|
||||
const auto comp = memcmp(&data[0u], &data2[0u], data.size());
|
||||
EXPECT_EQ(0, comp);
|
||||
}
|
||||
|
||||
size_remain -= read_size;
|
||||
offset += read_size;
|
||||
}
|
||||
EXPECT_EQ(api_error::success, result_code);
|
||||
}
|
||||
EXPECT_EQ(source_file_size, total_read);
|
||||
download.reset();
|
||||
}
|
||||
source_file->close();
|
||||
}
|
||||
event_system::instance().stop();
|
||||
}
|
||||
|
||||
utils::file::delete_file(source_file_path);
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./downloaders_data"));
|
||||
}
|
||||
|
||||
static void run_read_past_full_buffer_test() {
|
||||
const auto max_read_size = READ_SIZE;
|
||||
const auto source_file_path = get_source_file_name();
|
||||
const auto source_file_size = 20u * READ_SIZE;
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./downloaders_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./downloaders_data");
|
||||
|
||||
utils::file::delete_file(source_file_path);
|
||||
|
||||
console_consumer c;
|
||||
auto source_file = create_random_file(source_file_path, source_file_size);
|
||||
EXPECT_NE(source_file, nullptr);
|
||||
|
||||
if (source_file) {
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
std::size_t bytes_read{};
|
||||
const auto ret = source_file->read_bytes(&data[0u], data.size(), offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
event_system::instance().start();
|
||||
for (auto i = 0; i < DOWNLOADER_COUNT; i++) {
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/Test.dat";
|
||||
fsi.size = source_file_size;
|
||||
fsi.api_parent = "/";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
|
||||
mock_open_file_table oft;
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(1ull));
|
||||
auto download = create_download(i, config, fsi, api_reader, oft);
|
||||
|
||||
auto size_remain = source_file_size;
|
||||
auto result_code = api_error::success;
|
||||
auto offset = 0ull;
|
||||
while ((result_code == api_error::success) && (size_remain > 0)) {
|
||||
const auto read_size = std::min(max_read_size, static_cast<std::size_t>(size_remain));
|
||||
std::vector<char> data;
|
||||
if ((result_code = download->read_bytes(0u, read_size, offset, data)) ==
|
||||
api_error::success) {
|
||||
EXPECT_EQ(read_size, data.size());
|
||||
if (data.size() == read_size) {
|
||||
std::size_t bytes_read = 0;
|
||||
std::vector<char> data2(data.size());
|
||||
result_code = source_file->read_bytes(&data2[0u], data2.size(), offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, result_code);
|
||||
EXPECT_EQ(data.size(), bytes_read);
|
||||
const auto comp = memcmp(&data[0u], &data2[0u], data.size());
|
||||
EXPECT_EQ(0, comp);
|
||||
}
|
||||
|
||||
if (size_remain == source_file_size) {
|
||||
size_remain -= (read_size + (6ull * READ_SIZE));
|
||||
offset += (read_size + (6ull * READ_SIZE));
|
||||
} else {
|
||||
size_remain -= read_size;
|
||||
offset += read_size;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, result_code);
|
||||
}
|
||||
download.reset();
|
||||
}
|
||||
source_file->close();
|
||||
utils::file::delete_file(source_file_path);
|
||||
}
|
||||
event_system::instance().stop();
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./downloaders_data"));
|
||||
}
|
||||
|
||||
static void run_read_with_seek_behind() {
|
||||
const auto max_read_size = READ_SIZE;
|
||||
const auto source_file_path = get_source_file_name();
|
||||
const auto source_file_size = 20u * READ_SIZE;
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./downloaders_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./downloaders_data");
|
||||
|
||||
utils::file::delete_file(source_file_path);
|
||||
|
||||
console_consumer c;
|
||||
auto source_file = create_random_file(source_file_path, source_file_size);
|
||||
EXPECT_NE(source_file, nullptr);
|
||||
|
||||
if (source_file) {
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
std::size_t bytes_read{};
|
||||
auto ret = source_file->read_bytes(&data[0u], data.size(), offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
event_system::instance().start();
|
||||
|
||||
for (auto i = 0; i < DOWNLOADER_COUNT; i++) {
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/Test.dat";
|
||||
fsi.size = source_file_size;
|
||||
fsi.api_parent = "/";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
|
||||
mock_open_file_table oft;
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(1ull));
|
||||
auto download = create_download(i, config, fsi, api_reader, oft);
|
||||
|
||||
auto size_remain = source_file_size;
|
||||
auto result_code = api_error::success;
|
||||
auto offset = 0ull;
|
||||
auto read_count = 0;
|
||||
while ((result_code == api_error::success) && (size_remain > 0)) {
|
||||
const auto read_size = std::min(max_read_size, static_cast<std::size_t>(size_remain));
|
||||
std::vector<char> data;
|
||||
if ((result_code = download->read_bytes(0u, read_size, offset, data)) ==
|
||||
api_error::success) {
|
||||
EXPECT_EQ(read_size, data.size());
|
||||
if (data.size() == read_size) {
|
||||
std::size_t bytes_read = 0;
|
||||
std::vector<char> data2(data.size());
|
||||
result_code = source_file->read_bytes(&data2[0u], data2.size(), offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, result_code);
|
||||
EXPECT_EQ(data.size(), bytes_read);
|
||||
const auto comp = memcmp(&data[0u], &data2[0u], data.size());
|
||||
EXPECT_EQ(0, comp);
|
||||
}
|
||||
|
||||
if (++read_count == 3) {
|
||||
size_remain += (read_size * 2);
|
||||
offset -= (read_size * 2);
|
||||
} else {
|
||||
size_remain -= read_size;
|
||||
offset += read_size;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(api_error::success, result_code);
|
||||
}
|
||||
download.reset();
|
||||
}
|
||||
source_file->close();
|
||||
utils::file::delete_file(source_file_path);
|
||||
}
|
||||
event_system::instance().stop();
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./downloaders_data"));
|
||||
}
|
||||
|
||||
static void run_seek_begin_to_end_to_begin() {
|
||||
const auto max_read_size = READ_SIZE;
|
||||
const auto source_file_path = get_source_file_name();
|
||||
const auto source_file_size = 20u * READ_SIZE;
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./downloaders_data"));
|
||||
{
|
||||
app_config config(provider_type::sia, "./downloaders_data");
|
||||
|
||||
utils::file::delete_file(source_file_path);
|
||||
|
||||
console_consumer c;
|
||||
auto source_file = create_random_file(source_file_path, source_file_size);
|
||||
EXPECT_NE(source_file, nullptr);
|
||||
|
||||
if (source_file) {
|
||||
|
||||
api_reader_callback api_reader = [&](const std::string &, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &) -> api_error {
|
||||
data.resize(size);
|
||||
std::size_t bytes_read{};
|
||||
auto ret = source_file->read_bytes(&data[0u], data.size(), offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, ret);
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
};
|
||||
|
||||
event_system::instance().start();
|
||||
|
||||
for (auto i = 0; i < DOWNLOADER_COUNT; i++) {
|
||||
filesystem_item fsi{};
|
||||
fsi.api_path = "/Test.dat";
|
||||
fsi.size = source_file_size;
|
||||
fsi.api_parent = "/";
|
||||
fsi.directory = false;
|
||||
fsi.lock = std::make_shared<std::recursive_mutex>();
|
||||
|
||||
mock_open_file_table oft;
|
||||
EXPECT_CALL(oft, get_open_count(_)).WillRepeatedly(Return(1ull));
|
||||
auto download = create_download(i, config, fsi, api_reader, oft);
|
||||
|
||||
auto size_remain = source_file_size;
|
||||
auto result_code = api_error::success;
|
||||
auto offset = 0ull;
|
||||
auto readCount = 0;
|
||||
while ((result_code == api_error::success) && (readCount < 4)) {
|
||||
const auto read_size = std::min(max_read_size, static_cast<std::size_t>(size_remain));
|
||||
std::vector<char> data;
|
||||
if ((result_code = download->read_bytes(0u, read_size, offset, data)) ==
|
||||
api_error::success) {
|
||||
EXPECT_EQ(read_size, data.size());
|
||||
if (data.size() == read_size) {
|
||||
std::size_t bytes_read = 0;
|
||||
std::vector<char> data2(data.size());
|
||||
result_code = source_file->read_bytes(&data2[0u], data2.size(), offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(api_error::success, result_code);
|
||||
EXPECT_EQ(data.size(), bytes_read);
|
||||
const auto comp = memcmp(&data[0u], &data2[0u], data.size());
|
||||
EXPECT_EQ(0, comp);
|
||||
if (comp) {
|
||||
std::cout << "mismatch-" << read_size << ':' << offset << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
++readCount;
|
||||
if (readCount == 1) {
|
||||
size_remain = read_size;
|
||||
offset = source_file_size - read_size;
|
||||
} else if (readCount == 2) {
|
||||
std::this_thread::sleep_for(10ms);
|
||||
size_remain = source_file_size;
|
||||
offset = 0ull;
|
||||
} else {
|
||||
size_remain -= read_size;
|
||||
offset += read_size;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(api_error::success, result_code);
|
||||
}
|
||||
download.reset();
|
||||
}
|
||||
source_file->close();
|
||||
utils::file::delete_file(source_file_path);
|
||||
}
|
||||
event_system::instance().stop();
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(utils::path::absolute("./downloaders_data"));
|
||||
}
|
||||
|
||||
TEST(downloaders, read_full_file) {
|
||||
const auto max_read_size = READ_SIZE;
|
||||
const auto source_file_size = 20u * READ_SIZE;
|
||||
run_full_file_test(max_read_size, source_file_size);
|
||||
}
|
||||
|
||||
TEST(downloaders, read_full_file_with_overlapping_chunks) {
|
||||
const auto max_read_size = READ_SIZE + (READ_SIZE / 2);
|
||||
const auto source_file_size = 20u * READ_SIZE;
|
||||
run_full_file_test(max_read_size, source_file_size);
|
||||
}
|
||||
|
||||
TEST(downloaders, read_full_file_with_non_matching_chunk_size) {
|
||||
const auto max_read_size = READ_SIZE;
|
||||
const auto source_file_size = (20u * READ_SIZE) + 252u;
|
||||
run_full_file_test(max_read_size, source_file_size);
|
||||
}
|
||||
|
||||
TEST(downloaders, read_full_file_with_partial_reads) {
|
||||
const auto max_read_size = 32u * 1024u;
|
||||
const auto source_file_size = 20u * READ_SIZE;
|
||||
run_full_file_test(max_read_size, source_file_size);
|
||||
}
|
||||
|
||||
TEST(downloaders, read_full_file_with_partial_overlapping_reads) {
|
||||
const auto max_read_size = (READ_SIZE / 2) + 20u;
|
||||
const auto source_file_size = 20u * READ_SIZE;
|
||||
run_full_file_test(max_read_size, source_file_size);
|
||||
}
|
||||
|
||||
TEST(downloaders, read_past_full_buffer) { run_read_past_full_buffer_test(); }
|
||||
|
||||
TEST(downloaders, read_with_seek_behind) { run_read_with_seek_behind(); }
|
||||
|
||||
TEST(downloaders, seek_begin_to_end_to_begin) { run_seek_begin_to_end_to_begin(); }
|
||||
} // namespace repertory
|
236
tests/encrypting_reader_test.cpp
Normal file
236
tests/encrypting_reader_test.cpp
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "utils/encrypting_reader.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
static std::string get_source_file_name() {
|
||||
return generate_test_file_name("./", "encrypting_reader");
|
||||
}
|
||||
|
||||
TEST(encrypting_reader, get_encrypted_file_name) {
|
||||
const auto source_file_name = get_source_file_name();
|
||||
utils::file::delete_file(source_file_name);
|
||||
|
||||
const auto token = std::string("moose");
|
||||
auto source_file = create_random_file(source_file_name, 1024ul);
|
||||
EXPECT_TRUE(source_file != nullptr);
|
||||
if (source_file) {
|
||||
bool stop_requested = false;
|
||||
utils::encryption::encrypting_reader reader("test.dat", source_file_name, stop_requested,
|
||||
token);
|
||||
|
||||
auto file_name = reader.get_encrypted_file_name();
|
||||
std::cout << file_name << std::endl;
|
||||
|
||||
EXPECT_EQ(api_error::success, utils::encryption::decrypt_file_name(token, file_name));
|
||||
std::cout << file_name << std::endl;
|
||||
EXPECT_STREQ("test.dat", file_name.c_str());
|
||||
|
||||
source_file->close();
|
||||
}
|
||||
utils::file::delete_file(source_file_name);
|
||||
}
|
||||
|
||||
TEST(encrypting_reader, file_data) {
|
||||
const auto source_file_name = get_source_file_name();
|
||||
utils::file::delete_file(source_file_name);
|
||||
|
||||
const auto token = std::string("moose");
|
||||
auto source_file = create_random_file(
|
||||
source_file_name, 8u * utils::encryption::encrypting_reader::get_data_chunk_size());
|
||||
EXPECT_TRUE(source_file != nullptr);
|
||||
if (source_file) {
|
||||
bool stop_requested = false;
|
||||
utils::encryption::encrypting_reader reader("test.dat", source_file_name, stop_requested,
|
||||
token);
|
||||
|
||||
for (std::uint8_t i = 0u; i < 8u; i++) {
|
||||
std::vector<char> buffer(utils::encryption::encrypting_reader::get_encrypted_chunk_size());
|
||||
for (std::uint8_t j = 0u; j < 2u; j++) {
|
||||
utils::encryption::encrypting_reader::reader_function(&buffer[(buffer.size() / 2u) * j],
|
||||
buffer.size() / 2u, 1u, &reader);
|
||||
}
|
||||
|
||||
std::vector<char> decrypted_data;
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(token, buffer, decrypted_data));
|
||||
|
||||
EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(), decrypted_data.size());
|
||||
|
||||
std::size_t bytes_read{};
|
||||
std::vector<char> file_data(decrypted_data.size());
|
||||
source_file->read_bytes(&file_data[0u], file_data.size(),
|
||||
utils::encryption::encrypting_reader::get_data_chunk_size() * i,
|
||||
bytes_read);
|
||||
EXPECT_EQ(0, std::memcmp(&file_data[0u], &decrypted_data[0u], file_data.size()));
|
||||
}
|
||||
|
||||
source_file->close();
|
||||
}
|
||||
utils::file::delete_file(source_file_name);
|
||||
}
|
||||
|
||||
TEST(encrypting_reader, file_data_in_multiple_chunks) {
|
||||
const auto source_file_name = get_source_file_name();
|
||||
utils::file::delete_file(source_file_name);
|
||||
|
||||
const auto token = std::string("moose");
|
||||
auto source_file = create_random_file(
|
||||
source_file_name, 8u * utils::encryption::encrypting_reader::get_data_chunk_size());
|
||||
EXPECT_TRUE(source_file != nullptr);
|
||||
if (source_file) {
|
||||
bool stop_requested = false;
|
||||
utils::encryption::encrypting_reader reader("test.dat", source_file_name, stop_requested,
|
||||
token);
|
||||
|
||||
for (std::uint8_t i = 0u; i < 8u; i += 2u) {
|
||||
std::vector<char> buffer(utils::encryption::encrypting_reader::get_encrypted_chunk_size() *
|
||||
2u);
|
||||
utils::encryption::encrypting_reader::reader_function(&buffer[0u], buffer.size(), 1u,
|
||||
&reader);
|
||||
|
||||
for (std::uint8_t j = 0u; j < 2u; j++) {
|
||||
std::vector<char> decrypted_data;
|
||||
const auto offset = (j * (buffer.size() / 2u));
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(
|
||||
token,
|
||||
std::vector<char>(buffer.begin() + offset,
|
||||
buffer.begin() + offset + (buffer.size() / 2u)),
|
||||
decrypted_data));
|
||||
|
||||
EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(),
|
||||
decrypted_data.size());
|
||||
|
||||
std::size_t bytes_read{};
|
||||
std::vector<char> file_data(decrypted_data.size());
|
||||
source_file->read_bytes(
|
||||
&file_data[0u], file_data.size(),
|
||||
(utils::encryption::encrypting_reader::get_data_chunk_size() * i) +
|
||||
(j * utils::encryption::encrypting_reader::get_data_chunk_size()),
|
||||
bytes_read);
|
||||
EXPECT_EQ(0, std::memcmp(&file_data[0u], &decrypted_data[0u], file_data.size()));
|
||||
}
|
||||
}
|
||||
|
||||
source_file->close();
|
||||
}
|
||||
utils::file::delete_file(source_file_name);
|
||||
}
|
||||
|
||||
TEST(encrypting_reader, file_data_as_stream) {
|
||||
const auto source_file_name = get_source_file_name();
|
||||
utils::file::delete_file(source_file_name);
|
||||
|
||||
const auto token = std::string("moose");
|
||||
auto source_file = create_random_file(
|
||||
source_file_name, 8u * utils::encryption::encrypting_reader::get_data_chunk_size());
|
||||
EXPECT_TRUE(source_file != nullptr);
|
||||
if (source_file) {
|
||||
bool stop_requested = false;
|
||||
utils::encryption::encrypting_reader reader("test.dat", source_file_name, stop_requested,
|
||||
token);
|
||||
auto io_stream = reader.create_iostream();
|
||||
EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
EXPECT_EQ(reader.get_total_size(), io_stream->tellg());
|
||||
EXPECT_FALSE(io_stream->seekg(0, std::ios_base::beg).fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
|
||||
for (std::uint8_t i = 0u; i < 8u; i++) {
|
||||
std::vector<char> buffer(utils::encryption::encrypting_reader::get_encrypted_chunk_size());
|
||||
EXPECT_FALSE(io_stream->seekg(i * buffer.size()).fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
for (std::uint8_t j = 0u; j < 2u; j++) {
|
||||
EXPECT_FALSE(io_stream->read(&buffer[(buffer.size() / 2u) * j], buffer.size() / 2u).fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
}
|
||||
|
||||
std::vector<char> decrypted_data;
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(token, buffer, decrypted_data));
|
||||
|
||||
EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(), decrypted_data.size());
|
||||
|
||||
std::size_t bytes_read{};
|
||||
std::vector<char> file_data(decrypted_data.size());
|
||||
source_file->read_bytes(&file_data[0u], file_data.size(),
|
||||
utils::encryption::encrypting_reader::get_data_chunk_size() * i,
|
||||
bytes_read);
|
||||
EXPECT_EQ(0, std::memcmp(&file_data[0u], &decrypted_data[0u], file_data.size()));
|
||||
}
|
||||
|
||||
source_file->close();
|
||||
}
|
||||
utils::file::delete_file(source_file_name);
|
||||
}
|
||||
|
||||
TEST(encrypting_reader, file_data_in_multiple_chunks_as_stream) {
|
||||
const auto source_file_name = get_source_file_name();
|
||||
utils::file::delete_file(source_file_name);
|
||||
|
||||
const auto token = std::string("moose");
|
||||
auto source_file = create_random_file(
|
||||
source_file_name, 8u * utils::encryption::encrypting_reader::get_data_chunk_size());
|
||||
EXPECT_TRUE(source_file != nullptr);
|
||||
if (source_file) {
|
||||
bool stop_requested = false;
|
||||
utils::encryption::encrypting_reader reader("test.dat", source_file_name, stop_requested,
|
||||
token);
|
||||
auto io_stream = reader.create_iostream();
|
||||
EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
EXPECT_EQ(reader.get_total_size(), io_stream->tellg());
|
||||
EXPECT_FALSE(io_stream->seekg(0, std::ios_base::beg).fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
|
||||
for (std::uint8_t i = 0u; i < 8u; i += 2u) {
|
||||
std::vector<char> buffer(utils::encryption::encrypting_reader::get_encrypted_chunk_size() *
|
||||
2u);
|
||||
EXPECT_FALSE(io_stream->read(&buffer[0u], buffer.size()).fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
|
||||
for (std::uint8_t j = 0u; j < 2u; j++) {
|
||||
std::vector<char> decrypted_data;
|
||||
const auto offset = (j * (buffer.size() / 2u));
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(
|
||||
token,
|
||||
std::vector<char>(buffer.begin() + offset,
|
||||
buffer.begin() + offset + (buffer.size() / 2u)),
|
||||
decrypted_data));
|
||||
|
||||
EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(),
|
||||
decrypted_data.size());
|
||||
|
||||
std::size_t bytes_read{};
|
||||
std::vector<char> file_data(decrypted_data.size());
|
||||
source_file->read_bytes(
|
||||
&file_data[0u], file_data.size(),
|
||||
(utils::encryption::encrypting_reader::get_data_chunk_size() * i) +
|
||||
(j * utils::encryption::encrypting_reader::get_data_chunk_size()),
|
||||
bytes_read);
|
||||
EXPECT_EQ(0, std::memcmp(&file_data[0u], &decrypted_data[0u], file_data.size()));
|
||||
}
|
||||
}
|
||||
|
||||
source_file->close();
|
||||
}
|
||||
utils::file::delete_file(source_file_name);
|
||||
}
|
||||
} // namespace repertory
|
125
tests/encryption_test.cpp
Normal file
125
tests/encryption_test.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "utils/encryption.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
static const std::string buffer = "cow moose dog chicken";
|
||||
static const std::string token = "moose";
|
||||
|
||||
static void test_encrypted_result(const std::vector<char> &result) {
|
||||
EXPECT_EQ(buffer.size() + utils::encryption::encrypting_reader::get_header_size(), result.size());
|
||||
std::string data;
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(token, result, data));
|
||||
EXPECT_EQ(buffer.size(), data.size());
|
||||
EXPECT_STREQ(buffer.c_str(), data.c_str());
|
||||
}
|
||||
|
||||
TEST(encryption, generate_key) {
|
||||
const auto key = utils::encryption::generate_key(token);
|
||||
const auto str = utils::to_hex_string(key);
|
||||
EXPECT_STREQ("182072537ada59e4d6b18034a80302ebae935f66adbdf0f271d3d36309c2d481", str.c_str());
|
||||
}
|
||||
|
||||
TEST(encryption, encrypt_data_buffer) {
|
||||
std::vector<char> result;
|
||||
utils::encryption::encrypt_data(token, buffer, result);
|
||||
test_encrypted_result(result);
|
||||
}
|
||||
|
||||
TEST(encryption, encrypt_data_buffer_with_key) {
|
||||
const auto key = utils::encryption::generate_key(token);
|
||||
std::vector<char> result;
|
||||
utils::encryption::encrypt_data(key, buffer, result);
|
||||
test_encrypted_result(result);
|
||||
}
|
||||
|
||||
TEST(encryption, encrypt_data_pointer) {
|
||||
std::vector<char> result;
|
||||
utils::encryption::encrypt_data(token, &buffer[0u], buffer.size(), result);
|
||||
test_encrypted_result(result);
|
||||
}
|
||||
|
||||
TEST(encryption, encrypt_data_pointer_with_key) {
|
||||
const auto key = utils::encryption::generate_key(token);
|
||||
std::vector<char> result;
|
||||
utils::encryption::encrypt_data(key, &buffer[0u], buffer.size(), result);
|
||||
test_encrypted_result(result);
|
||||
}
|
||||
|
||||
TEST(encryption, decrypt_data_pointer) {
|
||||
const auto key = utils::encryption::generate_key(token);
|
||||
std::vector<char> result;
|
||||
utils::encryption::encrypt_data(key, &buffer[0u], buffer.size(), result);
|
||||
|
||||
std::string data;
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(token, &result[0u], result.size(), data));
|
||||
|
||||
EXPECT_EQ(buffer.size(), data.size());
|
||||
EXPECT_STREQ(buffer.c_str(), data.c_str());
|
||||
}
|
||||
|
||||
TEST(encryption, decrypt_data_buffer_with_key) {
|
||||
const auto key = utils::encryption::generate_key(token);
|
||||
std::vector<char> result;
|
||||
utils::encryption::encrypt_data(key, &buffer[0u], buffer.size(), result);
|
||||
|
||||
std::string data;
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(key, result, data));
|
||||
|
||||
EXPECT_EQ(buffer.size(), data.size());
|
||||
EXPECT_STREQ(buffer.c_str(), data.c_str());
|
||||
}
|
||||
|
||||
TEST(encryption, decrypt_data_pointer_with_key) {
|
||||
const auto key = utils::encryption::generate_key(token);
|
||||
std::vector<char> result;
|
||||
utils::encryption::encrypt_data(key, &buffer[0u], buffer.size(), result);
|
||||
|
||||
std::string data;
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(key, &result[0u], result.size(), data));
|
||||
|
||||
EXPECT_EQ(buffer.size(), data.size());
|
||||
EXPECT_STREQ(buffer.c_str(), data.c_str());
|
||||
}
|
||||
|
||||
TEST(encryption, decryption_failure) {
|
||||
const auto key = utils::encryption::generate_key(token);
|
||||
std::vector<char> result;
|
||||
utils::encryption::encrypt_data(key, &buffer[0u], buffer.size(), result);
|
||||
result[0u] = 0u;
|
||||
result[1u] = 1u;
|
||||
result[2u] = 2u;
|
||||
|
||||
std::string data;
|
||||
EXPECT_FALSE(utils::encryption::decrypt_data(key, result, data));
|
||||
}
|
||||
|
||||
TEST(encryption, encryption_failure) {
|
||||
std::vector<char> result;
|
||||
auto key = CryptoPP::SecByteBlock();
|
||||
try {
|
||||
utils::encryption::encrypt_data(key, &buffer[0u], buffer.size(), result);
|
||||
EXPECT_TRUE(false);
|
||||
} catch (const std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
} // namespace repertory
|
69
tests/fixtures/aws_s3_comm_fixture.hpp
vendored
Normal file
69
tests/fixtures/aws_s3_comm_fixture.hpp
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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_AWS_S3_COMM_FIXTURE_H
|
||||
#define REPERTORY_AWS_S3_COMM_FIXTURE_H
|
||||
#if defined(REPERTORY_ENABLE_S3_TESTING)
|
||||
|
||||
#include "comm/aws_s3/aws_s3_comm.hpp"
|
||||
#include "app_config.hpp"
|
||||
#include "test_common.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class aws_s3_comm_test : public ::testing::Test {
|
||||
private:
|
||||
console_consumer c_;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<app_config> config_;
|
||||
std::unique_ptr<aws_s3_comm> s3_comm_;
|
||||
|
||||
public:
|
||||
void SetUp() override {
|
||||
const auto path = utils::path::absolute("./aws_test/");
|
||||
utils::file::delete_directory_recursively(path);
|
||||
{
|
||||
app_config config(provider_type::s3, "../../filebase");
|
||||
config_ = std::make_unique<app_config>(provider_type::s3, "./aws_test");
|
||||
config_->set_event_level(event_level::verbose);
|
||||
config_->set_value_by_name("S3Config.AccessKey", config.get_s3_config().access_key);
|
||||
config_->set_value_by_name("S3Config.SecretKey", config.get_s3_config().secret_key);
|
||||
config_->set_value_by_name("S3Config.Region", config.get_s3_config().region);
|
||||
config_->set_value_by_name("S3Config.URL", config.get_s3_config().url);
|
||||
config_->set_value_by_name("S3Config.Bucket", "");
|
||||
}
|
||||
|
||||
s3_comm_ = std::make_unique<aws_s3_comm>(*config_);
|
||||
|
||||
event_system::instance().start();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
event_system::instance().stop();
|
||||
s3_comm_.reset();
|
||||
config_.reset();
|
||||
|
||||
const auto path = utils::path::absolute("./aws_test/");
|
||||
utils::file::delete_directory_recursively(path);
|
||||
}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_ENABLE_S3_TESTING
|
||||
#endif // REPERTORY_AWS_S3_COMM_FIXTURE_H
|
52
tests/fixtures/directory_db_fixture.hpp
vendored
Normal file
52
tests/fixtures/directory_db_fixture.hpp
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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_DIRECTORY_DB_FIXTURE_H
|
||||
#define REPERTORY_DIRECTORY_DB_FIXTURE_H
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "db/directory_db.hpp"
|
||||
#include "test_common.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class directory_db_test : public ::testing::Test {
|
||||
private:
|
||||
const std::string config_location_ = utils::path::absolute("./directorydb");
|
||||
|
||||
protected:
|
||||
std::unique_ptr<app_config> config_;
|
||||
std::unique_ptr<directory_db> db_;
|
||||
|
||||
public:
|
||||
void SetUp() override {
|
||||
utils::file::delete_directory_recursively(config_location_);
|
||||
config_ = std::make_unique<app_config>(provider_type::skynet, config_location_);
|
||||
db_ = std::make_unique<directory_db>(*config_.get());
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
db_.reset();
|
||||
config_.reset();
|
||||
|
||||
utils::file::delete_directory_recursively(config_location_);
|
||||
}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_DIRECTORY_DB_FIXTURE_H
|
133
tests/fixtures/fuse_fixture.hpp
vendored
Normal file
133
tests/fixtures/fuse_fixture.hpp
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 TESTS_FIXTURES_FUSE_FIXTURE_HPP_
|
||||
#define TESTS_FIXTURES_FUSE_FIXTURE_HPP_
|
||||
#if !_WIN32
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "drives/fuse/fuse_drive.hpp"
|
||||
#include "mocks/mock_comm.hpp"
|
||||
#include "mocks/mock_s3_comm.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
#include "providers/s3/s3_provider.hpp"
|
||||
#include "providers/skynet/skynet_provider.hpp"
|
||||
#include "providers/sia/sia_provider.hpp"
|
||||
#include "test_common.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class fuse_test : public ::testing::Test {
|
||||
public:
|
||||
mock_comm mock_sia_comm_;
|
||||
#ifdef REPERTORY_ENABLE_SKYNET
|
||||
mock_comm mock_skynet_comm_;
|
||||
#endif
|
||||
|
||||
#ifdef REPERTORY_ENABLE_S3_TESTING
|
||||
/* mock_s3_comm mock_s3_comm_; */
|
||||
#ifdef REPERTORY_ENABLE_SKYNET
|
||||
std::array<std::tuple<std::shared_ptr<app_config>, std::shared_ptr<i_provider>,
|
||||
std::shared_ptr<fuse_drive>>,
|
||||
2>
|
||||
provider_tests_;
|
||||
#else
|
||||
std::array<std::tuple<std::shared_ptr<app_config>, std::shared_ptr<i_provider>,
|
||||
std::shared_ptr<fuse_drive>>,
|
||||
1>
|
||||
provider_tests_;
|
||||
#endif
|
||||
#else
|
||||
#ifdef REPERTORY_ENABLE_SKYNET
|
||||
std::array<std::tuple<std::shared_ptr<app_config>, std::shared_ptr<i_provider>,
|
||||
std::shared_ptr<fuse_drive>>,
|
||||
2>
|
||||
provider_tests_;
|
||||
#else
|
||||
std::array<std::tuple<std::shared_ptr<app_config>, std::shared_ptr<i_provider>,
|
||||
std::shared_ptr<fuse_drive>>,
|
||||
1>
|
||||
provider_tests_;
|
||||
#endif
|
||||
#endif
|
||||
lock_data lock_data_;
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
std::size_t provider_index = 0u;
|
||||
utils::file::delete_directory_recursively("./fuse_test");
|
||||
auto config = std::make_shared<app_config>(provider_type::sia, "./fuse_test");
|
||||
config->set_enable_drive_events(true);
|
||||
config->set_event_level(event_level::verbose);
|
||||
config->set_api_port(11115);
|
||||
auto sp = std::make_shared<sia_provider>(*config, mock_sia_comm_);
|
||||
auto drive = std::make_shared<fuse_drive>(*config, lock_data_, *sp);
|
||||
provider_tests_[provider_index++] = {config, sp, drive};
|
||||
|
||||
#ifdef REPERTORY_ENABLE_SKYNET
|
||||
utils::file::delete_directory_recursively("./fuse_test2");
|
||||
config = std::make_shared<app_config>(provider_type::skynet, "./fuse_test2");
|
||||
config->set_enable_drive_events(true);
|
||||
config->set_event_level(event_level::verbose);
|
||||
config->set_api_port(11116);
|
||||
auto skp = std::make_shared<skynet_provider>(*config, mock_skynet_comm_);
|
||||
drive = std::make_shared<fuse_drive>(*config, lock_data_, *skp);
|
||||
provider_tests_[provider_index++] = {config, skp, drive};
|
||||
#endif
|
||||
|
||||
#ifdef REPERTORY_ENABLE_S3_TESTING
|
||||
// utils::file::delete_directory_recursively("./fuse_test3");
|
||||
// config = std::make_shared<app_config>(provider_type::s3, "./fuse_test3");
|
||||
// config->SetEnableDriveEvents(true);
|
||||
// config->set_event_level(event_level::Verbose);
|
||||
// config->SetAPIPort(11117);
|
||||
//{
|
||||
// app_config config(provider_type::s3, "../../filebase");
|
||||
// config->set_event_level(event_level::Verbose);
|
||||
// config->set_value_by_name("S3Config.AccessKey", config.get_s3_config().AccessKey);
|
||||
// config->set_value_by_name("S3Config.SecretKey", config.get_s3_config().SecretKey);
|
||||
// config->set_value_by_name("S3Config.Region", config.get_s3_config().Region);
|
||||
// config->set_value_by_name("S3Config.URL", config.get_s3_config().URL);
|
||||
// config->set_value_by_name("S3Config.Bucket", "repertory");
|
||||
//}
|
||||
// mock_s3_comm_.SetS3Config(config->get_s3_config());
|
||||
|
||||
// auto s3p = std::make_shared<s3_provider>(*config, mock_s3_comm_);
|
||||
// drive = std::make_shared<fuse_drive>(*config, lock_data_, *s3p);
|
||||
// provider_tests_[provider_index++] = {config, s3p, drive};
|
||||
#endif
|
||||
event_system::instance().start();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
for (auto &i : provider_tests_) {
|
||||
std::get<2>(i).reset();
|
||||
}
|
||||
event_system::instance().stop();
|
||||
for (auto &i : provider_tests_) {
|
||||
std::get<1>(i).reset();
|
||||
std::get<0>(i).reset();
|
||||
}
|
||||
utils::file::delete_directory_recursively("./fuse_test");
|
||||
utils::file::delete_directory_recursively("./fuse_test2");
|
||||
utils::file::delete_directory_recursively("./fuse_test3");
|
||||
}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif
|
||||
#endif // TESTS_FIXTURES_FUSE_FIXTURE_HPP_
|
105
tests/fixtures/skynet_provider_fixture.hpp
vendored
Normal file
105
tests/fixtures/skynet_provider_fixture.hpp
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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_SKYNET_PROVIDER_FIXTURE_H
|
||||
#define REPERTORY_SKYNET_PROVIDER_FIXTURE_H
|
||||
#if defined(REPERTORY_ENABLE_SKYNET)
|
||||
|
||||
#include "comm/curl/curl_comm.hpp"
|
||||
#include "app_config.hpp"
|
||||
#include "mocks/mock_open_file_table.hpp"
|
||||
#include "providers/skynet/skynet_provider.hpp"
|
||||
#include "test_common.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class skynet_provider_test : public ::testing::Test {
|
||||
private:
|
||||
console_consumer c_;
|
||||
const std::string config_location_ = utils::path::absolute("./skynetprovider");
|
||||
|
||||
protected:
|
||||
std::unique_ptr<app_config> config_;
|
||||
std::unique_ptr<curl_comm> curl_comm_;
|
||||
std::unique_ptr<skynet_provider> provider_;
|
||||
mock_open_file_table oft_;
|
||||
|
||||
public:
|
||||
void SetUp() override {
|
||||
utils::file::delete_directory_recursively(config_location_);
|
||||
|
||||
config_ = std::make_unique<app_config>(provider_type::skynet, config_location_);
|
||||
config_->set_event_level(event_level::verbose);
|
||||
|
||||
event_system::instance().start();
|
||||
curl_comm_ = std::make_unique<curl_comm>(*config_.get());
|
||||
provider_ = std::make_unique<skynet_provider>(*config_.get(), *curl_comm_.get());
|
||||
|
||||
const auto res = provider_->start(
|
||||
[&](const std::string &api_path, const std::string &api_parent, const std::string &source,
|
||||
const bool &directory, const std::uint64_t &created_date,
|
||||
const std::uint64_t &accessed_date, const std::uint64_t &modified_date,
|
||||
const std::uint64_t &changed_date) {
|
||||
event_system::instance().raise<filesystem_item_added>(api_path, api_parent, directory);
|
||||
#ifdef _WIN32
|
||||
provider_->set_item_meta(
|
||||
api_path, {{META_ATTRIBUTES, std::to_string(directory ? FILE_ATTRIBUTE_DIRECTORY
|
||||
: FILE_ATTRIBUTE_NORMAL |
|
||||
FILE_ATTRIBUTE_ARCHIVE)},
|
||||
{META_CREATION, std::to_string(created_date)},
|
||||
{META_WRITTEN, std::to_string(modified_date)},
|
||||
{META_MODIFIED, std::to_string(modified_date)},
|
||||
{ META_ACCESSED,
|
||||
std::to_string(accessed_date) }});
|
||||
#else
|
||||
provider_->set_item_meta(
|
||||
api_path,
|
||||
{{META_CREATION, std::to_string(created_date)},
|
||||
{META_MODIFIED, std::to_string(modified_date)},
|
||||
{META_WRITTEN, std::to_string(modified_date)},
|
||||
{META_ACCESSED, std::to_string(accessed_date)},
|
||||
{META_OSXFLAGS, "0"},
|
||||
{META_BACKUP, "0"},
|
||||
{META_CHANGED, std::to_string(changed_date)},
|
||||
{META_MODE, utils::string::from_uint32(directory ? S_IRUSR | S_IWUSR | S_IXUSR
|
||||
: S_IRUSR | S_IWUSR)},
|
||||
{META_UID, utils::string::from_uint32(getuid())},
|
||||
{META_GID, utils::string::from_uint32(getgid())}});
|
||||
#endif
|
||||
if (not directory && not source.empty()) {
|
||||
provider_->set_source_path(api_path, source);
|
||||
}
|
||||
},
|
||||
&oft_);
|
||||
EXPECT_FALSE(res);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
provider_->stop();
|
||||
event_system::instance().stop();
|
||||
curl_comm_.reset();
|
||||
config_.reset();
|
||||
provider_.reset();
|
||||
|
||||
utils::file::delete_directory_recursively(config_location_);
|
||||
}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_ENABLE_SKYNET
|
||||
#endif // REPERTORY_SKYNET_PROVIDER_FIXTURE_H
|
85
tests/fixtures/winfsp_fixture.hpp
vendored
Normal file
85
tests/fixtures/winfsp_fixture.hpp
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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_WINFSP_FIXTURE_H
|
||||
#define REPERTORY_WINFSP_FIXTURE_H
|
||||
#if _WIN32
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "drives/winfsp/winfsp_drive.hpp"
|
||||
#include "mocks/mock_comm.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
#include "providers/sia/sia_provider.hpp"
|
||||
#include "providers/skynet/skynet_provider.hpp"
|
||||
#include "test_common.hpp"
|
||||
|
||||
extern std::size_t PROVIDER_INDEX;
|
||||
|
||||
namespace repertory {
|
||||
class winfsp_test : public ::testing::Test {
|
||||
public:
|
||||
mock_comm mock_sia_comm_;
|
||||
mock_comm mock_skynet_comm_;
|
||||
std::array<std::tuple<std::shared_ptr<app_config>, std::shared_ptr<i_provider>,
|
||||
std::shared_ptr<winfsp_drive>>,
|
||||
2>
|
||||
provider_tests_;
|
||||
lock_data lock_data_;
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
if (PROVIDER_INDEX != 0) {
|
||||
utils::file::delete_directory_recursively("./winfsp_test");
|
||||
auto config = std::make_shared<app_config>(provider_type::sia, "./winfsp_test");
|
||||
config->set_enable_drive_events(true);
|
||||
config->set_event_level(event_level::verbose);
|
||||
config->set_api_port(11115);
|
||||
auto sp = std::make_shared<sia_provider>(*config, mock_sia_comm_);
|
||||
auto drive = std::make_shared<winfsp_drive>(*config, lock_data_, *sp);
|
||||
provider_tests_[0] = {config, sp, drive};
|
||||
|
||||
config = std::make_shared<app_config>(provider_type::skynet, "./winfsp_test");
|
||||
config->set_enable_drive_events(true);
|
||||
config->set_event_level(event_level::verbose);
|
||||
config->set_api_port(11116);
|
||||
auto skp = std::make_shared<skynet_provider>(*config, mock_skynet_comm_);
|
||||
drive = std::make_shared<winfsp_drive>(*config, lock_data_, *skp);
|
||||
provider_tests_[1] = {config, skp, drive};
|
||||
|
||||
event_system::instance().start();
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if (PROVIDER_INDEX != 0) {
|
||||
for (auto &i : provider_tests_) {
|
||||
std::get<2>(i).reset();
|
||||
}
|
||||
event_system::instance().stop();
|
||||
for (auto &i : provider_tests_) {
|
||||
std::get<1>(i).reset();
|
||||
std::get<0>(i).reset();
|
||||
}
|
||||
utils::file::delete_directory_recursively("./winfsp_test");
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif
|
||||
#endif // REPERTORY_WINFSP_FIXTURE_H
|
1589
tests/fuse_test.cpp
Normal file
1589
tests/fuse_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
119
tests/lock_data_test.cpp
Normal file
119
tests/lock_data_test.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "common.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
#include "test_common.hpp"
|
||||
|
||||
namespace repertory {
|
||||
TEST(lock_data, lock_and_unlock) {
|
||||
{
|
||||
lock_data l(provider_type::sia, "1");
|
||||
EXPECT_EQ(lock_result::success, l.grab_lock());
|
||||
|
||||
lock_data l2(provider_type::skynet, "1");
|
||||
EXPECT_EQ(lock_result::success, l2.grab_lock());
|
||||
|
||||
std::thread([]() {
|
||||
lock_data l(provider_type::sia, "1");
|
||||
EXPECT_EQ(lock_result::locked, l.grab_lock(10));
|
||||
|
||||
lock_data l2(provider_type::skynet, "1");
|
||||
EXPECT_EQ(lock_result::locked, l2.grab_lock(10));
|
||||
}).join();
|
||||
}
|
||||
|
||||
std::thread([]() {
|
||||
lock_data l(provider_type::sia, "1");
|
||||
EXPECT_EQ(lock_result::success, l.grab_lock(10));
|
||||
|
||||
lock_data l2(provider_type::skynet, "1");
|
||||
EXPECT_EQ(lock_result::success, l2.grab_lock(10));
|
||||
}).join();
|
||||
|
||||
#ifdef _WIN32
|
||||
lock_data l2(provider_type::remote, "1");
|
||||
EXPECT_EQ(lock_result::success, l2.grab_lock());
|
||||
|
||||
lock_data l3(provider_type::remote, "2");
|
||||
EXPECT_EQ(lock_result::success, l3.grab_lock());
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
TEST(lock_data, set_and_unset_mount_state) {
|
||||
lock_data l(provider_type::sia, "1");
|
||||
EXPECT_TRUE(l.set_mount_state(true, "C:", 99));
|
||||
|
||||
lock_data l2(provider_type::skynet, "1");
|
||||
EXPECT_TRUE(l2.set_mount_state(true, "D:", 98));
|
||||
|
||||
lock_data l3(provider_type::remote, "1");
|
||||
EXPECT_TRUE(l3.set_mount_state(true, "E:", 97));
|
||||
|
||||
lock_data l4(provider_type::remote, "2");
|
||||
EXPECT_TRUE(l4.set_mount_state(true, "F:", 96));
|
||||
|
||||
json mount_state;
|
||||
EXPECT_TRUE(l.get_mount_state(mount_state));
|
||||
|
||||
EXPECT_STREQ(R"({"Active":true,"Location":"E:","PID":97})",
|
||||
mount_state["Remote1"].dump().c_str());
|
||||
EXPECT_STREQ(R"({"Active":true,"Location":"F:","PID":96})",
|
||||
mount_state["Remote2"].dump().c_str());
|
||||
EXPECT_STREQ(R"({"Active":true,"Location":"C:","PID":99})", mount_state["Sia1"].dump().c_str());
|
||||
EXPECT_STREQ(R"({"Active":true,"Location":"D:","PID":98})",
|
||||
mount_state["Skynet1"].dump().c_str());
|
||||
|
||||
EXPECT_TRUE(l.set_mount_state(false, "C:", 99));
|
||||
EXPECT_TRUE(l2.set_mount_state(false, "D:", 98));
|
||||
EXPECT_TRUE(l3.set_mount_state(false, "E:", 97));
|
||||
EXPECT_TRUE(l4.set_mount_state(false, "F:", 96));
|
||||
|
||||
EXPECT_TRUE(l.get_mount_state(mount_state));
|
||||
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})", mount_state["Remote1"].dump().c_str());
|
||||
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})", mount_state["Remote2"].dump().c_str());
|
||||
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})", mount_state["Sia1"].dump().c_str());
|
||||
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})", mount_state["Skynet1"].dump().c_str());
|
||||
}
|
||||
#else
|
||||
TEST(lock_data, set_and_unset_mount_state) {
|
||||
lock_data l(provider_type::sia, "1");
|
||||
EXPECT_TRUE(l.set_mount_state(true, "/mnt/1", 99));
|
||||
|
||||
lock_data l2(provider_type::skynet, "1");
|
||||
EXPECT_TRUE(l2.set_mount_state(true, "/mnt/2", 98));
|
||||
|
||||
json mount_state;
|
||||
EXPECT_TRUE(l.get_mount_state(mount_state));
|
||||
|
||||
EXPECT_STREQ(R"({"Active":true,"Location":"/mnt/1","PID":99})",
|
||||
mount_state["Sia1"].dump().c_str());
|
||||
EXPECT_STREQ(R"({"Active":true,"Location":"/mnt/2","PID":98})",
|
||||
mount_state["Skynet1"].dump().c_str());
|
||||
|
||||
EXPECT_TRUE(l.set_mount_state(false, "/mnt/1", 99));
|
||||
EXPECT_TRUE(l2.set_mount_state(false, "/mnt/t", 98));
|
||||
|
||||
EXPECT_TRUE(l.get_mount_state(mount_state));
|
||||
|
||||
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})", mount_state["Sia1"].dump().c_str());
|
||||
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})", mount_state["Skynet1"].dump().c_str());
|
||||
}
|
||||
#endif
|
||||
} // namespace repertory
|
176
tests/mocks/mock_comm.hpp
Normal file
176
tests/mocks/mock_comm.hpp
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 TESTS_MOCKS_MOCK_COMM_HPP_
|
||||
#define TESTS_MOCKS_MOCK_COMM_HPP_
|
||||
|
||||
#include "test_common.hpp"
|
||||
#include "comm/i_comm.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class mock_comm : public virtual i_comm {
|
||||
private:
|
||||
struct mock_data {
|
||||
api_error error;
|
||||
json result;
|
||||
json json_error;
|
||||
bool persist = false;
|
||||
};
|
||||
std::unordered_map<std::string, std::deque<mock_data>> return_lookup_;
|
||||
|
||||
public:
|
||||
void push_return(const std::string &op, const std::string &path, const json &result,
|
||||
const json &error, const api_error &apiError, bool persist = false) {
|
||||
const auto lookup_path = op + path;
|
||||
if (return_lookup_.find(lookup_path) == return_lookup_.end()) {
|
||||
return_lookup_[lookup_path] = std::deque<mock_data>();
|
||||
};
|
||||
mock_data data = {apiError, result, error, persist};
|
||||
return_lookup_[lookup_path].emplace_back(data);
|
||||
}
|
||||
|
||||
void remove_return(const std::string &op, const std::string &path) {
|
||||
const auto lookup_path = op + path;
|
||||
return_lookup_.erase(lookup_path);
|
||||
}
|
||||
|
||||
private:
|
||||
api_error process(const std::string &op, const std::string &path, json &data, json &error) {
|
||||
const auto lookup_path = op + path;
|
||||
if ((return_lookup_.find(lookup_path) == return_lookup_.end()) ||
|
||||
return_lookup_[lookup_path].empty()) {
|
||||
EXPECT_STREQ("", ("unexpected path: " + lookup_path).c_str());
|
||||
return api_error::comm_error;
|
||||
}
|
||||
error = return_lookup_[lookup_path].front().json_error;
|
||||
data = return_lookup_[lookup_path].front().result;
|
||||
const auto ret = return_lookup_[lookup_path].front().error;
|
||||
if (not return_lookup_[lookup_path].front().persist) {
|
||||
return_lookup_[lookup_path].pop_front();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public:
|
||||
api_error get(const std::string &path, json &data, json &error) override {
|
||||
return process("get", path, data, error);
|
||||
}
|
||||
|
||||
api_error get(const host_config &, const std::string &path, json &data, json &error) override {
|
||||
return process("get", path, data, error);
|
||||
}
|
||||
|
||||
api_error get(const std::string &path, const http_parameters &, json &data,
|
||||
json &error) override {
|
||||
return process("get_params", path, data, error);
|
||||
}
|
||||
|
||||
api_error get(const host_config &, const std::string &path, const http_parameters &, json &data,
|
||||
json &error) override {
|
||||
return process("get_params", path, data, error);
|
||||
}
|
||||
|
||||
api_error get_range(const std::string & /*path*/, const std::uint64_t & /*data_size*/,
|
||||
const http_parameters & /*parameters*/,
|
||||
const std::string & /*encryption_token*/, std::vector<char> & /*data*/,
|
||||
const http_ranges & /*ranges*/, json & /*error*/,
|
||||
const bool & /*stop_requested*/) override {
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
api_error get_range(const host_config & /*hc*/, const std::string & /*path*/,
|
||||
const std::uint64_t & /*data_size*/, const http_parameters & /*parameters*/,
|
||||
const std::string & /*encryption_token*/, std::vector<char> & /*data*/,
|
||||
const http_ranges & /*ranges*/, json & /*error*/,
|
||||
const bool & /*stop_requested*/) override {
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
api_error get_range_and_headers(const std::string & /*path*/, const std::uint64_t & /*data_size*/,
|
||||
const http_parameters & /*parameters*/,
|
||||
const std::string & /*encryption_token*/,
|
||||
std::vector<char> & /*data*/, const http_ranges & /*ranges*/,
|
||||
json & /*error*/, http_headers & /*headers*/,
|
||||
const bool & /*stop_requested*/) override {
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
api_error get_range_and_headers(const host_config & /*hc*/, const std::string & /*path*/,
|
||||
const std::uint64_t & /*data_size*/,
|
||||
const http_parameters & /*parameters*/,
|
||||
const std::string & /*encryption_token*/,
|
||||
std::vector<char> & /*data*/, const http_ranges & /*ranges*/,
|
||||
json & /*error*/, http_headers & /*headers*/,
|
||||
const bool & /*stop_requested*/) override {
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
api_error get_raw(const std::string &, const http_parameters &, std::vector<char> &, json &,
|
||||
const bool &) override {
|
||||
throw std::runtime_error("not implemented: get_raw");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
api_error get_raw(const host_config &, const std::string &, const http_parameters &,
|
||||
std::vector<char> &, json &, const bool &) override {
|
||||
throw std::runtime_error("not implemented: get_raw");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
api_error post(const std::string &path, json &data, json &error) override {
|
||||
return process("post", path, data, error);
|
||||
}
|
||||
|
||||
api_error post(const host_config &, const std::string &path, json &data, json &error) override {
|
||||
return process("post", path, data, error);
|
||||
}
|
||||
|
||||
api_error post(const std::string &path, const http_parameters &, json &data,
|
||||
json &error) override {
|
||||
return process("post_params", path, data, error);
|
||||
}
|
||||
|
||||
api_error post(const host_config &, const std::string &path, const http_parameters &, json &data,
|
||||
json &error) override {
|
||||
return process("post_params", path, data, error);
|
||||
}
|
||||
|
||||
api_error post_file(const std::string &, const std::string &, const http_parameters &, json &,
|
||||
json &, const bool &) override {
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
api_error post_file(const host_config &, const std::string &, const std::string &,
|
||||
const http_parameters &, json &, json &, const bool &) override {
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
api_error post_multipart_file(const std::string &, const std::string &, const std::string &,
|
||||
const std::string &, json &, json &, const bool &) override {
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
api_error post_multipart_file(const host_config &, const std::string &, const std::string &,
|
||||
const std::string &, const std::string &, json &, json &,
|
||||
const bool &) override {
|
||||
return api_error::error;
|
||||
}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // TESTS_MOCKS_MOCK_COMM_HPP_
|
134
tests/mocks/mock_fuse_drive.hpp
Normal file
134
tests/mocks/mock_fuse_drive.hpp
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 TESTS_MOCKS_MOCK_FUSE_DRIVE_HPP_
|
||||
#define TESTS_MOCKS_MOCK_FUSE_DRIVE_HPP_
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "common.hpp"
|
||||
#include "drives/fuse/i_fuse_drive.hpp"
|
||||
#include "types/remote.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class mock_fuse_drive final : public virtual i_fuse_drive {
|
||||
public:
|
||||
explicit mock_fuse_drive(std::string mount_location)
|
||||
: mount_location_(std::move(mount_location)) {}
|
||||
|
||||
private:
|
||||
const std::string mount_location_;
|
||||
std::unordered_map<std::string, api_meta_map> meta_;
|
||||
|
||||
public:
|
||||
api_error check_parent_access(const std::string &, int) const override {
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
std::uint64_t get_directory_item_count(const std::string &) const override { return 1; }
|
||||
|
||||
directory_item_list get_directory_items(const std::string &) const override {
|
||||
directory_item_list list{};
|
||||
|
||||
directory_item di{};
|
||||
di.api_path = ".";
|
||||
di.directory = true;
|
||||
di.size = 0;
|
||||
di.meta = {{META_ATTRIBUTES, "16"},
|
||||
{META_MODIFIED, std::to_string(utils::get_file_time_now())},
|
||||
{META_WRITTEN, std::to_string(utils::get_file_time_now())},
|
||||
{META_ACCESSED, std::to_string(utils::get_file_time_now())},
|
||||
{META_CREATION, std::to_string(utils::get_file_time_now())}};
|
||||
list.emplace_back(di);
|
||||
|
||||
di.api_path = "..";
|
||||
list.emplace_back(di);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
std::uint64_t get_file_size(const std::string &) const override { return 0u; }
|
||||
|
||||
api_error get_item_meta(const std::string &api_path, api_meta_map &meta) const override {
|
||||
meta = const_cast<mock_fuse_drive *>(this)->meta_[api_path];
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
api_error get_item_meta(const std::string &api_path, const std::string &name,
|
||||
std::string &value) const override {
|
||||
value = const_cast<mock_fuse_drive *>(this)->meta_[api_path][name];
|
||||
if (value.empty()) {
|
||||
value = "0";
|
||||
}
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
std::uint64_t get_total_drive_space() const override { return 100 * 1024 * 1024; }
|
||||
|
||||
std::uint64_t get_total_item_count() const override { return 0u; }
|
||||
|
||||
std::uint64_t get_used_drive_space() const override { return 0u; }
|
||||
|
||||
void get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
||||
std::string &volume_label) const override {
|
||||
free_size = 100u;
|
||||
total_size = 200u;
|
||||
volume_label = "TestVolumeLabel";
|
||||
}
|
||||
|
||||
void populate_stat(const directory_item &, struct stat &) const override {}
|
||||
|
||||
int rename_directory(const std::string &from_api_path, const std::string &to_api_path) override {
|
||||
const auto from_file_path = utils::path::combine(mount_location_, {from_api_path});
|
||||
const auto to_file_path = utils::path::combine(mount_location_, {to_api_path});
|
||||
return rename(from_file_path.c_str(), to_file_path.c_str());
|
||||
}
|
||||
|
||||
int rename_file(const std::string &from_api_path, const std::string &to_api_path,
|
||||
const bool &overwrite) override {
|
||||
const auto from_file_path = utils::path::combine(mount_location_, {from_api_path});
|
||||
const auto to_file_path = utils::path::combine(mount_location_, {to_api_path});
|
||||
|
||||
if (overwrite) {
|
||||
if (not utils::file::delete_file(to_file_path)) {
|
||||
return -1;
|
||||
}
|
||||
} else if (utils::file::is_directory(to_file_path) || utils::file::is_file(to_file_path)) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return rename(from_file_path.c_str(), to_file_path.c_str());
|
||||
}
|
||||
|
||||
bool is_processing(const std::string &) const override { return false; }
|
||||
|
||||
void set_item_meta(const std::string &api_path, const std::string &key,
|
||||
const std::string &value) override {
|
||||
meta_[api_path][key] = value;
|
||||
}
|
||||
|
||||
void update_directory_item(directory_item &) const override {}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // _WIN32
|
||||
#endif // TESTS_MOCKS_MOCK_FUSE_DRIVE_HPP_
|
70
tests/mocks/mock_open_file_table.hpp
Normal file
70
tests/mocks/mock_open_file_table.hpp
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 TESTS_MOCKS_MOCK_OPEN_FILE_TABLE_HPP_
|
||||
#define TESTS_MOCKS_MOCK_OPEN_FILE_TABLE_HPP_
|
||||
|
||||
#include "download/download_manager.hpp"
|
||||
#include "drives/i_open_file_table.hpp"
|
||||
#include "test_common.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class mock_open_file_table : public virtual i_open_file_table {
|
||||
public:
|
||||
explicit mock_open_file_table(download_manager *dm = nullptr, filesystem_item *fsi = nullptr)
|
||||
: dm_(dm), fsi_(fsi) {}
|
||||
|
||||
private:
|
||||
download_manager *dm_;
|
||||
filesystem_item *fsi_;
|
||||
|
||||
public:
|
||||
MOCK_CONST_METHOD1(get_open_count, std::uint64_t(const std::string &api_path));
|
||||
|
||||
MOCK_CONST_METHOD0(has_no_open_file_handles, bool());
|
||||
|
||||
MOCK_METHOD1(close, void(const std::uint64_t &handle));
|
||||
|
||||
MOCK_CONST_METHOD1(contains_restore, bool(const std::string &api_path));
|
||||
|
||||
MOCK_METHOD1(evict_file, bool(const std::string &api_path));
|
||||
|
||||
MOCK_CONST_METHOD1(get_directory_items, directory_item_list(const std::string &api_path));
|
||||
|
||||
MOCK_METHOD2(get_open_file, bool(const std::string &api_path, struct filesystem_item *&fsi));
|
||||
|
||||
MOCK_CONST_METHOD0(get_open_files, std::unordered_map<std::string, std::size_t>());
|
||||
|
||||
MOCK_METHOD1(force_schedule_upload, void(const struct filesystem_item &fsi));
|
||||
|
||||
MOCK_METHOD2(open, api_error(const struct filesystem_item &fsi, std::uint64_t &handle));
|
||||
|
||||
MOCK_METHOD3(set_item_meta, api_error(const std::string &api_path, const std::string &key,
|
||||
const std::string &value));
|
||||
bool perform_locked_operation(locked_operation_callback /*locked_operation*/) override {
|
||||
if (fsi_ && dm_) {
|
||||
fsi_->source_path = dm_->get_source_path(fsi_->api_path);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void update_directory_item(directory_item &) const override {}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // TESTS_MOCKS_MOCK_OPEN_FILE_TABLE_HPP_
|
84
tests/mocks/mock_provider.hpp
Normal file
84
tests/mocks/mock_provider.hpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 TESTS_MOCKS_MOCKPROVIDER_HPP_
|
||||
#define TESTS_MOCKS_MOCKPROVIDER_HPP_
|
||||
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "test_common.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class mock_provider : public virtual i_provider {
|
||||
public:
|
||||
mock_provider(const bool &allow_rename = true) : allow_rename_(allow_rename) {}
|
||||
|
||||
private:
|
||||
const bool allow_rename_;
|
||||
|
||||
public:
|
||||
MOCK_METHOD2(create_directory, api_error(const std::string &api_path, const api_meta_map &meta));
|
||||
MOCK_METHOD2(create_directory_clone_source_meta,
|
||||
api_error(const std::string &source_api_path, const std::string &api_path));
|
||||
MOCK_METHOD2(create_file, api_error(const std::string &api_path, const api_meta_map &meta));
|
||||
MOCK_CONST_METHOD2(get_api_path_from_source,
|
||||
api_error(const std::string &source_path, std::string &api_path));
|
||||
MOCK_CONST_METHOD1(get_directory_item_count, std::uint64_t(const std::string &api_path));
|
||||
MOCK_CONST_METHOD2(get_directory_items,
|
||||
api_error(const std::string &api_path, directory_item_list &list));
|
||||
MOCK_CONST_METHOD2(get_file, api_error(const std::string &api_path, ApiFile &apiFile));
|
||||
MOCK_CONST_METHOD1(get_file_list, api_error(api_file_list &list));
|
||||
MOCK_CONST_METHOD2(get_file_size,
|
||||
api_error(const std::string &api_path, std::uint64_t &file_size));
|
||||
MOCK_CONST_METHOD3(get_filesystem_item, api_error(const std::string &api_path,
|
||||
const bool &directory, filesystem_item &fsi));
|
||||
MOCK_CONST_METHOD2(get_filesystem_item_from_source_path,
|
||||
api_error(const std::string &source_path, filesystem_item &fsi));
|
||||
MOCK_CONST_METHOD2(get_item_meta, api_error(const std::string &api_path, api_meta_map &meta));
|
||||
MOCK_CONST_METHOD3(get_item_meta, api_error(const std::string &api_path, const std::string &key,
|
||||
std::string &value));
|
||||
MOCK_CONST_METHOD0(get_pinned_files, std::vector<std::string>());
|
||||
MOCK_CONST_METHOD0(get_provider_type, provider_type());
|
||||
MOCK_CONST_METHOD0(get_total_drive_space, std::uint64_t());
|
||||
MOCK_CONST_METHOD0(get_total_item_count, std::uint64_t());
|
||||
MOCK_CONST_METHOD0(get_used_drive_space, std::uint64_t());
|
||||
MOCK_CONST_METHOD1(is_directory, bool(const std::string &api_path));
|
||||
MOCK_CONST_METHOD1(is_file, bool(const std::string &api_path));
|
||||
bool is_file_writeable(const std::string &api_path) const override { return true; }
|
||||
MOCK_CONST_METHOD0(IsOnline, bool());
|
||||
bool is_rename_supported() const override { return allow_rename_; }
|
||||
MOCK_METHOD5(read_file_bytes, api_error(const std::string &path, const std::size_t &size,
|
||||
const std::uint64_t &offset, std::vector<char> &data,
|
||||
const bool &stop_requested));
|
||||
MOCK_METHOD1(remove_directory, api_error(const std::string &api_path));
|
||||
MOCK_METHOD1(remove_file, api_error(const std::string &api_path));
|
||||
MOCK_METHOD2(remove_item_meta, api_error(const std::string &api_path, const std::string &key));
|
||||
MOCK_METHOD2(rename_file,
|
||||
api_error(const std::string &from_api_path, const std::string &to_api_path));
|
||||
MOCK_METHOD3(set_item_meta, api_error(const std::string &api_path, const std::string &key,
|
||||
const std::string &value));
|
||||
MOCK_METHOD2(set_item_meta, api_error(const std::string &api_path, const api_meta_map &meta));
|
||||
MOCK_METHOD2(set_source_path,
|
||||
api_error(const std::string &api_path, const std::string &source_path));
|
||||
MOCK_METHOD2(start, bool(api_item_added_callback api_item_added, i_open_file_table *oft));
|
||||
MOCK_METHOD0(stop, void());
|
||||
MOCK_METHOD3(upload_file, api_error(const std::string &api_path, const std::string &source_path,
|
||||
const std::string &encryption_token));
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // TESTS_MOCKS_MOCKPROVIDER_HPP_
|
80
tests/mocks/mock_s3_comm.hpp
Normal file
80
tests/mocks/mock_s3_comm.hpp
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 TESTS_MOCKS_MOCK_S3_COMM_HPP_
|
||||
#define TESTS_MOCKS_MOCK_S3_COMM_HPP_
|
||||
#ifdef REPERTORY_ENABLE_S3_TESTING
|
||||
|
||||
#include "test_common.hpp"
|
||||
#include "comm/i_s3_comm.hpp"
|
||||
|
||||
namespace repertory {
|
||||
/* class mock_s3_comm final : public i_s3_comm { */
|
||||
/* private: */
|
||||
/* S3Config s3_config_; */
|
||||
/* */
|
||||
/* public: */
|
||||
/* MOCK_METHOD1(create_bucket, api_error(const std::string &api_path)); */
|
||||
/* MOCK_CONST_METHOD1(Exists, bool(const std::string &api_path)); */
|
||||
/* */
|
||||
/* MOCK_CONST_METHOD3(get_bucket_name_and_object_name, */
|
||||
/* void(const std::string &api_path, std::string &bucketName, */
|
||||
/* std::string &objectName)); */
|
||||
/* */
|
||||
/* MOCK_CONST_METHOD2(get_directory_item_count, */
|
||||
/* std::size_t(const std::string &api_path, */
|
||||
/* const MetaProviderCallback &metaProviderCallback)); */
|
||||
/* */
|
||||
/* MOCK_CONST_METHOD3(get_directory_items, */
|
||||
/* api_error(const std::string &api_path, */
|
||||
/* const MetaProviderCallback &metaProviderCallback, */
|
||||
/* directory_item_list &list)); */
|
||||
/* */
|
||||
/* S3Config GetS3Config() override { return s3Config_; } */
|
||||
/* */
|
||||
/* S3Config GetS3Config() const override { return s3Config_; } */
|
||||
/* */
|
||||
/* MOCK_CONST_METHOD2(GetFile, api_error(const std::string &api_path, ApiFile &apiFile)); */
|
||||
/* */
|
||||
/* MOCK_CONST_METHOD1(get_file_list, api_error(ApiFileList &apiFileList)); */
|
||||
/* */
|
||||
/* bool IsOnline() const override { return true; } */
|
||||
/* */
|
||||
/* MOCK_CONST_METHOD5(read_file_bytes, */
|
||||
/* api_error(const std::string &path, const std::size_t &size, */
|
||||
/* const std::uint64_t &offset, std::vector<char> &data, */
|
||||
/* const bool &stop_requested)); */
|
||||
/* */
|
||||
/* MOCK_METHOD1(remove_bucket, api_error(const std::string &api_path)); */
|
||||
/* */
|
||||
/* MOCK_METHOD1(RemoveFile, api_error(const std::string &api_path)); */
|
||||
/* */
|
||||
/* MOCK_METHOD2(RenameFile, */
|
||||
/* api_error(const std::string &api_path, const std::string &newApiFilePath));
|
||||
*/
|
||||
/* */
|
||||
/* void SetS3Config(S3Config s3Config) { s3Config_ = std::move(s3Config); } */
|
||||
/* */
|
||||
/* MOCK_METHOD3(upload_file, api_error(const std::string &api_path, */
|
||||
/* const std::string &sourcePath, const bool
|
||||
* &stop_requested)); */
|
||||
/* }; */
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_ENABLE_S3_TESTING
|
||||
#endif // TESTS_MOCKS_MOCK_S3_COMM_HPP_
|
142
tests/mocks/mock_winfsp_drive.hpp
Normal file
142
tests/mocks/mock_winfsp_drive.hpp
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 TESTS_MOCKS_MOCK_WINFSP_DRIVE_HPP_
|
||||
#define TESTS_MOCKS_MOCK_WINFSP_DRIVE_HPP_
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "common.hpp"
|
||||
#include "drives/winfsp/i_winfsp_drive.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class mock_winfsp_drive final : public virtual i_winfsp_drive {
|
||||
public:
|
||||
explicit mock_winfsp_drive(const std::string &mount_location) : mount_location_(mount_location) {}
|
||||
|
||||
private:
|
||||
const std::string mount_location_;
|
||||
|
||||
public:
|
||||
std::uint64_t get_directory_item_count(const std::string &api_path) const override { return 1; }
|
||||
|
||||
directory_item_list get_directory_items(const std::string &api_path) const override {
|
||||
directory_item_list list{};
|
||||
|
||||
directory_item di{};
|
||||
di.api_path = ".";
|
||||
di.directory = true;
|
||||
di.size = 0u;
|
||||
di.meta = {{META_ATTRIBUTES, "16"},
|
||||
{META_MODIFIED, std::to_string(utils::get_file_time_now())},
|
||||
{META_WRITTEN, std::to_string(utils::get_file_time_now())},
|
||||
{META_ACCESSED, std::to_string(utils::get_file_time_now())},
|
||||
{META_CREATION, std::to_string(utils::get_file_time_now())}};
|
||||
list.emplace_back(di);
|
||||
|
||||
di.api_path = "..";
|
||||
list.emplace_back(di);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
std::uint64_t get_file_size(const std::string &api_path) const override { return 0; }
|
||||
|
||||
api_error get_item_meta(const std::string &api_path, api_meta_map &meta) const override {
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
api_error get_item_meta(const std::string &api_path, const std::string &name,
|
||||
std::string &value) const override {
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
NTSTATUS get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||
PSECURITY_DESCRIPTOR descriptor,
|
||||
std::uint64_t *descriptor_size) override {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
if (attributes) {
|
||||
*attributes = FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
|
||||
if (descriptor_size) {
|
||||
ULONG sz = 0;
|
||||
PSECURITY_DESCRIPTOR sd = nullptr;
|
||||
if (::ConvertStringSecurityDescriptorToSecurityDescriptor(
|
||||
"O:BAG:BAD:P(A;;FA;;;SY)(A;;FA;;;BA)(A;;FA;;;WD)", SDDL_REVISION_1, &sd, &sz)) {
|
||||
if (sz > *descriptor_size) {
|
||||
ret = STATUS_BUFFER_TOO_SMALL;
|
||||
} else {
|
||||
::CopyMemory(descriptor, sd, sz);
|
||||
}
|
||||
*descriptor_size = sz;
|
||||
::LocalFree(sd);
|
||||
} else {
|
||||
ret = FspNtStatusFromWin32(::GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::uint64_t get_total_drive_space() const override { return 100 * 1024 * 1024; }
|
||||
|
||||
std::uint64_t get_total_item_count() const override { return 0; }
|
||||
|
||||
std::uint64_t get_used_drive_space() const override { return 0; }
|
||||
|
||||
void get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
||||
std::string &volume_label) const override {
|
||||
free_size = 100;
|
||||
total_size = 200;
|
||||
volume_label = "TestVolumeLabel";
|
||||
}
|
||||
|
||||
api_error populate_file_info(const std::string &api_path, remote::file_info &file_info) override {
|
||||
const auto file_path = utils::path::combine(mount_location_, {api_path});
|
||||
const auto directory = utils::file::is_directory(file_path);
|
||||
const auto attributes =
|
||||
FILE_FLAG_BACKUP_SEMANTICS | (directory ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL);
|
||||
const auto share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
auto handle = ::CreateFileA(&file_path[0], GENERIC_READ, share_mode, nullptr, OPEN_EXISTING,
|
||||
attributes, nullptr);
|
||||
FILE_BASIC_INFO fi{};
|
||||
::GetFileInformationByHandleEx(handle, FileBasicInfo, &fi, sizeof(fi));
|
||||
if (not directory) {
|
||||
utils::file::get_file_size(file_path, file_info.FileSize);
|
||||
}
|
||||
file_info.AllocationSize =
|
||||
directory ? 0
|
||||
: utils::divide_with_ceiling(file_info.FileSize, WINFSP_ALLOCATION_UNIT) *
|
||||
WINFSP_ALLOCATION_UNIT;
|
||||
file_info.FileAttributes = fi.FileAttributes;
|
||||
file_info.ChangeTime = fi.ChangeTime.QuadPart;
|
||||
file_info.CreationTime = fi.CreationTime.QuadPart;
|
||||
file_info.LastAccessTime = fi.LastAccessTime.QuadPart;
|
||||
file_info.LastWriteTime = fi.LastWriteTime.QuadPart;
|
||||
::CloseHandle(handle);
|
||||
return api_error::success;
|
||||
}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // _WIN32
|
||||
#endif // TESTS_MOCKS_MOCK_WINFSP_DRIVE_HPP_
|
37
tests/packet_test.cpp
Normal file
37
tests/packet_test.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "comm/packet/packet.hpp"
|
||||
|
||||
namespace repertory {
|
||||
TEST(packet, encrypt_and_decrypt) {
|
||||
packet packet;
|
||||
packet.encode("test");
|
||||
packet.encrypt("moose");
|
||||
|
||||
std::uint32_t size{};
|
||||
packet.decode(size);
|
||||
EXPECT_EQ(0, packet.decrypt("moose"));
|
||||
|
||||
std::string data;
|
||||
packet.decode(data);
|
||||
|
||||
EXPECT_STREQ("test", &data[0]);
|
||||
}
|
||||
} // namespace repertory
|
129
tests/path_utils_test.cpp
Normal file
129
tests/path_utils_test.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "utils/path_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
TEST(path_utils, combine) {
|
||||
auto s = utils::path::combine(R"(\test\path)", {});
|
||||
|
||||
#ifdef _WIN32
|
||||
EXPECT_STREQ(R"(\test\path)", s.c_str());
|
||||
#else
|
||||
EXPECT_STREQ("/test/path", s.c_str());
|
||||
#endif
|
||||
|
||||
s = utils::path::combine(R"(\test)", {R"(\path)"});
|
||||
#ifdef _WIN32
|
||||
EXPECT_STREQ(R"(\test\path)", s.c_str());
|
||||
#else
|
||||
EXPECT_STREQ("/test/path", s.c_str());
|
||||
#endif
|
||||
|
||||
s = utils::path::combine(R"(\test)", {R"(\path)", R"(\again\)"});
|
||||
#ifdef _WIN32
|
||||
EXPECT_STREQ(R"(\test\path\again)", s.c_str());
|
||||
#else
|
||||
EXPECT_STREQ("/test/path/again", s.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(path_utils, create_api_path) {
|
||||
auto s = utils::path::create_api_path("");
|
||||
EXPECT_STREQ("/", s.c_str());
|
||||
|
||||
s = utils::path::create_api_path(R"(\)");
|
||||
EXPECT_STREQ("/", s.c_str());
|
||||
|
||||
s = utils::path::create_api_path("/");
|
||||
EXPECT_STREQ("/", s.c_str());
|
||||
|
||||
s = utils::path::create_api_path(".");
|
||||
EXPECT_STREQ("/", s.c_str());
|
||||
|
||||
s = utils::path::create_api_path(R"(\\)");
|
||||
EXPECT_STREQ("/", s.c_str());
|
||||
|
||||
s = utils::path::create_api_path("//");
|
||||
EXPECT_STREQ("/", s.c_str());
|
||||
|
||||
s = utils::path::create_api_path("/cow///moose/////dog/chicken");
|
||||
EXPECT_STREQ("/cow/moose/dog/chicken", s.c_str());
|
||||
|
||||
s = utils::path::create_api_path("\\cow\\\\\\moose\\\\\\\\dog\\chicken/");
|
||||
EXPECT_STREQ("/cow/moose/dog/chicken/", s.c_str());
|
||||
|
||||
s = utils::path::create_api_path("/cow\\\\/moose\\\\/\\dog\\chicken\\");
|
||||
EXPECT_STREQ("/cow/moose/dog/chicken/", s.c_str());
|
||||
}
|
||||
|
||||
TEST(path_utils, finalize) {
|
||||
auto s = utils::path::finalize("");
|
||||
EXPECT_STREQ("", s.c_str());
|
||||
|
||||
s = utils::path::finalize(R"(\)");
|
||||
#ifdef _WIN32
|
||||
EXPECT_STREQ(R"(\)", s.c_str());
|
||||
#else
|
||||
EXPECT_STREQ("/", s.c_str());
|
||||
#endif
|
||||
|
||||
s = utils::path::finalize("/");
|
||||
#ifdef _WIN32
|
||||
EXPECT_STREQ(R"(\)", s.c_str());
|
||||
#else
|
||||
EXPECT_STREQ("/", s.c_str());
|
||||
#endif
|
||||
|
||||
s = utils::path::finalize(R"(\\)");
|
||||
#ifdef _WIN32
|
||||
EXPECT_STREQ(R"(\)", s.c_str());
|
||||
#else
|
||||
EXPECT_STREQ("/", s.c_str());
|
||||
#endif
|
||||
|
||||
s = utils::path::finalize("//");
|
||||
#ifdef _WIN32
|
||||
EXPECT_STREQ(R"(\)", s.c_str());
|
||||
#else
|
||||
EXPECT_STREQ("/", s.c_str());
|
||||
#endif
|
||||
|
||||
s = utils::path::finalize("/cow///moose/////dog/chicken");
|
||||
#ifdef _WIN32
|
||||
EXPECT_STREQ(R"(\cow\moose\dog\chicken)", s.c_str());
|
||||
#else
|
||||
EXPECT_STREQ("/cow/moose/dog/chicken", s.c_str());
|
||||
#endif
|
||||
|
||||
s = utils::path::finalize("\\cow\\\\\\moose\\\\\\\\dog\\chicken/");
|
||||
#ifdef _WIN32
|
||||
EXPECT_STREQ(R"(\cow\moose\dog\chicken)", s.c_str());
|
||||
#else
|
||||
EXPECT_STREQ("/cow/moose/dog/chicken", s.c_str());
|
||||
#endif
|
||||
|
||||
s = utils::path::finalize("/cow\\\\/moose\\\\/\\dog\\chicken\\");
|
||||
#ifdef _WIN32
|
||||
EXPECT_STREQ(R"(\cow\moose\dog\chicken)", s.c_str());
|
||||
#else
|
||||
EXPECT_STREQ("/cow/moose/dog/chicken", s.c_str());
|
||||
#endif
|
||||
}
|
||||
} // namespace repertory
|
917
tests/remote_fuse_test.cpp
Normal file
917
tests/remote_fuse_test.cpp
Normal file
@ -0,0 +1,917 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOT_IMPLEMENTED STATUS_NOT_IMPLEMENTED
|
||||
#include "drives/winfsp/i_winfsp_drive.hpp"
|
||||
#include "drives/winfsp/remotewinfsp/remote_server.hpp"
|
||||
#include "mocks/mock_winfsp_drive.hpp"
|
||||
#else
|
||||
#define NOT_IMPLEMENTED -ENOTSUP
|
||||
#include "drives/fuse/i_fuse_drive.hpp"
|
||||
#include "drives/fuse/remotefuse/remote_server.hpp"
|
||||
#include "mocks/mock_fuse_drive.hpp"
|
||||
#endif
|
||||
#include "drives/fuse/remotefuse/remote_client.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
using namespace repertory;
|
||||
#ifdef _WIN32
|
||||
using namespace repertory::remote_winfsp;
|
||||
#else
|
||||
using namespace repertory::remote_fuse;
|
||||
#endif
|
||||
namespace fuse_test {
|
||||
static std::string mount_location_;
|
||||
|
||||
static void access_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_access.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
EXPECT_EQ(0, client.fuse_access(api_path.c_str(), 0));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void create_and_release_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_create_release.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void chflags_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_chflags.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
#ifdef __APPLE__
|
||||
EXPECT_EQ(0, client.fuse_chflags(api_path.c_str(), 0));
|
||||
|
||||
#else
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_chflags(api_path.c_str(), 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void chmod_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_chmod.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
#ifdef _WIN32
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_chmod(api_path.c_str(), 0));
|
||||
#else
|
||||
EXPECT_EQ(0, client.fuse_chmod(api_path.c_str(), S_IRUSR | S_IWUSR));
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void chown_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_chown.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
#ifdef _WIN32
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_chown(api_path.c_str(), 0, 0));
|
||||
#else
|
||||
if (getuid() == 0) {
|
||||
EXPECT_EQ(0, client.fuse_chown(api_path.c_str(), 0, 0));
|
||||
} else {
|
||||
EXPECT_EQ(-EPERM, client.fuse_chown(api_path.c_str(), 0, 0));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void destroy_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_destroy());
|
||||
}
|
||||
|
||||
/*static void fallocate_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_fallocate.txt");
|
||||
const auto api_path = test_file.substr(mountLocation_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::Create | remote::open_flags::ReadWrite, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_fallocate(api_path.c_str(), 0, 0, 100, handle));
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
std::uint64_t file_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(test_file, file_size));
|
||||
EXPECT_EQ(100, file_size);
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}*/
|
||||
|
||||
static void fgetattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_fgetattr.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_ftruncate(api_path.c_str(), 100, handle));
|
||||
client.set_fuse_uid_gid(10, 11);
|
||||
|
||||
bool directory;
|
||||
remote::stat st{};
|
||||
EXPECT_EQ(0, client.fuse_fgetattr(api_path.c_str(), st, directory, handle));
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
EXPECT_FALSE(directory);
|
||||
#ifdef _WIN32
|
||||
struct _stat64 st1 {};
|
||||
_stat64(&test_file[0], &st1);
|
||||
#else
|
||||
struct stat st1 {};
|
||||
stat(&test_file[0], &st1);
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(11, st.st_gid);
|
||||
EXPECT_EQ(10, st.st_uid);
|
||||
EXPECT_EQ(st1.st_size, st.st_size);
|
||||
EXPECT_EQ(st1.st_nlink, st.st_nlink);
|
||||
EXPECT_EQ(st1.st_mode, st.st_mode);
|
||||
EXPECT_LE(static_cast<remote::file_time>(st1.st_atime), st.st_atimespec / NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_mtime), st.st_mtimespec / NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_ctime), st.st_ctimespec / NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_ctime), st.st_birthtimespec / NANOS_PER_SECOND);
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void fsetattr_x_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_fsetattr_x.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
remote::setattr_x attr{};
|
||||
#ifdef __APPLE__
|
||||
EXPECT_EQ(0, client.fuse_fsetattr_x(api_path.c_str(), attr, handle));
|
||||
#else
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_fsetattr_x(api_path.c_str(), attr, handle));
|
||||
#endif
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void fsync_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_fsync.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_fsync(api_path.c_str(), 0, handle));
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void ftruncate_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_ftruncate.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_ftruncate(api_path.c_str(), 100, handle));
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
std::uint64_t file_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(test_file, file_size));
|
||||
EXPECT_EQ(100, file_size);
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void getattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_getattr.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_ftruncate(api_path.c_str(), 100, handle));
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
client.set_fuse_uid_gid(10, 11);
|
||||
|
||||
bool directory;
|
||||
remote::stat st{};
|
||||
EXPECT_EQ(0, client.fuse_getattr(api_path.c_str(), st, directory));
|
||||
EXPECT_FALSE(directory);
|
||||
#ifdef _WIN32
|
||||
struct _stat64 st1 {};
|
||||
_stat64(&test_file[0], &st1);
|
||||
#else
|
||||
struct stat st1 {};
|
||||
stat(&test_file[0], &st1);
|
||||
#endif
|
||||
EXPECT_EQ(11, st.st_gid);
|
||||
EXPECT_EQ(10, st.st_uid);
|
||||
EXPECT_EQ(st1.st_size, st.st_size);
|
||||
EXPECT_EQ(st1.st_nlink, st.st_nlink);
|
||||
EXPECT_EQ(st1.st_mode, st.st_mode);
|
||||
EXPECT_LE(static_cast<remote::file_time>(st1.st_atime), st.st_atimespec / NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_mtime), st.st_mtimespec / NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_ctime), st.st_ctimespec / NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_ctime), st.st_birthtimespec / NANOS_PER_SECOND);
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
/*static void getxattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_getxattr.txt");
|
||||
const auto api_path = test_file.substr(mountLocation_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::Create | remote::open_flags::ReadWrite, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
#if _WIN32 || !HAS_SETXATTR || __APPLE__
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_getxattr(api_path.c_str(), "test", nullptr, 0));
|
||||
#else
|
||||
EXPECT_EQ(-EACCES, client.fuse_getxattr(api_path.c_str(), "test", nullptr, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void getxattr_osx_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_getxattr_osx.txt");
|
||||
const auto api_path = test_file.substr(mountLocation_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::Create | remote::open_flags::ReadWrite, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
EXPECT_EQ(NOT_IMPLEMENTED,
|
||||
client.fuse_getxattrOSX(api_path.c_str(), "test", nullptr, 0, 0));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}*/
|
||||
|
||||
static void getxtimes_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_getxtimes.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
remote::file_time bkuptime = 0;
|
||||
remote::file_time crtime = 0;
|
||||
#ifdef __APPLE__
|
||||
EXPECT_EQ(0, client.fuse_getxtimes(api_path.c_str(), bkuptime, crtime));
|
||||
#else
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_getxtimes(api_path.c_str(), bkuptime, crtime));
|
||||
#endif
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void init_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_init());
|
||||
}
|
||||
|
||||
/*static void listxattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_listxattr.txt");
|
||||
const auto api_path = test_file.substr(mountLocation_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::Create | remote::open_flags::ReadWrite, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
#if _WIN32 || !HAS_SETXATTR
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_listxattr(api_path.c_str(), nullptr, 0));
|
||||
#else
|
||||
EXPECT_EQ(-EIO, client.fuse_listxattr(api_path.c_str(), nullptr, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}*/
|
||||
|
||||
static void mkdir_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_directory = utils::path::absolute("./fuse_remote/fuse_remote_mkdir");
|
||||
const auto api_path = test_directory.substr(mount_location_.size());
|
||||
utils::file::delete_directory(test_directory);
|
||||
|
||||
#ifdef _WIN32
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), 0));
|
||||
#else
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), S_IRWXU));
|
||||
#endif
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
|
||||
utils::file::delete_directory(test_directory);
|
||||
}
|
||||
|
||||
static void open_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_open.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
#ifdef _WIN32
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
#else
|
||||
const auto ret =
|
||||
client.fuse_create(api_path.c_str(), S_IRWXU,
|
||||
remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
#endif
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
remote::file_handle handle2;
|
||||
EXPECT_EQ(0, client.fuse_open(api_path.c_str(), remote::open_flags::read_write, handle2));
|
||||
EXPECT_NE(handle, handle2);
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle2));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void opendir_and_releasedir_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_directory = utils::path::absolute("./fuse_remote/fuse_remote_opendir");
|
||||
const auto api_path = test_directory.substr(mount_location_.size());
|
||||
utils::file::delete_directory(test_directory);
|
||||
|
||||
#ifdef _WIN32
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), 0));
|
||||
#else
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), S_IRWXU));
|
||||
#endif
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
|
||||
remote::file_handle handle = 0;
|
||||
EXPECT_EQ(0, client.fuse_opendir(api_path.c_str(), handle));
|
||||
EXPECT_EQ(0, client.fuse_releasedir(api_path.c_str(), handle));
|
||||
|
||||
utils::file::delete_directory(test_directory);
|
||||
}
|
||||
|
||||
static void read_and_write_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_read_write.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(10, client.fuse_write(api_path.c_str(), "1234567890", 10, 0, handle));
|
||||
std::vector<char> buffer(10);
|
||||
EXPECT_EQ(10, client.fuse_read(api_path.c_str(), &buffer[0], 10, 0, handle));
|
||||
EXPECT_EQ(0, memcmp("1234567890", &buffer[0], 10));
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void read_and_write_base64_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_read_write_base64.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
const auto data = macaron::Base64::Encode("1234567890");
|
||||
EXPECT_EQ(10, client.fuse_write_base64(api_path.c_str(), &data[0], data.size(), 0, handle));
|
||||
std::vector<char> buffer(10);
|
||||
EXPECT_EQ(10, client.fuse_read(api_path.c_str(), &buffer[0], 10, 0, handle));
|
||||
EXPECT_EQ(0, memcmp("1234567890", &buffer[0], 10));
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void readdir_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_directory = utils::path::absolute("./fuse_remote/fuse_remote_readdir");
|
||||
const auto api_path = test_directory.substr(mount_location_.size());
|
||||
utils::file::delete_directory(test_directory);
|
||||
|
||||
#ifdef _WIN32
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), 0));
|
||||
#else
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), S_IRWXU));
|
||||
#endif
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
|
||||
remote::file_handle handle = 0;
|
||||
EXPECT_EQ(0, client.fuse_opendir(api_path.c_str(), handle));
|
||||
|
||||
std::string item_path;
|
||||
EXPECT_EQ(0, client.fuse_readdir(api_path.c_str(), 0, handle, item_path));
|
||||
EXPECT_STREQ(".", item_path.c_str());
|
||||
|
||||
EXPECT_EQ(0, client.fuse_readdir(api_path.c_str(), 1, handle, item_path));
|
||||
EXPECT_STREQ("..", item_path.c_str());
|
||||
|
||||
EXPECT_EQ(0, client.fuse_releasedir(api_path.c_str(), handle));
|
||||
|
||||
utils::file::delete_directory(test_directory);
|
||||
}
|
||||
|
||||
/*static void removexattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_removexattr.txt");
|
||||
const auto api_path = test_file.substr(mountLocation_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::Create | remote::open_flags::ReadWrite, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
#if _WIN32 || !HAS_SETXATTR
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_removexattr(api_path.c_str(), "test"));
|
||||
#else
|
||||
EXPECT_EQ(-EACCES, client.fuse_removexattr(api_path.c_str(), "test"));
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}*/
|
||||
|
||||
static void rename_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_rename.txt");
|
||||
const auto renamed_test_file = utils::path::absolute("./fuse_remote/fuse_remote_rename2.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
const auto renamed_api_path = renamed_test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
utils::file::delete_file(renamed_test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
#ifdef _WIN32
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
#else
|
||||
const auto ret =
|
||||
client.fuse_create(api_path.c_str(), S_IRWXU,
|
||||
remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
EXPECT_EQ(0, client.fuse_rename(api_path.c_str(), renamed_api_path.c_str()));
|
||||
EXPECT_FALSE(utils::file::is_file(test_file));
|
||||
EXPECT_TRUE(utils::file::is_file(renamed_test_file));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
utils::file::delete_file(renamed_test_file);
|
||||
}
|
||||
|
||||
static void rmdir_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_directory = utils::path::absolute("./fuse_remote/fuse_remote_rmdir");
|
||||
const auto api_path = test_directory.substr(mount_location_.size());
|
||||
utils::file::delete_directory(test_directory);
|
||||
|
||||
#ifdef _WIN32
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), 0));
|
||||
#else
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), S_IRWXU));
|
||||
#endif
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
|
||||
EXPECT_EQ(0, client.fuse_rmdir(api_path.c_str()));
|
||||
EXPECT_FALSE(utils::file::is_directory(test_directory));
|
||||
|
||||
utils::file::delete_directory(test_directory);
|
||||
}
|
||||
|
||||
static void setattr_x_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_setattr_x.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
remote::setattr_x attr{};
|
||||
#ifdef __APPLE__
|
||||
EXPECT_EQ(0, client.fuse_setattr_x(api_path.c_str(), attr));
|
||||
#else
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_setattr_x(api_path.c_str(), attr));
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void setbkuptime_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_setbkuptime.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
remote::file_time ts = 0;
|
||||
#ifdef __APPLE__
|
||||
EXPECT_EQ(0, client.fuse_setbkuptime(api_path.c_str(), ts));
|
||||
#else
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_setbkuptime(api_path.c_str(), ts));
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void setchgtime_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_setchgtime.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
remote::file_time ts = 0;
|
||||
#ifdef __APPLE__
|
||||
EXPECT_EQ(0, client.fuse_setchgtime(api_path.c_str(), ts));
|
||||
#else
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_setchgtime(api_path.c_str(), ts));
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void setcrtime_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_setcrtime.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
remote::file_time ts = 0;
|
||||
#ifdef __APPLE__
|
||||
EXPECT_EQ(0, client.fuse_setcrtime(api_path.c_str(), ts));
|
||||
#else
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_setcrtime(api_path.c_str(), ts));
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void setvolname_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_setvolname("moose"));
|
||||
}
|
||||
|
||||
/*static void setxattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_setxattr.txt");
|
||||
const auto api_path = test_file.substr(mountLocation_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::Create | remote::open_flags::ReadWrite, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
#if _WIN32 || !HAS_SETXATTR
|
||||
EXPECT_EQ(NOT_IMPLEMENTED,
|
||||
client.fuse_setxattr(api_path.c_str(), "test", "moose", 5, 0));
|
||||
#else
|
||||
EXPECT_EQ(-EACCES, client.fuse_setxattr(api_path.c_str(), "test", "moose", 5, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void setxattr_osx_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_setxattr_osx.txt");
|
||||
const auto api_path = test_file.substr(mountLocation_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::Create | remote::open_flags::ReadWrite, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
EXPECT_EQ(NOT_IMPLEMENTED,
|
||||
client.fuse_setxattr_osx(api_path.c_str(), "test", "moose", 5, 0, 0));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}*/
|
||||
|
||||
#ifdef _WIN32
|
||||
static void test_statfs(repertory::remote_fuse::remote_client &client,
|
||||
const i_winfsp_drive &drive) {
|
||||
#else
|
||||
static void test_statfs(repertory::remote_fuse::remote_client &client, const i_fuse_drive &drive) {
|
||||
#endif
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
|
||||
remote::statfs st{};
|
||||
EXPECT_EQ(0, client.fuse_statfs(api_path.c_str(), 4096, st));
|
||||
|
||||
const auto total_bytes = drive.get_total_drive_space();
|
||||
const auto total_used = drive.get_used_drive_space();
|
||||
const auto used_blocks = utils::divide_with_ceiling(total_used, static_cast<std::uint64_t>(4096));
|
||||
EXPECT_EQ(utils::divide_with_ceiling(total_bytes, static_cast<std::uint64_t>(4096)), st.f_blocks);
|
||||
EXPECT_EQ(st.f_blocks ? (st.f_blocks - used_blocks) : 0, st.f_bavail);
|
||||
EXPECT_EQ(st.f_bavail, st.f_bfree);
|
||||
EXPECT_EQ(4294967295, st.f_files);
|
||||
EXPECT_EQ(4294967295 - drive.get_total_item_count(), st.f_favail);
|
||||
EXPECT_EQ(st.f_favail, st.f_ffree);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void statfs_x_test(repertory::remote_fuse::remote_client &client,
|
||||
const i_winfsp_drive &drive) {
|
||||
#else
|
||||
|
||||
static void statfs_x_test(repertory::remote_fuse::remote_client &client,
|
||||
const i_fuse_drive &drive) {
|
||||
#endif
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
|
||||
remote::statfs_x st{};
|
||||
EXPECT_EQ(0, client.fuse_statfs_x(api_path.c_str(), 4096, st));
|
||||
EXPECT_STREQ(&st.f_mntfromname[0], utils::create_volume_label(provider_type::remote).c_str());
|
||||
|
||||
const auto total_bytes = drive.get_total_drive_space();
|
||||
const auto total_used = drive.get_used_drive_space();
|
||||
const auto used_blocks = utils::divide_with_ceiling(total_used, static_cast<std::uint64_t>(4096));
|
||||
EXPECT_EQ(utils::divide_with_ceiling(total_bytes, static_cast<std::uint64_t>(4096)), st.f_blocks);
|
||||
EXPECT_EQ(st.f_blocks ? (st.f_blocks - used_blocks) : 0, st.f_bavail);
|
||||
EXPECT_EQ(st.f_bavail, st.f_bfree);
|
||||
EXPECT_EQ(4294967295, st.f_files);
|
||||
EXPECT_EQ(4294967295 - drive.get_total_item_count(), st.f_favail);
|
||||
EXPECT_EQ(st.f_favail, st.f_ffree);
|
||||
}
|
||||
|
||||
static void truncate_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_truncate.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
#ifdef _WIN32
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
#else
|
||||
const auto ret =
|
||||
client.fuse_create(api_path.c_str(), S_IRWXU,
|
||||
remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
#endif
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
EXPECT_EQ(0, client.fuse_truncate(api_path.c_str(), 100));
|
||||
|
||||
std::uint64_t file_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(test_file, file_size));
|
||||
EXPECT_EQ(100, file_size);
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void unlink_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_unlink.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
EXPECT_EQ(0, client.fuse_unlink(api_path.c_str()));
|
||||
EXPECT_FALSE(utils::file::is_file(test_file));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void utimens_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./fuse_remote/fuse_remote_utimens.txt");
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
utils::file::delete_file(test_file);
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
api_path.c_str(), 0, remote::open_flags::create | remote::open_flags::read_write, handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
remote::file_time tv[2] = {0};
|
||||
EXPECT_EQ(0, client.fuse_utimens(api_path.c_str(), tv, 0, 0));
|
||||
}
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
TEST(remote_fuse, all_tests) {
|
||||
std::uint16_t port = 0u;
|
||||
const auto found_port = utils::get_next_available_port(20000u, port);
|
||||
EXPECT_TRUE(found_port);
|
||||
if (found_port) {
|
||||
console_consumer c;
|
||||
|
||||
app_config config(provider_type::remote, "./fuse_remote");
|
||||
config.set_remote_host_name_or_ip("localhost");
|
||||
config.set_remote_port(port);
|
||||
config.set_remote_token("testtoken");
|
||||
config.set_enable_drive_events(true);
|
||||
config.set_event_level(event_level::verbose);
|
||||
|
||||
event_system::instance().start();
|
||||
#ifdef _WIN32
|
||||
mount_location_ = std::string(__FILE__).substr(0, 2);
|
||||
mock_winfsp_drive drive(mount_location_);
|
||||
remote_server server(config, drive, mount_location_);
|
||||
#else
|
||||
mount_location_ = utils::path::absolute(".");
|
||||
mock_fuse_drive drive(mount_location_);
|
||||
remote_server server(config, drive, mount_location_);
|
||||
#endif
|
||||
std::thread([&]() {
|
||||
repertory::remote_fuse::remote_client client(config);
|
||||
|
||||
create_and_release_test(client);
|
||||
access_test(client);
|
||||
chflags_test(client);
|
||||
chmod_test(client);
|
||||
chown_test(client);
|
||||
destroy_test(client);
|
||||
fgetattr_test(client);
|
||||
fsetattr_x_test(client);
|
||||
fsync_test(client);
|
||||
ftruncate_test(client);
|
||||
getattr_test(client);
|
||||
getxtimes_test(client);
|
||||
init_test(client);
|
||||
mkdir_test(client);
|
||||
open_test(client);
|
||||
opendir_and_releasedir_test(client);
|
||||
read_and_write_base64_test(client);
|
||||
read_and_write_test(client);
|
||||
readdir_test(client);
|
||||
rename_test(client);
|
||||
rmdir_test(client);
|
||||
setattr_x_test(client);
|
||||
setbkuptime_test(client);
|
||||
setchgtime_test(client);
|
||||
setcrtime_test(client);
|
||||
setvolname_test(client);
|
||||
statfs_x_test(client, drive);
|
||||
test_statfs(client, drive);
|
||||
truncate_test(client);
|
||||
unlink_test(client);
|
||||
utimens_test(client);
|
||||
// fallocate_test(client);
|
||||
// getxattr_osx_test(client);
|
||||
// getxattr_test(client);
|
||||
// listxattr_test(client);
|
||||
// removexattr_test(client);
|
||||
// setxattr_osx_test(client);
|
||||
// setxattr_test(client);
|
||||
}).join();
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
utils::file::delete_directory_recursively("./fuse_remote");
|
||||
}
|
||||
} // namespace fuse_test
|
492
tests/remote_winfsp_test.cpp
Normal file
492
tests/remote_winfsp_test.cpp
Normal file
@ -0,0 +1,492 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "drives/winfsp/i_winfsp_drive.hpp"
|
||||
#include "drives/winfsp/remotewinfsp/remote_client.hpp"
|
||||
#include "events/consumers/console_consumer.hpp"
|
||||
#include "test_common.hpp"
|
||||
#ifdef _WIN32
|
||||
#include "drives/winfsp/remotewinfsp/remote_server.hpp"
|
||||
#include "mocks/mock_winfsp_drive.hpp"
|
||||
#else
|
||||
#include "drives/fuse/remotefuse/remote_server.hpp"
|
||||
#include "mocks/mock_fuse_drive.hpp"
|
||||
#endif
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
using namespace repertory;
|
||||
using namespace repertory::remote_winfsp;
|
||||
|
||||
namespace winfsp_test {
|
||||
static std::string mount_location_;
|
||||
|
||||
static void can_delete_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/candelete.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
native_file::native_file_ptr nf;
|
||||
native_file::create_or_open(test_file, nf);
|
||||
EXPECT_TRUE(nf);
|
||||
if (nf) {
|
||||
EXPECT_EQ(STATUS_INVALID_HANDLE,
|
||||
client.winfsp_can_delete(reinterpret_cast<PVOID>(nf->get_handle()), &api_path[0]));
|
||||
|
||||
nf->close();
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
}
|
||||
|
||||
static void create_and_close_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/create.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
const auto ret =
|
||||
client.winfsp_create(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, 0,
|
||||
&file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void cleanup_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/cleanup.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, 0,
|
||||
&file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
BOOLEAN was_closed = 0;
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_cleanup(file_desc, &api_path[0], 0, was_closed));
|
||||
EXPECT_FALSE(was_closed);
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void flush_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/flush.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, 0,
|
||||
&file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_flush(file_desc, &fi));
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void get_file_info_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/getfileinfo.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, 0,
|
||||
&file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_get_file_info(file_desc, &fi));
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void get_security_by_name_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/getsecuritybyname.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, 0,
|
||||
&file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
UINT32 attributes = 0;
|
||||
std::uint64_t securityDescriptorSize = 1024;
|
||||
std::wstring strDescriptor;
|
||||
ret = client.winfsp_get_security_by_name(&api_path[0], &attributes, &securityDescriptorSize,
|
||||
strDescriptor);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
EXPECT_EQ(FILE_ATTRIBUTE_NORMAL, attributes);
|
||||
EXPECT_FALSE(strDescriptor.empty());
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void get_volume_info_test(remote_client &client) {
|
||||
UINT64 total_size = 0u;
|
||||
UINT64 free_size = 0u;
|
||||
std::string volume_label;
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_get_volume_info(total_size, free_size, volume_label));
|
||||
EXPECT_EQ(100, free_size);
|
||||
EXPECT_EQ(200, total_size);
|
||||
EXPECT_STREQ(&volume_label[0], "TestVolumeLabel");
|
||||
}
|
||||
|
||||
static void mounted_test(remote_client &client) {
|
||||
const auto location = utils::string::from_utf8(mount_location_);
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_mounted(location));
|
||||
}
|
||||
|
||||
static void open_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/open.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
PVOID file_desc2 = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
{
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL,
|
||||
0, &file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
}
|
||||
{
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
const auto ret = client.winfsp_open(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, &file_desc2,
|
||||
&fi, normalized_name);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
}
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc2));
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void overwrite_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/overwrite.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, 0,
|
||||
&file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
const UINT32 attributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE;
|
||||
const BOOLEAN replace_attributes = 0;
|
||||
const UINT64 allocation_size = 0;
|
||||
ret = client.winfsp_overwrite(file_desc, attributes, replace_attributes, allocation_size, &fi);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
EXPECT_EQ(0, fi.FileSize);
|
||||
EXPECT_EQ(attributes, fi.FileAttributes);
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void create_and_read_directory_test(remote_client &client) {
|
||||
const auto test_directory = utils::path::absolute("./win_remote/readdirectory");
|
||||
utils::file::delete_directory(test_directory);
|
||||
auto api_path = utils::string::from_utf8(test_directory).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], FILE_DIRECTORY_FILE, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_ATTRIBUTE_DIRECTORY, 0, &file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
|
||||
json list;
|
||||
ret = client.winfsp_read_directory(file_desc, nullptr, nullptr, list);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
EXPECT_EQ(2, list.size());
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
utils::file::delete_directory(test_directory);
|
||||
}
|
||||
|
||||
static void open_and_read_directory_test(remote_client &client) {
|
||||
const auto test_directory = utils::path::absolute("./win_remote/openreaddirectory");
|
||||
utils::file::delete_directory(test_directory);
|
||||
auto api_path = utils::string::from_utf8(test_directory).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], FILE_DIRECTORY_FILE, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_ATTRIBUTE_DIRECTORY, 0, &file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
|
||||
file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
ret = client.winfsp_open(&api_path[0], FILE_DIRECTORY_FILE, GENERIC_READ | GENERIC_WRITE,
|
||||
&file_desc, &fi, normalized_name);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
json item_list;
|
||||
ret = client.winfsp_read_directory(file_desc, nullptr, nullptr, item_list);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
EXPECT_EQ(2, item_list.size());
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
utils::file::delete_directory(test_directory);
|
||||
}
|
||||
|
||||
static void read_and_write_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/readwrite.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, 0,
|
||||
&file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
std::vector<char> buffer;
|
||||
buffer.emplace_back('T');
|
||||
buffer.emplace_back('e');
|
||||
buffer.emplace_back('s');
|
||||
buffer.emplace_back('t');
|
||||
UINT32 bytes_transferred = 0;
|
||||
ret = client.winfsp_write(file_desc, &buffer[0], 0, static_cast<UINT32>(buffer.size()), 0, 0,
|
||||
&bytes_transferred, &fi);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
EXPECT_EQ(buffer.size(), bytes_transferred);
|
||||
|
||||
std::vector<char> buffer2(buffer.size());
|
||||
UINT32 bytes_transferred2 = 0;
|
||||
ret = client.winfsp_read(file_desc, &buffer2[0], 0, static_cast<UINT32>(buffer2.size()),
|
||||
&bytes_transferred2);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
EXPECT_EQ(bytes_transferred, bytes_transferred2);
|
||||
EXPECT_EQ(0, memcmp(&buffer[0], &buffer2[0], buffer.size()));
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void rename_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/rename.txt");
|
||||
const auto test_file2 = utils::path::absolute("./win_remote/rename2.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
utils::file::delete_file(test_file2);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
auto api_path2 = utils::string::from_utf8(test_file2).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, 0,
|
||||
&file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
ret = client.winfsp_rename(file_desc, &api_path[0], &api_path2[0], 0);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
EXPECT_TRUE(utils::file::is_file(test_file2));
|
||||
EXPECT_FALSE(utils::file::is_file(test_file));
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
utils::file::delete_file(test_file2);
|
||||
}
|
||||
|
||||
static void set_basic_info_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/setbasicinfo.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
utils::file::delete_file(test_file);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, 0,
|
||||
&file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
const auto attributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE;
|
||||
#ifdef _WIN32
|
||||
SYSTEMTIME st{};
|
||||
::GetSystemTime(&st);
|
||||
|
||||
LARGE_INTEGER ft{};
|
||||
::SystemTimeToFileTime(&st, reinterpret_cast<FILETIME *>(&ft));
|
||||
|
||||
const auto creation_time = ft.QuadPart;
|
||||
const auto last_access_time = ft.QuadPart + 1;
|
||||
const auto last_write_time = ft.QuadPart + 2;
|
||||
const auto change_time = last_write_time;
|
||||
#else
|
||||
const auto creation_time = utils::unix_time_to_windows_time(utils::get_time_now());
|
||||
const auto last_access_time = creation_time + 1;
|
||||
const auto last_write_time = creation_time + 2;
|
||||
const auto change_time = last_write_time;
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS,
|
||||
client.winfsp_set_basic_info(file_desc, attributes, creation_time, last_access_time,
|
||||
last_write_time, change_time, &fi));
|
||||
EXPECT_EQ(attributes, fi.FileAttributes);
|
||||
EXPECT_EQ(creation_time, fi.CreationTime);
|
||||
EXPECT_EQ(last_access_time, fi.LastAccessTime);
|
||||
EXPECT_EQ(last_write_time, fi.LastWriteTime);
|
||||
EXPECT_EQ(change_time, fi.ChangeTime);
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void set_file_size_test(remote_client &client) {
|
||||
const auto test_file = utils::path::absolute("./win_remote/setfilesize.txt");
|
||||
utils::file::delete_file(test_file);
|
||||
auto api_path = utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
PVOID file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
remote::file_info fi{};
|
||||
std::string normalized_name;
|
||||
BOOLEAN exists = 0;
|
||||
auto ret =
|
||||
client.winfsp_create(&api_path[0], 0, GENERIC_READ | GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, 0,
|
||||
&file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
const UINT64 new_file_size = 34;
|
||||
const BOOLEAN set_allocation_size = 0;
|
||||
EXPECT_EQ(STATUS_SUCCESS,
|
||||
client.winfsp_set_file_size(file_desc, new_file_size, set_allocation_size, &fi));
|
||||
|
||||
std::uint64_t file_size = 0;
|
||||
utils::file::get_file_size(test_file, file_size);
|
||||
EXPECT_EQ(34, file_size);
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
utils::file::delete_file(test_file);
|
||||
}
|
||||
|
||||
static void unmounted_test(remote_client &client) {
|
||||
const auto location = utils::string::from_utf8(mount_location_);
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_unmounted(location));
|
||||
}
|
||||
|
||||
TEST(remote_winfsp, all_tests) {
|
||||
std::uint16_t port = 0;
|
||||
const auto found_port = utils::get_next_available_port(20000u, port);
|
||||
EXPECT_TRUE(found_port);
|
||||
if (found_port) {
|
||||
console_consumer c;
|
||||
|
||||
app_config config(provider_type::remote, "./win_remote");
|
||||
config.set_remote_host_name_or_ip("localhost");
|
||||
config.set_remote_port(port);
|
||||
config.set_remote_token("testtoken");
|
||||
config.set_enable_drive_events(true);
|
||||
config.set_event_level(event_level::verbose);
|
||||
|
||||
event_system::instance().start();
|
||||
#ifdef _WIN32
|
||||
mount_location_ = std::string(__FILE__).substr(0, 2);
|
||||
mock_winfsp_drive drive(mount_location_);
|
||||
remote_server server(config, drive, mount_location_);
|
||||
#else
|
||||
mount_location_ = utils::path::absolute(".");
|
||||
mock_fuse_drive drive(mount_location_);
|
||||
remote_fuse::remote_server server(config, drive, mount_location_);
|
||||
#endif
|
||||
std::thread([&]() {
|
||||
remote_client client(config);
|
||||
|
||||
can_delete_test(client);
|
||||
cleanup_test(client);
|
||||
create_and_close_test(client);
|
||||
create_and_read_directory_test(client);
|
||||
flush_test(client);
|
||||
get_file_info_test(client);
|
||||
get_security_by_name_test(client);
|
||||
get_volume_info_test(client);
|
||||
mounted_test(client);
|
||||
open_and_read_directory_test(client);
|
||||
open_test(client);
|
||||
overwrite_test(client);
|
||||
read_and_write_test(client);
|
||||
rename_test(client);
|
||||
set_basic_info_test(client);
|
||||
set_file_size_test(client);
|
||||
unmounted_test(client);
|
||||
}).join();
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
utils::file::delete_directory_recursively("./win_remote");
|
||||
}
|
||||
} // namespace winfsp_test
|
126
tests/retry_db_test.cpp
Normal file
126
tests/retry_db_test.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "db/retry_db.hpp"
|
||||
#include "test_common.hpp"
|
||||
|
||||
namespace repertory {
|
||||
TEST(retry_db, exists_and_set) {
|
||||
const std::string data_directory = "./retrydb_exists_and_set";
|
||||
utils::file::delete_directory_recursively(data_directory);
|
||||
{
|
||||
app_config config(provider_type::sia, data_directory);
|
||||
retry_db db(config);
|
||||
|
||||
const auto api_path = "my_test/path.txt";
|
||||
|
||||
EXPECT_FALSE(db.exists(api_path));
|
||||
db.set(api_path);
|
||||
EXPECT_TRUE(db.exists(api_path));
|
||||
#ifdef _WIN32
|
||||
EXPECT_FALSE(db.exists(utils::string::to_upper(api_path)));
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(data_directory);
|
||||
}
|
||||
|
||||
TEST(retry_db, rename) {
|
||||
const std::string data_directory = "./retrydb_rename";
|
||||
utils::file::delete_directory_recursively(data_directory);
|
||||
{
|
||||
app_config config(provider_type::sia, data_directory);
|
||||
retry_db db(config);
|
||||
|
||||
const auto api_path = "my_test/path.txt";
|
||||
const auto api_path2 = "my_test/path2.txt";
|
||||
|
||||
db.set(api_path);
|
||||
db.rename(api_path, api_path2);
|
||||
EXPECT_FALSE(db.exists(api_path));
|
||||
EXPECT_TRUE(db.exists(api_path2));
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(data_directory);
|
||||
}
|
||||
|
||||
TEST(retry_db, remove) {
|
||||
const std::string data_directory = "./retrydb_remove";
|
||||
utils::file::delete_directory_recursively(data_directory);
|
||||
{
|
||||
app_config config(provider_type::sia, data_directory);
|
||||
retry_db db(config);
|
||||
|
||||
const auto api_path = "my_test/path.txt";
|
||||
|
||||
db.set(api_path);
|
||||
db.remove(api_path);
|
||||
EXPECT_FALSE(db.exists(api_path));
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(data_directory);
|
||||
}
|
||||
|
||||
TEST(retry_db, process_all) {
|
||||
const std::string data_directory = "./retrydb_process_all";
|
||||
utils::file::delete_directory_recursively(data_directory);
|
||||
{
|
||||
app_config config(provider_type::sia, data_directory);
|
||||
retry_db db(config);
|
||||
|
||||
const auto api_path = "my_test/path.txt";
|
||||
|
||||
for (auto i = 0; i < 10; i++) {
|
||||
db.set(api_path + std::to_string(i));
|
||||
}
|
||||
|
||||
std::vector<std::string> items;
|
||||
db.process_all([&items](const std::string &api_path) -> bool {
|
||||
items.emplace_back(api_path);
|
||||
return false;
|
||||
});
|
||||
EXPECT_EQ((std::size_t)10u, items.size());
|
||||
|
||||
for (auto i = 0; i < 10; i++) {
|
||||
EXPECT_TRUE(db.exists(api_path + std::to_string(i)));
|
||||
utils::remove_element_from(items, api_path + std::to_string(i));
|
||||
}
|
||||
EXPECT_TRUE(items.empty());
|
||||
|
||||
db.process_all([&items](const std::string &api_path) -> bool {
|
||||
items.emplace_back(api_path);
|
||||
return true;
|
||||
});
|
||||
EXPECT_EQ((std::size_t)10u, items.size());
|
||||
|
||||
for (auto i = 0; i < 10; i++) {
|
||||
EXPECT_FALSE(db.exists(api_path + std::to_string(i)));
|
||||
utils::remove_element_from(items, api_path + std::to_string(i));
|
||||
}
|
||||
EXPECT_TRUE(items.empty());
|
||||
|
||||
db.process_all([&items](const std::string &api_path) -> bool {
|
||||
items.emplace_back(api_path);
|
||||
return true;
|
||||
});
|
||||
EXPECT_TRUE(items.empty());
|
||||
}
|
||||
|
||||
utils::file::delete_directory_recursively(data_directory);
|
||||
}
|
||||
} // namespace repertory
|
803
tests/skynet_provider_test.cpp
Normal file
803
tests/skynet_provider_test.cpp
Normal file
@ -0,0 +1,803 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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.
|
||||
*/
|
||||
#if defined(REPERTORY_ENABLE_SKYNET)
|
||||
|
||||
#include "fixtures/skynet_provider_fixture.hpp"
|
||||
#include "utils/encrypting_reader.hpp"
|
||||
#include "utils/encryption.hpp"
|
||||
|
||||
#define EXTERNAL_SKYLINK "AACoqIuN00YdDhS21dUMpMYFYGDeGmPnGoNWOkItkmzLfw"
|
||||
|
||||
namespace repertory {
|
||||
static void populate_file_meta(const std::string &, api_meta_map &meta) {
|
||||
meta[META_ACCESSED] = std::to_string(utils::get_file_time_now());
|
||||
meta[META_MODIFIED] = std::to_string(utils::get_file_time_now());
|
||||
meta[META_CREATION] = std::to_string(utils::get_file_time_now());
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, create_directory_and_create_file) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_TRUE(provider_->is_directory("/"));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
EXPECT_TRUE(provider_->is_file("/test.txt"));
|
||||
EXPECT_TRUE(provider_->is_file_writeable("/test.txt"));
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, get_file) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_TRUE(provider_->is_directory("/"));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
EXPECT_TRUE(provider_->is_file("/test.txt"));
|
||||
|
||||
api_file apiFile{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_file("/test.txt", apiFile));
|
||||
|
||||
EXPECT_STREQ("/test.txt", apiFile.api_path.c_str());
|
||||
EXPECT_STREQ("/", apiFile.api_parent.c_str());
|
||||
EXPECT_EQ(utils::string::to_uint64(file_meta[META_ACCESSED]), apiFile.accessed_date);
|
||||
EXPECT_EQ(utils::string::to_uint64(file_meta[META_MODIFIED]), apiFile.changed_date);
|
||||
EXPECT_EQ(utils::string::to_uint64(file_meta[META_CREATION]), apiFile.created_date);
|
||||
EXPECT_EQ(0, apiFile.file_size);
|
||||
EXPECT_EQ(utils::string::to_uint64(file_meta[META_MODIFIED]), apiFile.modified_date);
|
||||
EXPECT_TRUE(apiFile.recoverable);
|
||||
EXPECT_EQ(3.0, apiFile.redundancy);
|
||||
EXPECT_TRUE(utils::file::is_file(apiFile.source_path));
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, get_directory_item_count) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/sub", directory_meta));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
|
||||
EXPECT_EQ(2, provider_->get_directory_item_count("/"));
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, get_directory_items) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/sub", directory_meta));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
|
||||
directory_item_list itemList;
|
||||
EXPECT_EQ(api_error::success, provider_->get_directory_items("/", itemList));
|
||||
EXPECT_EQ(std::size_t(4), itemList.size());
|
||||
|
||||
EXPECT_STREQ("/sub", itemList[2u].api_path.c_str());
|
||||
EXPECT_STREQ("/", itemList[2u].api_parent.c_str());
|
||||
EXPECT_TRUE(itemList[2u].directory);
|
||||
EXPECT_EQ(0u, itemList[2u].size);
|
||||
// itemList[0].MetaMap;
|
||||
|
||||
EXPECT_STREQ("/test.txt", itemList[3u].api_path.c_str());
|
||||
EXPECT_STREQ("/", itemList[3u].api_parent.c_str());
|
||||
EXPECT_FALSE(itemList[3u].directory);
|
||||
EXPECT_EQ(0u, itemList[3u].size);
|
||||
// itemList[1].MetaMap;
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, get_file_list) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/sub", directory_meta));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
populate_file_meta("/test2.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test2.txt", file_meta));
|
||||
|
||||
api_file_list fileList;
|
||||
EXPECT_EQ(api_error::success, provider_->get_file_list(fileList));
|
||||
EXPECT_EQ(std::size_t(2), fileList.size());
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, get_fileSize) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
|
||||
std::uint64_t file_size = 100ull;
|
||||
EXPECT_EQ(api_error::success, provider_->get_file_size("/test.txt", file_size));
|
||||
EXPECT_EQ(std::uint64_t(0), file_size);
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, get_host_config) {
|
||||
auto hc = provider_->get_host_config(false);
|
||||
EXPECT_TRUE(hc.agent_string.empty());
|
||||
EXPECT_TRUE(hc.api_password.empty());
|
||||
EXPECT_EQ(hc.api_port, 443);
|
||||
EXPECT_STREQ(DEFAULT_SKYNET_URLS[0u].c_str(), hc.host_name_or_ip.c_str());
|
||||
EXPECT_STREQ("/", hc.path.c_str());
|
||||
EXPECT_STREQ("https", hc.protocol.c_str());
|
||||
EXPECT_STREQ(DEFAULT_SKYNET_URLS[1u].c_str(), hc.auth_url.c_str());
|
||||
|
||||
hc = provider_->get_host_config(true);
|
||||
EXPECT_TRUE(hc.agent_string.empty());
|
||||
EXPECT_TRUE(hc.api_password.empty());
|
||||
EXPECT_EQ(hc.api_port, 443);
|
||||
EXPECT_STREQ(DEFAULT_SKYNET_URLS[0u].c_str(), hc.host_name_or_ip.c_str());
|
||||
EXPECT_STREQ("/skynet/skyfile", hc.path.c_str());
|
||||
EXPECT_STREQ(DEFAULT_SKYNET_URLS[1u].c_str(), hc.auth_url.c_str());
|
||||
EXPECT_STREQ("https", hc.protocol.c_str());
|
||||
|
||||
const auto string_list = config_->get_value_by_name("SkynetConfig.PortalList");
|
||||
json list = json::parse(string_list);
|
||||
list[0u]["AuthUser"] = "test_user";
|
||||
list[0u]["AuthURL"] = "test_url";
|
||||
list[0u]["AuthPassword"] = "test_pwd";
|
||||
|
||||
config_->set_value_by_name("SkynetConfig.PortalList", list.dump());
|
||||
provider_->update_portal_list();
|
||||
|
||||
hc = provider_->get_host_config(false);
|
||||
EXPECT_TRUE(hc.agent_string.empty());
|
||||
EXPECT_TRUE(hc.api_password.empty());
|
||||
EXPECT_EQ(hc.api_port, 443);
|
||||
EXPECT_STREQ(DEFAULT_SKYNET_URLS[0u].c_str(), hc.host_name_or_ip.c_str());
|
||||
EXPECT_STREQ("/", hc.path.c_str());
|
||||
EXPECT_STREQ("https", hc.protocol.c_str());
|
||||
EXPECT_STREQ("test_user", hc.auth_user.c_str());
|
||||
EXPECT_STREQ("test_url", hc.auth_url.c_str());
|
||||
EXPECT_STREQ("test_pwd", hc.auth_password.c_str());
|
||||
|
||||
hc = provider_->get_host_config(true);
|
||||
EXPECT_TRUE(hc.agent_string.empty());
|
||||
EXPECT_TRUE(hc.api_password.empty());
|
||||
EXPECT_EQ(hc.api_port, 443);
|
||||
EXPECT_STREQ(DEFAULT_SKYNET_URLS[0u].c_str(), hc.host_name_or_ip.c_str());
|
||||
EXPECT_STREQ("/skynet/skyfile", hc.path.c_str());
|
||||
EXPECT_STREQ("https", hc.protocol.c_str());
|
||||
EXPECT_STREQ("test_user", hc.auth_user.c_str());
|
||||
EXPECT_STREQ("test_url", hc.auth_url.c_str());
|
||||
EXPECT_STREQ("test_pwd", hc.auth_password.c_str());
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, remove_directory) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/sub", directory_meta));
|
||||
EXPECT_TRUE(provider_->is_directory("/sub"));
|
||||
|
||||
EXPECT_EQ(api_error::success, provider_->remove_directory("/sub"));
|
||||
EXPECT_FALSE(provider_->is_directory("/sub"));
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, recreate_directory_after_remove_directory) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/sub", directory_meta));
|
||||
EXPECT_TRUE(provider_->is_directory("/sub"));
|
||||
|
||||
EXPECT_EQ(api_error::success, provider_->remove_directory("/sub"));
|
||||
EXPECT_FALSE(provider_->is_directory("/sub"));
|
||||
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/sub", directory_meta));
|
||||
EXPECT_TRUE(provider_->is_directory("/sub"));
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, remove_directory_fails_if_sub_directories_exist) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/sub", directory_meta));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/sub/sub2", directory_meta));
|
||||
EXPECT_TRUE(provider_->is_directory("/sub/sub2"));
|
||||
|
||||
EXPECT_EQ(api_error::directory_not_empty, provider_->remove_directory("/sub"));
|
||||
EXPECT_TRUE(provider_->is_directory("/sub"));
|
||||
EXPECT_TRUE(provider_->is_directory("/sub/sub2"));
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, remove_directory_fails_if_files_exist) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/sub", directory_meta));
|
||||
EXPECT_TRUE(provider_->is_directory("/sub"));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/sub/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/sub/test.txt", file_meta));
|
||||
|
||||
EXPECT_EQ(api_error::directory_not_empty, provider_->remove_directory("/sub"));
|
||||
EXPECT_TRUE(provider_->is_directory("/sub"));
|
||||
EXPECT_TRUE(provider_->is_file("/sub/test.txt"));
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, remove_directory_fails_for_root_directory) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
EXPECT_EQ(api_error::access_denied, provider_->remove_directory("/"));
|
||||
EXPECT_TRUE(provider_->is_directory("/"));
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, remove_file) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_TRUE(provider_->is_directory("/"));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
EXPECT_TRUE(provider_->is_file("/test.txt"));
|
||||
|
||||
EXPECT_EQ(api_error::success, provider_->remove_file("/test.txt"));
|
||||
EXPECT_FALSE(provider_->is_file("/test.txt"));
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, recreate_file_after_remove_file) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_TRUE(provider_->is_directory("/"));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
EXPECT_TRUE(provider_->is_file("/test.txt"));
|
||||
|
||||
EXPECT_EQ(api_error::success, provider_->remove_file("/test.txt"));
|
||||
EXPECT_FALSE(provider_->is_file("/test.txt"));
|
||||
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
EXPECT_TRUE(provider_->is_file("/test.txt"));
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, rename_file) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/test.txt", file_meta));
|
||||
|
||||
EXPECT_EQ(api_error::success, provider_->rename_file("/test.txt", "/test2.txt"));
|
||||
EXPECT_TRUE(provider_->is_file("/test2.txt"));
|
||||
EXPECT_FALSE(provider_->is_file("/test.txt"));
|
||||
|
||||
api_meta_map fileMeta2{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/test2.txt", fileMeta2));
|
||||
EXPECT_EQ(file_meta.size(), fileMeta2.size());
|
||||
for (const auto &kv : file_meta) {
|
||||
EXPECT_STREQ(file_meta[kv.first].c_str(), fileMeta2[kv.first].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, upload_file_and_read_file_bytes) {
|
||||
config_->set_value_by_name("SkynetConfig.EncryptionToken", "");
|
||||
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
|
||||
filesystem_item fsi{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_filesystem_item("/test.txt", false, fsi));
|
||||
EXPECT_TRUE(fsi.encryption_token.empty());
|
||||
EXPECT_FALSE(fsi.is_encrypted());
|
||||
|
||||
json j = {{"test", "test"}, {"test2", "test"}};
|
||||
EXPECT_TRUE(utils::file::write_json_file(fsi.source_path, j));
|
||||
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->upload_file(fsi.api_path, fsi.source_path, fsi.encryption_token));
|
||||
while (provider_->is_processing(fsi.api_path)) {
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
std::string id;
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta(fsi.api_path, META_ID, id));
|
||||
|
||||
json skynet_info = json::parse(id);
|
||||
std::cout << skynet_info.dump(2) << std::endl;
|
||||
EXPECT_NE(0u, skynet_info["skylink"].size());
|
||||
|
||||
std::uint64_t file_size = 0;
|
||||
utils::file::get_file_size(fsi.source_path, file_size);
|
||||
|
||||
std::vector<char> data;
|
||||
auto stop_requested = false;
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->read_file_bytes("/test.txt", static_cast<std::size_t>(file_size), 0, data,
|
||||
stop_requested));
|
||||
EXPECT_EQ(file_size, std::uint64_t(data.size()));
|
||||
EXPECT_STREQ(j.dump().c_str(), json::parse(std::string(&data[0], data.size())).dump().c_str());
|
||||
|
||||
http_ranges ranges = {{0, 0}};
|
||||
http_headers headers;
|
||||
json error;
|
||||
EXPECT_EQ(api_error::success,
|
||||
curl_comm_->get_range_and_headers(
|
||||
provider_->get_host_config(false), "/" + skynet_info["skylink"].get<std::string>(),
|
||||
0u, {{"format", "concat"}}, "", data, ranges, error, headers, stop_requested));
|
||||
for (const auto &header : headers) {
|
||||
std::cout << header.first << ":" << header.second << std::endl;
|
||||
}
|
||||
json meta_data;
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->get_skynet_metadata(skynet_info["skylink"].get<std::string>(), meta_data));
|
||||
EXPECT_STREQ(meta_data["filename"].get<std::string>().c_str(), "test.txt");
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, upload_encrypted_file_and_read_file_bytes) {
|
||||
config_->set_value_by_name("SkynetConfig.EncryptionToken", "TestToken");
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
|
||||
filesystem_item fsi{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_filesystem_item("/test.txt", false, fsi));
|
||||
EXPECT_STREQ("TestToken", fsi.encryption_token.c_str());
|
||||
EXPECT_TRUE(fsi.is_encrypted());
|
||||
|
||||
const auto file_size = 2u * utils::encryption::encrypting_reader::get_data_chunk_size() + 3u;
|
||||
auto source_file = create_random_file(fsi.source_path, file_size);
|
||||
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->upload_file(fsi.api_path, fsi.source_path, fsi.encryption_token));
|
||||
while (provider_->is_processing(fsi.api_path)) {
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
std::string id;
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta(fsi.api_path, META_ID, id));
|
||||
|
||||
json skynet_info = json::parse(id);
|
||||
std::cout << skynet_info.dump(2) << std::endl;
|
||||
EXPECT_NE(0u, skynet_info["skylink"].size());
|
||||
|
||||
auto stop_requested = false;
|
||||
const auto size = file_size / 3u;
|
||||
const auto size_remain = file_size % 3u;
|
||||
for (std::uint8_t i = 0u; i < 3u; i++) {
|
||||
const auto read_size = size + (i == 2u ? size_remain : 0u);
|
||||
std::vector<char> data;
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->read_file_bytes("/test.txt", read_size, i * size, data, stop_requested));
|
||||
|
||||
std::size_t bytes_read{};
|
||||
std::vector<char> b(read_size);
|
||||
EXPECT_TRUE(source_file->read_bytes(&b[0u], b.size(), i * size, bytes_read));
|
||||
EXPECT_EQ(b.size(), read_size);
|
||||
EXPECT_EQ(0, std::memcmp(&data[0u], &b[0u], data.size()));
|
||||
}
|
||||
source_file->close();
|
||||
|
||||
http_ranges ranges = {{0, 0}};
|
||||
http_headers headers;
|
||||
json error;
|
||||
auto err = api_error::error;
|
||||
for (std::size_t j = 0u; (err != api_error::success) && (j < config_->get_retry_read_count());
|
||||
j++) {
|
||||
std::vector<char> data;
|
||||
err = curl_comm_->get_range_and_headers(
|
||||
provider_->get_host_config(false), "/" + skynet_info["skylink"].get<std::string>(), 0u,
|
||||
{{"format", "concat"}}, "", data, ranges, error, headers, stop_requested);
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, err);
|
||||
for (const auto &header : headers) {
|
||||
std::cout << header.first << ":" << header.second << std::endl;
|
||||
}
|
||||
|
||||
json meta_data;
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->get_skynet_metadata(skynet_info["skylink"].get<std::string>(), meta_data));
|
||||
|
||||
const auto encrypted_file_name = meta_data["filename"].get<std::string>();
|
||||
std::vector<char> buffer;
|
||||
EXPECT_TRUE(utils::from_hex_string(encrypted_file_name, buffer));
|
||||
|
||||
std::string file_name;
|
||||
decrypt_and_verify(buffer, fsi.encryption_token, file_name);
|
||||
EXPECT_STREQ("test.txt", file_name.c_str());
|
||||
|
||||
config_->set_value_by_name("SkynetConfig.EncryptionToken", "");
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, upload_tiny_encrypted_file_and_read_file_bytes) {
|
||||
config_->set_value_by_name("SkynetConfig.EncryptionToken", "TestToken");
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
api_meta_map file_meta{};
|
||||
populate_file_meta("/test.txt", file_meta);
|
||||
EXPECT_EQ(api_error::success, provider_->create_file("/test.txt", file_meta));
|
||||
|
||||
filesystem_item fsi{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_filesystem_item("/test.txt", false, fsi));
|
||||
EXPECT_STREQ("TestToken", fsi.encryption_token.c_str());
|
||||
EXPECT_TRUE(fsi.is_encrypted());
|
||||
|
||||
json j = {{"test", "test"}, {"test2", "test"}};
|
||||
EXPECT_TRUE(utils::file::write_json_file(fsi.source_path, j));
|
||||
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->upload_file(fsi.api_path, fsi.source_path, fsi.encryption_token));
|
||||
while (provider_->is_processing(fsi.api_path)) {
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
std::string id;
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta(fsi.api_path, META_ID, id));
|
||||
|
||||
json skynet_info = json::parse(id);
|
||||
std::cout << skynet_info.dump(2) << std::endl;
|
||||
EXPECT_NE(0u, skynet_info["skylink"].size());
|
||||
|
||||
std::uint64_t file_size = 0;
|
||||
utils::file::get_file_size(fsi.source_path, file_size);
|
||||
|
||||
std::vector<char> data;
|
||||
auto stop_requested = false;
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->read_file_bytes("/test.txt", static_cast<std::size_t>(file_size), 0, data,
|
||||
stop_requested));
|
||||
EXPECT_EQ(file_size, std::uint64_t(data.size()));
|
||||
|
||||
const auto str = std::string(&data[0u], data.size());
|
||||
EXPECT_STREQ(j.dump().c_str(), json::parse(str).dump().c_str());
|
||||
|
||||
http_ranges ranges = {{0, 0}};
|
||||
http_headers headers;
|
||||
json error;
|
||||
auto apiError = api_error::error;
|
||||
for (std::size_t i = 0; (apiError != api_error::success) && (i < config_->get_retry_read_count());
|
||||
i++) {
|
||||
apiError = curl_comm_->get_range_and_headers(
|
||||
provider_->get_host_config(false), "/" + skynet_info["skylink"].get<std::string>(), 0u,
|
||||
{{"format", "concat"}}, "", data, ranges, error, headers, stop_requested);
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, apiError);
|
||||
for (const auto &header : headers) {
|
||||
std::cout << header.first << ":" << header.second << std::endl;
|
||||
}
|
||||
|
||||
json meta_data;
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->get_skynet_metadata(skynet_info["skylink"].get<std::string>(), meta_data));
|
||||
|
||||
const auto encrypted_file_name = meta_data["filename"].get<std::string>();
|
||||
std::vector<char> buffer;
|
||||
EXPECT_TRUE(utils::from_hex_string(encrypted_file_name, buffer));
|
||||
|
||||
std::string file_name;
|
||||
decrypt_and_verify(buffer, fsi.encryption_token, file_name);
|
||||
EXPECT_STREQ("test.txt", file_name.c_str());
|
||||
|
||||
config_->set_value_by_name("SkynetConfig.EncryptionToken", "");
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, import_and_export) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
skylink_import sl{"", "", "AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA", ""};
|
||||
EXPECT_EQ(api_error::success, provider_->import_skylink(sl));
|
||||
EXPECT_TRUE(provider_->is_file("/repertory_test_import.txt"));
|
||||
|
||||
std::uint64_t file_size = 0u;
|
||||
EXPECT_EQ(api_error::success, provider_->get_file_size("/repertory_test_import.txt", file_size));
|
||||
EXPECT_EQ(std::uint64_t(3u), file_size);
|
||||
|
||||
api_meta_map meta;
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/repertory_test_import.txt", meta));
|
||||
|
||||
const auto id = json::parse(meta[META_ID]);
|
||||
EXPECT_STREQ("AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",
|
||||
id["skylink"].get<std::string>().c_str());
|
||||
|
||||
const auto test_success = [](json &result) {
|
||||
EXPECT_EQ(std::size_t(1u), result["success"].size());
|
||||
|
||||
auto i = skylink_import::from_json(result["success"][0u]);
|
||||
EXPECT_STREQ("/", i.directory.c_str());
|
||||
EXPECT_STREQ("repertory_test_import.txt", i.file_name.c_str());
|
||||
EXPECT_STREQ("AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA", i.skylink.c_str());
|
||||
EXPECT_STREQ("", i.token.c_str());
|
||||
};
|
||||
|
||||
{
|
||||
auto export_with_failure =
|
||||
provider_->export_list({"/repertory_test_import.txt", "/repertory_test_import2.txt"});
|
||||
std::cout << export_with_failure.dump(2) << std::endl;
|
||||
EXPECT_EQ(std::size_t(1), export_with_failure["failed"].size());
|
||||
EXPECT_STREQ("/repertory_test_import2.txt",
|
||||
export_with_failure["failed"][0u].get<std::string>().c_str());
|
||||
|
||||
test_success(export_with_failure);
|
||||
}
|
||||
|
||||
{
|
||||
auto export_all = provider_->export_all();
|
||||
std::cout << export_all.dump(2) << std::endl;
|
||||
EXPECT_TRUE(export_all["failed"].empty());
|
||||
|
||||
test_success(export_all);
|
||||
}
|
||||
provider_->remove_file("/repertory_test_import.txt");
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, import_and_export_with_different_directory) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
skylink_import sl{"/test/sub", "", "AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA", ""};
|
||||
EXPECT_EQ(api_error::success, provider_->import_skylink(sl));
|
||||
EXPECT_TRUE(provider_->is_directory("/test"));
|
||||
EXPECT_TRUE(provider_->is_directory("/test/sub"));
|
||||
EXPECT_TRUE(provider_->is_file("/test/sub/repertory_test_import.txt"));
|
||||
|
||||
std::uint64_t file_size = 0;
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->get_file_size("/test/sub/repertory_test_import.txt", file_size));
|
||||
EXPECT_EQ(std::uint64_t(3), file_size);
|
||||
|
||||
api_meta_map meta;
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->get_item_meta("/test/sub/repertory_test_import.txt", meta));
|
||||
|
||||
const auto id = json::parse(meta[META_ID]);
|
||||
EXPECT_STREQ("AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",
|
||||
id["skylink"].get<std::string>().c_str());
|
||||
|
||||
const auto test_success = [](json &result) {
|
||||
EXPECT_EQ(std::size_t(1), result["success"].size());
|
||||
|
||||
auto i = skylink_import::from_json(result["success"][0u]);
|
||||
EXPECT_STREQ("/test/sub", i.directory.c_str());
|
||||
EXPECT_STREQ("repertory_test_import.txt", i.file_name.c_str());
|
||||
EXPECT_STREQ("AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA", i.skylink.c_str());
|
||||
EXPECT_STREQ("", i.token.c_str());
|
||||
};
|
||||
|
||||
{
|
||||
auto export_with_failure = provider_->export_list(
|
||||
{"/test/sub/repertory_test_import.txt", "/test/sub/repertory_test_import2.txt"});
|
||||
std::cout << export_with_failure.dump(2) << std::endl;
|
||||
EXPECT_EQ(std::size_t(1), export_with_failure["failed"].size());
|
||||
EXPECT_STREQ("/test/sub/repertory_test_import2.txt",
|
||||
export_with_failure["failed"][0u].get<std::string>().c_str());
|
||||
|
||||
test_success(export_with_failure);
|
||||
}
|
||||
|
||||
{
|
||||
auto export_all = provider_->export_all();
|
||||
std::cout << export_all.dump(2) << std::endl;
|
||||
EXPECT_TRUE(export_all["failed"].empty());
|
||||
|
||||
test_success(export_all);
|
||||
}
|
||||
|
||||
provider_->remove_file("/test/sub/repertory_test_import.txt");
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, import_directory) {
|
||||
const auto expected_json_data = json::parse(
|
||||
R"({ "filename": "skynet_test", "length": 36, "subfiles": { "sub_dir/test_03": { "contenttype": "application/octet-stream", "filename": "sub_dir/test_03", "len": 9, "offset": 18 }, "sub_dir/test_04": { "contenttype": "application/octet-stream", "filename": "sub_dir/test_04", "len": 9, "offset": 27 }, "test_01": { "contenttype": "application/octet-stream", "filename": "test_01", "len": 9 }, "test_02": { "contenttype": "application/octet-stream", "filename": "test_02", "len": 9, "offset": 9 } }, "tryfiles": [ "index.html" ] })");
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
skylink_import sl{"", "", EXTERNAL_SKYLINK, ""};
|
||||
EXPECT_EQ(api_error::success, provider_->import_skylink(sl));
|
||||
|
||||
for (const auto &subFile : expected_json_data["subfiles"]) {
|
||||
const auto api_path = utils::path::create_api_path(
|
||||
utils::path::combine("/", {subFile["filename"].get<std::string>()}));
|
||||
EXPECT_TRUE(provider_->is_file(api_path));
|
||||
|
||||
std::uint64_t file_size = 0;
|
||||
EXPECT_EQ(api_error::success, provider_->get_file_size(api_path, file_size));
|
||||
EXPECT_EQ(subFile["len"].get<std::uint64_t>(), file_size);
|
||||
|
||||
api_meta_map meta;
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta(api_path, meta));
|
||||
|
||||
const auto id = json::parse(meta[META_ID]);
|
||||
const auto skylink = sl.skylink + api_path;
|
||||
EXPECT_STREQ(skylink.c_str(), id["skylink"].get<std::string>().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, rename_file_fails_on_skylinks_with_directory_paths) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/test_rename2", {}));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/test_rename2/static", {}));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/test_rename2/static/css", {}));
|
||||
|
||||
skylink_import sl{"/test_rename", "", EXTERNAL_SKYLINK, ""};
|
||||
EXPECT_EQ(api_error::success, provider_->import_skylink(sl));
|
||||
if (not ::testing::Test::HasFailure()) {
|
||||
EXPECT_EQ(api_error::access_denied,
|
||||
provider_->rename_file("/test_rename/test_01", "/test_rename/test_01_"));
|
||||
EXPECT_EQ(api_error::access_denied, provider_->rename_file("/test_rename/sub_dir/test_03",
|
||||
"/test_rename/sub_dir/test_03_"));
|
||||
|
||||
EXPECT_EQ(api_error::access_denied,
|
||||
provider_->rename_file("/test_rename/test_01", "/test_rename2/test_01_"));
|
||||
EXPECT_EQ(api_error::access_denied, provider_->rename_file("/test_rename/sub_dir/test_03",
|
||||
"/test_rename2/sub_dir/test_03_"));
|
||||
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/test_rename/a", {}));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/test_rename/sub_dir/b", {}));
|
||||
|
||||
EXPECT_EQ(api_error::access_denied,
|
||||
provider_->rename_file("/test_rename/test_01", "/test_rename/a/test_01_"));
|
||||
|
||||
EXPECT_EQ(api_error::access_denied, provider_->rename_file("/test_rename/sub_dir/test_03",
|
||||
"/test_rename/static/b/test_03_"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, rename_file_succeeds_with_logical_directory_paths) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/test_rename2", {}));
|
||||
EXPECT_EQ(api_error::success, provider_->create_directory("/test_rename2/sub_dir", {}));
|
||||
|
||||
skylink_import sl{"/test_rename", "", EXTERNAL_SKYLINK, ""};
|
||||
EXPECT_EQ(api_error::success, provider_->import_skylink(sl));
|
||||
if (not ::testing::Test::HasFailure()) {
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider_->rename_file("/test_rename/test_01", "/test_rename2/test_01"));
|
||||
EXPECT_EQ(api_error::success, provider_->rename_file("/test_rename/sub_dir/test_03",
|
||||
"/test_rename2/sub_dir/test_03"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, export_with_nested_directory_paths) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
skylink_import sl{"/test_export/nested", "", EXTERNAL_SKYLINK, ""};
|
||||
EXPECT_EQ(api_error::success, provider_->import_skylink(sl));
|
||||
if (not ::testing::Test::HasFailure()) {
|
||||
const auto json_data = provider_->export_all();
|
||||
for (const auto &e : json_data["success"]) {
|
||||
EXPECT_STREQ("/test_export/nested", e["directory"].get<std::string>().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, export_with_nested_directory_paths_in_root) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
skylink_import sl{"/", "", EXTERNAL_SKYLINK, ""};
|
||||
EXPECT_EQ(api_error::success, provider_->import_skylink(sl));
|
||||
if (not ::testing::Test::HasFailure()) {
|
||||
const auto json_data = provider_->export_all();
|
||||
for (const auto &e : json_data["success"]) {
|
||||
EXPECT_STREQ("/", e["directory"].get<std::string>().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, is_file_writeable_is_false_for_nested_skylinks) {
|
||||
api_meta_map directory_meta{};
|
||||
EXPECT_EQ(api_error::success, provider_->get_item_meta("/", directory_meta));
|
||||
|
||||
skylink_import sl{"/", "", EXTERNAL_SKYLINK, ""};
|
||||
EXPECT_EQ(api_error::success, provider_->import_skylink(sl));
|
||||
if (not ::testing::Test::HasFailure()) {
|
||||
api_file_list list{};
|
||||
provider_->get_file_list(list);
|
||||
for (const auto &file : list) {
|
||||
EXPECT_FALSE(provider_->is_file_writeable(file.api_path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REPERTORY_ENABLE_SKYNET_PREMIUM_TESTS
|
||||
TEST_F(skynet_provider_test, authenticated_upload) {
|
||||
app_config config(provider_type::skynet, "../..");
|
||||
auto sk = config.get_skynet_config();
|
||||
EXPECT_FALSE(sk.portal_list[0u].auth_user.empty());
|
||||
sk.portal_list[0u].path = "/skynet/skyfile";
|
||||
curl_comm comm(config);
|
||||
|
||||
const auto source_file = __FILE__;
|
||||
const auto file_name = utils::path::strip_to_file_name(source_file);
|
||||
auto id = utils::create_uuid_string();
|
||||
utils::string::replace(id, "-", "");
|
||||
|
||||
json data, error;
|
||||
auto sr = false;
|
||||
EXPECT_EQ(api_error::success,
|
||||
comm.post_multipart_file(sk.portal_list.at(0), "", file_name, source_file, "repertory",
|
||||
data, error, sr));
|
||||
std::cout << data.dump(2) << std::endl;
|
||||
std::cout << error.dump(2) << std::endl;
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, authenticated_upload_access_denied_with_invalid_username) {
|
||||
app_config config(provider_type::skynet, "../..");
|
||||
auto sk = config.get_skynet_config();
|
||||
sk.portal_list[0u].auth_user = "cowaoeutnhsaoetuh@aosetuh.com";
|
||||
sk.portal_list[0u].path = "/skynet/skyfile";
|
||||
curl_comm comm(config);
|
||||
|
||||
const auto source_file = __FILE__;
|
||||
const auto file_name = utils::path::strip_to_file_name(source_file);
|
||||
auto id = utils::create_uuid_string();
|
||||
utils::string::replace(id, "-", "");
|
||||
|
||||
json data, error;
|
||||
auto sr = false;
|
||||
EXPECT_EQ(api_error::access_denied,
|
||||
comm.post_multipart_file(sk.portal_list.at(0), "", file_name, source_file, "repertory",
|
||||
data, error, sr));
|
||||
std::cout << data.dump(2) << std::endl;
|
||||
std::cout << error.dump(2) << std::endl;
|
||||
}
|
||||
|
||||
TEST_F(skynet_provider_test, authenticated_upload_access_denied_with_invalid_password) {
|
||||
app_config config(provider_type::skynet, "../..");
|
||||
auto sk = config.get_skynet_config();
|
||||
EXPECT_FALSE(sk.portal_list[0u].auth_user.empty());
|
||||
|
||||
sk.portal_list[0u].auth_password = "1";
|
||||
sk.portal_list[0u].path = "/skynet/skyfile";
|
||||
curl_comm comm(config);
|
||||
|
||||
const auto source_file = __FILE__;
|
||||
const auto file_name = utils::path::strip_to_file_name(source_file);
|
||||
auto id = utils::create_uuid_string();
|
||||
utils::string::replace(id, "-", "");
|
||||
|
||||
json data, error;
|
||||
auto sr = false;
|
||||
EXPECT_EQ(api_error::access_denied,
|
||||
comm.post_multipart_file(sk.portal_list.at(0), "", file_name, source_file, "repertory",
|
||||
data, error, sr));
|
||||
std::cout << data.dump(2) << std::endl;
|
||||
std::cout << error.dump(2) << std::endl;
|
||||
}
|
||||
#endif // REPERTORY_ENABLE_SKYNET_PREMIUM_TESTS
|
||||
} // namespace repertory
|
||||
|
||||
// TODO Test import without encryption token when global encryption token is set
|
||||
// TODO Test encrypted file import
|
||||
// TODO Test encrypted directory import
|
||||
#endif // REPERTORY_ENABLE_SKYNET
|
1
tests/skynet_test/sub_dir/test_03
Normal file
1
tests/skynet_test/sub_dir/test_03
Normal file
@ -0,0 +1 @@
|
||||
test_03
|
1
tests/skynet_test/sub_dir/test_04
Normal file
1
tests/skynet_test/sub_dir/test_04
Normal file
@ -0,0 +1 @@
|
||||
test_04
|
1
tests/skynet_test/test_01
Normal file
1
tests/skynet_test/test_01
Normal file
@ -0,0 +1 @@
|
||||
test_01
|
1
tests/skynet_test/test_02
Normal file
1
tests/skynet_test/test_02
Normal file
@ -0,0 +1 @@
|
||||
test_02
|
50
tests/test_common.cpp
Normal file
50
tests/test_common.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "utils/path_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
native_file_ptr create_random_file(std::string path, const size_t &size) {
|
||||
native_file_ptr nf;
|
||||
if (native_file::create_or_open(path, nf) == api_error::success) {
|
||||
EXPECT_TRUE(nf->truncate(0u));
|
||||
|
||||
std::vector<char> buf(size);
|
||||
CryptoPP::OS_GenerateRandomBlock(false, reinterpret_cast<CryptoPP::byte *>(&buf[0u]),
|
||||
buf.size());
|
||||
|
||||
std::size_t bytes_written{};
|
||||
nf->write_bytes(&buf[0u], buf.size(), 0u, bytes_written);
|
||||
nf->flush();
|
||||
|
||||
std::uint64_t current_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(path, current_size));
|
||||
EXPECT_EQ(size, current_size);
|
||||
}
|
||||
|
||||
return nf;
|
||||
}
|
||||
|
||||
std::string generate_test_file_name(const std::string &directory,
|
||||
const std::string &file_name_no_extension) {
|
||||
static std::atomic<std::uint32_t> idx(0u);
|
||||
return utils::path::absolute(utils::path::combine(
|
||||
directory, {file_name_no_extension + utils::string::from_uint32(idx++) + ".dat"}));
|
||||
}
|
||||
} // namespace repertory
|
90
tests/test_common.hpp
Normal file
90
tests/test_common.hpp
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 TESTS_TEST_COMMON_HPP_
|
||||
#define TESTS_TEST_COMMON_HPP_
|
||||
|
||||
#ifdef U
|
||||
#undef U
|
||||
#endif
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "events/consumers/console_consumer.hpp"
|
||||
#include "events/events.hpp"
|
||||
#include "events/event_system.hpp"
|
||||
#include "providers/passthrough/passthroughprovider.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
// Disable DLL-interface warnings
|
||||
#pragma warning(disable : 4251)
|
||||
#pragma warning(disable : 4275)
|
||||
#endif
|
||||
|
||||
#include "utils/encryption.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/native_file.hpp"
|
||||
|
||||
#define COMMA ,
|
||||
#define RENTER_FILE_DATA(api_path, size) \
|
||||
{ \
|
||||
{ \
|
||||
"file" COMMA { \
|
||||
{"filesize" COMMA size} COMMA{"siapath" COMMA api_path} COMMA{ \
|
||||
"redundancy" COMMA 1.0} COMMA{"available" COMMA false} COMMA{ \
|
||||
"expiration" COMMA 0} COMMA{"ondisk" COMMA true} COMMA{ \
|
||||
"recoverable" COMMA false} COMMA{"renewing" COMMA false} COMMA{ \
|
||||
"localpath" COMMA \
|
||||
".\\"} COMMA{"uploadedbytes" COMMA 0} COMMA{"uploadprogress" COMMA 0} COMMA{ \
|
||||
"accesstime" COMMA "2019-02-21T02:24:37.653091916-06:00"} COMMA{ \
|
||||
"changetime" COMMA "2019-02-21T02:24:37.653091916-06:00"} COMMA{ \
|
||||
"createtime" COMMA "2019-02-21T02:24:37.653091916-06:00"} COMMA{ \
|
||||
"modtime" COMMA "2019-02-21T02:24:37.653091916-06:00"} COMMA \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define RENTER_DIR_DATA(api_path) \
|
||||
{ \
|
||||
{ \
|
||||
"directories", { \
|
||||
{ \
|
||||
{"siapath", api_path}, {"numfiles", 0}, { "numsubdirs", 0 } \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
using ::testing::_;
|
||||
using namespace ::testing;
|
||||
|
||||
namespace repertory {
|
||||
native_file_ptr create_random_file(std::string path, const size_t &size);
|
||||
|
||||
std::string generate_test_file_name(const std::string &directory,
|
||||
const std::string &file_name_no_extension);
|
||||
|
||||
template <typename T, typename T2>
|
||||
static void decrypt_and_verify(const T &buffer, const std::string &token, T2 &result) {
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(token, buffer, result));
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
#endif // TESTS_TEST_COMMON_HPP_
|
99
tests/utils/event_capture.hpp
Normal file
99
tests/utils/event_capture.hpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 TESTS_UTILS_EVENT_CAPTURE_HPP_
|
||||
#define TESTS_UTILS_EVENT_CAPTURE_HPP_
|
||||
|
||||
#include "test_common.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class event_capture final {
|
||||
E_CONSUMER();
|
||||
|
||||
public:
|
||||
explicit event_capture(std::vector<std::string> event_names,
|
||||
std::vector<std::string> non_fired_event_names = {})
|
||||
: event_names_(std::move(event_names)),
|
||||
non_fired_event_names_(std::move(non_fired_event_names)) {
|
||||
E_SUBSCRIBE_ALL(process_event);
|
||||
}
|
||||
|
||||
~event_capture() {
|
||||
wait_for_empty();
|
||||
|
||||
E_CONSUMER_RELEASE();
|
||||
|
||||
EXPECT_TRUE(event_names_.empty());
|
||||
for (const auto &event_name : event_names_) {
|
||||
std::cerr << '\t' << event_name << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> event_names_;
|
||||
std::vector<std::string> fired_event_names_;
|
||||
std::vector<std::string> non_fired_event_names_;
|
||||
std::mutex mutex_;
|
||||
std::condition_variable notify_;
|
||||
|
||||
public:
|
||||
void process_event(const event &event) {
|
||||
unique_mutex_lock l(mutex_);
|
||||
utils::remove_element_from(event_names_, event.get_name());
|
||||
fired_event_names_.emplace_back(event.get_name());
|
||||
notify_.notify_all();
|
||||
l.unlock();
|
||||
|
||||
for (size_t i = 0; i < non_fired_event_names_.size(); i++) {
|
||||
EXPECT_EQ(non_fired_event_names_.end(),
|
||||
std::find(non_fired_event_names_.begin(), non_fired_event_names_.end(),
|
||||
event.get_name()));
|
||||
}
|
||||
}
|
||||
|
||||
void wait_for_empty() {
|
||||
const auto start_time = std::chrono::system_clock::now();
|
||||
unique_mutex_lock l(mutex_);
|
||||
while (not event_names_.empty() && (std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now() - start_time)
|
||||
.count() < 5)) {
|
||||
notify_.wait_for(l, 1s);
|
||||
}
|
||||
l.unlock();
|
||||
}
|
||||
|
||||
bool wait_for_event(const std::string &event_name) {
|
||||
auto missing = true;
|
||||
const auto start_time = std::chrono::system_clock::now();
|
||||
|
||||
unique_mutex_lock l(mutex_);
|
||||
while ((std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() -
|
||||
start_time)
|
||||
.count() < 5) &&
|
||||
(missing = (std::find(fired_event_names_.begin(), fired_event_names_.end(),
|
||||
event_name) == fired_event_names_.end()))) {
|
||||
notify_.wait_for(l, 1s);
|
||||
}
|
||||
l.unlock();
|
||||
return not missing;
|
||||
}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // TESTS_UTILS_EVENT_CAPTURE_HPP_
|
69
tests/utils_test.cpp
Normal file
69
tests/utils_test.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "comm/curl/curl_comm.hpp"
|
||||
#include "types/skynet.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
#ifdef _WIN32
|
||||
TEST(utils, convert_api_date) {
|
||||
LARGE_INTEGER li{};
|
||||
li.QuadPart = utils::convert_api_date("2019-02-21T03:24:37.653091916-06:00");
|
||||
|
||||
SYSTEMTIME st{};
|
||||
FileTimeToSystemTime((FILETIME *)&li, &st);
|
||||
|
||||
SYSTEMTIME lt{};
|
||||
SystemTimeToTzSpecificLocalTime(nullptr, &st, <);
|
||||
|
||||
EXPECT_EQ(2019, lt.wYear);
|
||||
EXPECT_EQ(2, lt.wMonth);
|
||||
EXPECT_EQ(21, lt.wDay);
|
||||
|
||||
EXPECT_EQ(3, lt.wHour);
|
||||
EXPECT_EQ(24, lt.wMinute);
|
||||
EXPECT_EQ(37, lt.wSecond);
|
||||
EXPECT_EQ(653, lt.wMilliseconds);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(utils, create_uuid_string) {
|
||||
const auto uuid1 = utils::create_uuid_string();
|
||||
const auto uuid2 = utils::create_uuid_string();
|
||||
ASSERT_EQ(36, uuid1.size());
|
||||
ASSERT_EQ(36, uuid2.size());
|
||||
ASSERT_STRNE(&uuid1[0], &uuid2[0]);
|
||||
}
|
||||
|
||||
TEST(utils, string_to_bool) {
|
||||
EXPECT_TRUE(utils::string::to_bool("1"));
|
||||
EXPECT_TRUE(utils::string::to_bool("-1"));
|
||||
EXPECT_TRUE(utils::string::to_bool("0.1"));
|
||||
EXPECT_TRUE(utils::string::to_bool("-0.1"));
|
||||
EXPECT_TRUE(utils::string::to_bool("00000.1000000"));
|
||||
EXPECT_TRUE(utils::string::to_bool("true"));
|
||||
|
||||
EXPECT_FALSE(utils::string::to_bool("false"));
|
||||
EXPECT_FALSE(utils::string::to_bool("0"));
|
||||
EXPECT_FALSE(utils::string::to_bool("00000.00000"));
|
||||
}
|
||||
} // namespace repertory
|
53
tests/version_test.cpp
Normal file
53
tests/version_test.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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 "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
TEST(version, equal) {
|
||||
EXPECT_EQ(0, utils::compare_version_strings("1.0", "1.0"));
|
||||
EXPECT_EQ(0, utils::compare_version_strings("1.0.0", "1.0"));
|
||||
EXPECT_EQ(0, utils::compare_version_strings("1.0.0.0", "1.0"));
|
||||
EXPECT_EQ(0, utils::compare_version_strings("1.0.0.0", "1.0.0"));
|
||||
}
|
||||
|
||||
TEST(version, greater) {
|
||||
EXPECT_EQ(1, utils::compare_version_strings("1.0.1", "1.0"));
|
||||
EXPECT_EQ(1, utils::compare_version_strings("1.0.1", "1.0.0"));
|
||||
EXPECT_EQ(1, utils::compare_version_strings("1.0.1", "1.0.0.0"));
|
||||
EXPECT_EQ(1, utils::compare_version_strings("1.0.1.0", "1.0"));
|
||||
EXPECT_EQ(1, utils::compare_version_strings("1.0.1.0", "1.0.0"));
|
||||
EXPECT_EQ(1, utils::compare_version_strings("1.0.1.0", "1.0.0.0"));
|
||||
EXPECT_EQ(1, utils::compare_version_strings("1.0", "0.9.9"));
|
||||
EXPECT_EQ(1, utils::compare_version_strings("1.0.1", "0.9.9"));
|
||||
EXPECT_EQ(1, utils::compare_version_strings("1.0.1.0", "0.9.9"));
|
||||
}
|
||||
|
||||
TEST(version, less) {
|
||||
EXPECT_EQ(-1, utils::compare_version_strings("0.9.9", "1.0"));
|
||||
EXPECT_EQ(-1, utils::compare_version_strings("0.9.9", "1.0.1"));
|
||||
EXPECT_EQ(-1, utils::compare_version_strings("0.9.9", "1.0.1.0"));
|
||||
EXPECT_EQ(-1, utils::compare_version_strings("1.0", "1.0.1"));
|
||||
EXPECT_EQ(-1, utils::compare_version_strings("1.0", "1.0.1.0"));
|
||||
EXPECT_EQ(-1, utils::compare_version_strings("1.0.0", "1.0.1"));
|
||||
EXPECT_EQ(-1, utils::compare_version_strings("1.0.0", "1.0.1.0"));
|
||||
EXPECT_EQ(-1, utils::compare_version_strings("1.0.0.0", "1.0.1"));
|
||||
EXPECT_EQ(-1, utils::compare_version_strings("1.0.0.0", "1.0.1.0"));
|
||||
}
|
||||
} // namespace repertory
|
685
tests/winfsp_test.cpp
Normal file
685
tests/winfsp_test.cpp
Normal file
@ -0,0 +1,685 @@
|
||||
/*
|
||||
Copyright <2018-2022> <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.
|
||||
*/
|
||||
#if _WIN32
|
||||
|
||||
#include "fixtures/winfsp_fixture.hpp"
|
||||
#include "utils/event_capture.hpp"
|
||||
#include "test_common.hpp"
|
||||
|
||||
namespace repertory {
|
||||
void launch_app(std::string cmd) {
|
||||
PROCESS_INFORMATION pi{};
|
||||
STARTUPINFO si{};
|
||||
si.cb = sizeof(si);
|
||||
|
||||
if (!::CreateProcessA(nullptr, (LPSTR)cmd.c_str(), nullptr, nullptr, FALSE,
|
||||
CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, nullptr, nullptr, &si,
|
||||
&pi)) {
|
||||
throw std::runtime_error("CreateProcess failed (" + std::to_string(::GetLastError()) + ")");
|
||||
}
|
||||
|
||||
::WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
DWORD code{};
|
||||
::GetExitCodeProcess(pi.hProcess, &code);
|
||||
|
||||
::CloseHandle(pi.hProcess);
|
||||
::CloseHandle(pi.hThread);
|
||||
EXPECT_EQ(0, code);
|
||||
}
|
||||
|
||||
E_SIMPLE1(test_begin, normal, false, std::string, test_name, TN, E_STRING);
|
||||
#define TEST_HEADER(func) \
|
||||
event_system::instance().raise<test_begin>( \
|
||||
std::string(func) + "\r\n***********************\r\n***********************")
|
||||
|
||||
static auto mount_setup(const std::size_t &idx, winfsp_test *test, std::string &mount_point) {
|
||||
// Mock communicator setup
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/wallet", {}, {}, api_error::success, true);
|
||||
mock_comm.push_return("get", "/renter/dir/",
|
||||
{{"directories", {{{"numfiles", 0}, {"numsubdirs", 0}}}}}, {},
|
||||
api_error::success, true);
|
||||
mock_comm.push_return("get", "/renter/file/", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/dir/autorun.inf", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/dir/.git", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/.git", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/dir/HEAD", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/HEAD", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/autorun.inf", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/dir/AutoRun.inf", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/AutoRun.inf", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/dir/Desktop.ini", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/Desktop.ini", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
json files;
|
||||
files["files"] = std::vector<json>();
|
||||
mock_comm.push_return("get", "/renter/files", files, {}, api_error::success, true);
|
||||
mock_comm.push_return("get", "/renter/prices", {}, {{"message", "offline"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return(
|
||||
"get", "/daemon/version",
|
||||
{{"version", app_config::get_provider_minimum_version(provider_type::sia)}}, {},
|
||||
api_error::success, true);
|
||||
|
||||
// Mount setup
|
||||
mount_point = "U:";
|
||||
return std::vector<std::string>({"unittests", "-f", mount_point});
|
||||
}
|
||||
|
||||
if (idx == 1) {
|
||||
// Mount setup
|
||||
mount_point = "V:";
|
||||
return std::vector<std::string>({"unittests", "-f", mount_point});
|
||||
}
|
||||
}
|
||||
|
||||
static void execute_mount(const std::size_t &idx, winfsp_test *test,
|
||||
const std::vector<std::string> &driveArgs, std::thread &th) {
|
||||
ASSERT_EQ(0, std::get<2>(test->provider_tests_[idx])->mount(driveArgs));
|
||||
th.join();
|
||||
}
|
||||
|
||||
static void unmount(const std::size_t &idx, winfsp_test *test, const std::string &mount_point) {
|
||||
std::get<2>(test->provider_tests_[idx])->shutdown();
|
||||
auto mounted = utils::file::is_directory(mount_point);
|
||||
for (auto i = 0; mounted && (i < 50); i++) {
|
||||
std::this_thread::sleep_for(100ms);
|
||||
mounted = utils::file::is_directory(mount_point);
|
||||
}
|
||||
EXPECT_FALSE(utils::file::is_directory(mount_point));
|
||||
}
|
||||
|
||||
static void root_creation_test(const std::string &mount_point) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
WIN32_FILE_ATTRIBUTE_DATA ad{};
|
||||
EXPECT_TRUE(::GetFileAttributesEx(&mount_point[0], GetFileExInfoStandard, &ad));
|
||||
EXPECT_EQ(FILE_ATTRIBUTE_DIRECTORY, ad.dwFileAttributes);
|
||||
EXPECT_EQ(0, ad.nFileSizeHigh);
|
||||
EXPECT_EQ(0, ad.nFileSizeLow);
|
||||
}
|
||||
|
||||
static auto create_test(const std::size_t &idx, winfsp_test *test, const std::string &mount_point) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/renter/dir/test_create.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/test_create.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error);
|
||||
mock_comm.push_return("post_params", "/renter/delete/test_create.txt", {},
|
||||
{{"message", "no file known"}}, api_error::comm_error);
|
||||
mock_comm.push_return("post_params", "/renter/upload/test_create.txt", {}, {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/file/test_create.txt",
|
||||
RENTER_FILE_DATA("test_create.txt", 0), {}, api_error::success, true);
|
||||
}
|
||||
|
||||
auto file = utils::path::combine(mount_point, {{"test_create.txt"}});
|
||||
auto handle = ::CreateFileA(&file[0], GENERIC_READ, FILE_SHARE_READ, nullptr, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
EXPECT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
EXPECT_TRUE(::CloseHandle(handle));
|
||||
|
||||
EXPECT_TRUE(utils::file::is_file(file));
|
||||
|
||||
std::uint64_t file_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(file, file_size));
|
||||
EXPECT_EQ(0, file_size);
|
||||
|
||||
std::string attr;
|
||||
EXPECT_EQ(api_error::success, std::get<1>(test->provider_tests_[idx])
|
||||
->get_item_meta("/test_create.txt", META_ATTRIBUTES, attr));
|
||||
EXPECT_EQ(FILE_ATTRIBUTE_NORMAL, utils::string::to_uint32(attr));
|
||||
|
||||
event_system::instance().stop();
|
||||
event_system::instance().start();
|
||||
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.remove_return("get", "/renter/dir/test_create.txt");
|
||||
mock_comm.remove_return("post_params", "/renter/delete/test_create.txt");
|
||||
mock_comm.remove_return("post_params", "/renter/upload/test_create.txt");
|
||||
mock_comm.remove_return("get", "/renter/file/test_create.txt");
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static void delete_file_test(const std::size_t &idx, winfsp_test *test, const std::string &file) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/renter/dir/test_create.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/test_create.txt",
|
||||
RENTER_FILE_DATA("test_create.txt", 0), {}, api_error::success);
|
||||
mock_comm.push_return("get", "/renter/file/test_create.txt",
|
||||
RENTER_FILE_DATA("test_create.txt", 0), {}, api_error::success);
|
||||
mock_comm.push_return("get", "/renter/file/test_create.txt",
|
||||
RENTER_FILE_DATA("test_create.txt", 0), {}, api_error::success);
|
||||
mock_comm.push_return("get", "/renter/file/test_create.txt",
|
||||
RENTER_FILE_DATA("test_create.txt", 0), {}, api_error::success);
|
||||
mock_comm.push_return("get", "/renter/file/test_create.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("post_params", "/renter/delete/test_create.txt", {}, {},
|
||||
api_error::success);
|
||||
}
|
||||
{
|
||||
event_capture ec({"file_removed"});
|
||||
EXPECT_TRUE(utils::file::delete_file(file));
|
||||
EXPECT_FALSE(utils::file::is_file(file));
|
||||
event_system::instance().stop();
|
||||
event_system::instance().start();
|
||||
}
|
||||
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.remove_return("post_params", "/renter/delete/test_create.txt");
|
||||
}
|
||||
}
|
||||
|
||||
static void create_directory_test(const std::size_t &idx, winfsp_test *test,
|
||||
const std::string &directory) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory.substr(3), {},
|
||||
{{"message", "no file known"}}, api_error::comm_error);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory.substr(3), {},
|
||||
{{"message", "no file known"}}, api_error::comm_error);
|
||||
mock_comm.push_return("get", "/renter/file/" + directory.substr(3), {},
|
||||
{{"message", "no file known"}}, api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory.substr(3),
|
||||
{{"directories", {{{"numfiles", 0}, {"numsubdirs", 0}}}}}, {},
|
||||
api_error::success, true);
|
||||
mock_comm.push_return("post_params", "/renter/dir/" + directory.substr(3), {}, {},
|
||||
api_error::success);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(::PathIsDirectory(&directory[0]));
|
||||
EXPECT_TRUE(::CreateDirectoryA(&directory[0], nullptr));
|
||||
EXPECT_TRUE(::PathIsDirectory(&directory[0]));
|
||||
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.remove_return("get", "/renter/dir/" + directory.substr(3));
|
||||
mock_comm.remove_return("get", "/renter/file/" + directory.substr(3));
|
||||
mock_comm.remove_return("post_params", "/renter/dir/" + directory.substr(3));
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_directory_test(const std::size_t &idx, winfsp_test *test,
|
||||
const std::string &directory) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory.substr(3),
|
||||
{{"directories", {{{"numfiles", 0}, {"numsubdirs", 0}}}}}, {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory.substr(3),
|
||||
{{"directories", {{{"numfiles", 0}, {"numsubdirs", 0}}}}}, {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory.substr(3),
|
||||
{{"directories", {{{"numfiles", 0}, {"numsubdirs", 0}}}}}, {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory.substr(3),
|
||||
{{"directories", {{{"numfiles", 0}, {"numsubdirs", 0}}}}}, {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("post_params", "/renter/dir/" + directory.substr(3), {}, {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory.substr(3), {},
|
||||
{{"message", "no file known"}}, api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/" + directory.substr(3), {},
|
||||
{{"message", "no file known"}}, api_error::comm_error, true);
|
||||
}
|
||||
|
||||
{
|
||||
event_capture ec({"directory_removed"});
|
||||
EXPECT_TRUE(::PathIsDirectory(&directory[0]));
|
||||
EXPECT_TRUE(::RemoveDirectoryA(&directory[0]));
|
||||
EXPECT_FALSE(::PathIsDirectory(&directory[0]));
|
||||
event_system::instance().stop();
|
||||
event_system::instance().start();
|
||||
}
|
||||
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.remove_return("post_params", "/renter/dir/" + directory.substr(3));
|
||||
}
|
||||
}
|
||||
|
||||
static void write_file_test(const std::size_t &idx, winfsp_test *test,
|
||||
const std::string &mount_point) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/renter/dir/",
|
||||
{{"directories", {{{"numfiles", 0}, {"numsubdirs", 0}}}}}, {},
|
||||
api_error::success, true);
|
||||
mock_comm.push_return("get", "/renter/dir/test_write.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/test_write.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error);
|
||||
mock_comm.push_return("post_params", "/renter/upload/test_write.txt", {}, {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("post_params", "/renter/upload/test_write.txt", {}, {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/file/test_write.txt",
|
||||
RENTER_FILE_DATA("test_write.txt", 0), {}, api_error::success);
|
||||
mock_comm.push_return("get", "/renter/file/test_write.txt",
|
||||
RENTER_FILE_DATA("test_write.txt", 10), {}, api_error::success, true);
|
||||
}
|
||||
|
||||
const auto file = utils::path::combine(mount_point, {"test_write.txt"});
|
||||
auto handle = ::CreateFileA(&file[0], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr,
|
||||
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
EXPECT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
const std::string data = "0123456789";
|
||||
DWORD bytes_written = 0;
|
||||
EXPECT_TRUE(
|
||||
::WriteFile(handle, &data[0], static_cast<DWORD>(data.size()), &bytes_written, nullptr));
|
||||
EXPECT_EQ(10, bytes_written);
|
||||
EXPECT_TRUE(::CloseHandle(handle));
|
||||
|
||||
EXPECT_TRUE(utils::file::is_file(file));
|
||||
|
||||
std::uint64_t file_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(file, file_size));
|
||||
EXPECT_EQ(10, file_size);
|
||||
|
||||
event_system::instance().stop();
|
||||
event_system::instance().start();
|
||||
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.remove_return("get", "/renter/dir/");
|
||||
mock_comm.remove_return("post_params", "/renter/upload/test_write.txt");
|
||||
}
|
||||
}
|
||||
|
||||
static void read_file_test(const std::size_t &idx, winfsp_test *test,
|
||||
const std::string &mount_point) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/renter/dir/",
|
||||
{{"directories", {{{"numfiles", 0}, {"numsubdirs", 0}}}}}, {},
|
||||
api_error::success, true);
|
||||
mock_comm.push_return("get", "/renter/dir/test_read.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/test_read.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error);
|
||||
mock_comm.push_return("post_params", "/renter/upload/test_read.txt", {}, {}, api_error::success,
|
||||
true);
|
||||
mock_comm.push_return("get", "/renter/file/test_read.txt", RENTER_FILE_DATA("test_read.txt", 0),
|
||||
{}, api_error::success);
|
||||
mock_comm.push_return("get", "/renter/file/test_read.txt",
|
||||
RENTER_FILE_DATA("test_read.txt", 10), {}, api_error::success, true);
|
||||
}
|
||||
|
||||
const auto file = utils::path::combine(mount_point, {"test_read.txt"});
|
||||
auto handle = ::CreateFileA(&file[0], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr,
|
||||
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
EXPECT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
const std::string data = "0123456789";
|
||||
DWORD bytes_written = 0;
|
||||
EXPECT_TRUE(
|
||||
::WriteFile(handle, &data[0], static_cast<DWORD>(data.size()), &bytes_written, nullptr));
|
||||
EXPECT_EQ(10, bytes_written);
|
||||
|
||||
std::vector<char> data2;
|
||||
data2.resize(10);
|
||||
DWORD bytes_read = 0;
|
||||
EXPECT_EQ(0, ::SetFilePointer(handle, 0, nullptr, FILE_BEGIN));
|
||||
EXPECT_TRUE(
|
||||
::ReadFile(handle, &data2[0], static_cast<DWORD>(data2.size()), &bytes_read, nullptr));
|
||||
EXPECT_EQ(10, bytes_read);
|
||||
for (auto i = 0; i < data.size(); i++) {
|
||||
EXPECT_EQ(data[i], data2[i]);
|
||||
}
|
||||
EXPECT_TRUE(::CloseHandle(handle));
|
||||
|
||||
event_system::instance().stop();
|
||||
event_system::instance().start();
|
||||
}
|
||||
|
||||
static void rename_file_test(const std::size_t &idx, winfsp_test *test,
|
||||
const std::string &mount_point) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/renter/dir/rename_file.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/rename_file.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error);
|
||||
mock_comm.push_return("post_params", "/renter/upload/rename_file.txt", {}, {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/file/rename_file.txt",
|
||||
RENTER_FILE_DATA("rename_file.txt", 0), {}, api_error::success, true);
|
||||
|
||||
mock_comm.push_return("get", "/renter/dir/rename_file2.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/rename_file2.txt", {},
|
||||
{{"message", "no file known"}}, api_error::comm_error);
|
||||
mock_comm.push_return("get", "/renter/file/rename_file2.txt", {},
|
||||
{{"message", "no file known"}}, api_error::comm_error);
|
||||
mock_comm.push_return("get", "/renter/file/rename_file2.txt", {},
|
||||
{{"message", "no file known"}}, api_error::comm_error);
|
||||
mock_comm.push_return("post_params", "/renter/rename/rename_file.txt", {}, {},
|
||||
api_error::success);
|
||||
}
|
||||
|
||||
const auto file = utils::path::combine(mount_point, {"rename_file.txt"});
|
||||
auto handle = ::CreateFileA(&file[0], GENERIC_READ, FILE_SHARE_READ, nullptr, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
EXPECT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
EXPECT_TRUE(::CloseHandle(handle));
|
||||
|
||||
auto &provider = *std::get<1>(test->provider_tests_[idx]);
|
||||
|
||||
api_meta_map meta1{};
|
||||
EXPECT_EQ(api_error::success, provider.get_item_meta("/rename_file.txt", meta1));
|
||||
|
||||
const auto file2 = utils::path::combine(mount_point, {"rename_file2.txt"});
|
||||
EXPECT_TRUE(::MoveFile(&file[0], &file2[0]));
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.remove_return("get", "/renter/file/rename_file.txt");
|
||||
mock_comm.push_return("get", "/renter/file/rename_file.txt", {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/rename_file2.txt",
|
||||
RENTER_FILE_DATA("rename_file2.txt", 0), {}, api_error::success, true);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::is_file(file2));
|
||||
EXPECT_FALSE(utils::file::is_file(file));
|
||||
|
||||
api_meta_map meta2{};
|
||||
EXPECT_EQ(api_error::success, provider.get_item_meta("/rename_file2.txt", meta2));
|
||||
EXPECT_STREQ(meta1[META_SOURCE].c_str(), meta2[META_SOURCE].c_str());
|
||||
|
||||
filesystem_item fsi{};
|
||||
EXPECT_EQ(api_error::success, provider.get_filesystem_item("/rename_file2.txt", false, fsi));
|
||||
EXPECT_STREQ(meta1[META_SOURCE].c_str(), fsi.source_path.c_str());
|
||||
|
||||
filesystem_item fsi2{};
|
||||
EXPECT_EQ(api_error::success,
|
||||
provider.get_filesystem_item_from_source_path(fsi.source_path, fsi2));
|
||||
EXPECT_STREQ("/rename_file2.txt", fsi2.api_path.c_str());
|
||||
|
||||
EXPECT_EQ(api_error::item_not_found, provider.get_item_meta("/rename_file.txt", meta2));
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.remove_return("post_params", "/renter/upload/rename_file.txt");
|
||||
mock_comm.remove_return("post_params", "/renter/rename/rename_file.txt");
|
||||
}
|
||||
}
|
||||
|
||||
static void rename_directory_test(const std::size_t &idx, winfsp_test *test,
|
||||
const std::string &mount_point) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
std::string directory = "rename_dir";
|
||||
const auto full_directory = utils::path::combine(mount_point, {directory});
|
||||
std::string directory2 = "rename_dir2";
|
||||
const auto full_directory2 = utils::path::combine(mount_point, {directory2});
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory, {}, {{"message", "no file known"}},
|
||||
api_error::comm_error);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory, {}, {{"message", "no file known"}},
|
||||
api_error::comm_error);
|
||||
mock_comm.push_return("get", "/renter/file/" + directory, {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory2, {}, {{"message", "no file known"}},
|
||||
api_error::comm_error);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory2, {}, {{"message", "no file known"}},
|
||||
api_error::comm_error);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory2, {}, {{"message", "no file known"}},
|
||||
api_error::comm_error);
|
||||
|
||||
mock_comm.push_return("get", "/renter/file/" + directory2, {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory, RENTER_DIR_DATA(directory), {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory, RENTER_DIR_DATA(directory), {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory, RENTER_DIR_DATA(directory), {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory, RENTER_DIR_DATA(directory), {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory, RENTER_DIR_DATA(directory), {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory, RENTER_DIR_DATA(directory), {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory, RENTER_DIR_DATA(directory), {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory, RENTER_DIR_DATA(directory), {},
|
||||
api_error::success);
|
||||
mock_comm.push_return("post_params", "/renter/dir/" + directory, {}, {}, api_error::success);
|
||||
mock_comm.push_return("post_params", "/renter/dir/" + directory, {}, {}, api_error::success);
|
||||
|
||||
mock_comm.push_return("post_params", "/renter/dir/" + directory2, {}, {}, api_error::success);
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory2, RENTER_DIR_DATA(directory2), {},
|
||||
api_error::success, true);
|
||||
|
||||
mock_comm.push_return("get", "/renter/dir/" + directory, {}, {{"message", "no file known"}},
|
||||
api_error::comm_error, true);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(::PathIsDirectory(&full_directory[0]));
|
||||
EXPECT_TRUE(::CreateDirectoryA(&full_directory[0], nullptr));
|
||||
EXPECT_TRUE(::PathIsDirectory(&full_directory[0]));
|
||||
EXPECT_TRUE(::MoveFile(&full_directory[0], &full_directory2[0]));
|
||||
EXPECT_FALSE(::PathIsDirectory(&full_directory[0]));
|
||||
EXPECT_TRUE(::PathIsDirectory(&full_directory2[0]));
|
||||
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.remove_return("post_params", "/renter/dir/" + directory);
|
||||
mock_comm.remove_return("get", "/renter/dir/" + directory2);
|
||||
mock_comm.remove_return("get", "/renter/file/" + directory2);
|
||||
mock_comm.remove_return("post_params", "/renter/dir/" + directory2);
|
||||
}
|
||||
}
|
||||
|
||||
static void get_set_basic_info_test(const std::size_t &idx, winfsp_test *test,
|
||||
const std::string &mount_point) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/renter/dir/setbasicinfo_file.txt", {},
|
||||
{{"message", "no file known"}}, api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/setbasicinfo_file.txt", {},
|
||||
{{"message", "no file known"}}, api_error::comm_error);
|
||||
mock_comm.push_return("post_params", "/renter/upload/setbasicinfo_file.txt", {}, {},
|
||||
api_error::success, true);
|
||||
|
||||
mock_comm.push_return("get", "/renter/file/setbasicinfo_file.txt",
|
||||
RENTER_FILE_DATA("setbasicinfo_file.txt", 0), {}, api_error::success,
|
||||
true);
|
||||
}
|
||||
|
||||
const auto file = utils::path::combine(mount_point, {"setbasicinfo_file.txt"});
|
||||
auto handle = ::CreateFileA(&file[0], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr,
|
||||
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
EXPECT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
|
||||
SYSTEMTIME st{};
|
||||
::GetSystemTime(&st);
|
||||
st.wMinute = 0;
|
||||
|
||||
FILETIME test_ch_time{};
|
||||
st.wMinute++;
|
||||
::SystemTimeToFileTime(&st, &test_ch_time);
|
||||
|
||||
FILETIME test_cr_time{};
|
||||
st.wMinute++;
|
||||
::SystemTimeToFileTime(&st, &test_cr_time);
|
||||
|
||||
FILETIME test_la_time{};
|
||||
st.wMinute++;
|
||||
::SystemTimeToFileTime(&st, &test_la_time);
|
||||
|
||||
FILETIME test_lw_time{};
|
||||
st.wMinute++;
|
||||
::SystemTimeToFileTime(&st, &test_lw_time);
|
||||
|
||||
FILE_BASIC_INFO fbi{};
|
||||
fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
|
||||
fbi.ChangeTime.HighPart = test_ch_time.dwHighDateTime;
|
||||
fbi.ChangeTime.LowPart = test_ch_time.dwLowDateTime;
|
||||
fbi.CreationTime = *(LARGE_INTEGER *)&test_cr_time;
|
||||
fbi.LastAccessTime = *(LARGE_INTEGER *)&test_la_time;
|
||||
fbi.LastWriteTime = *(LARGE_INTEGER *)&test_lw_time;
|
||||
|
||||
EXPECT_TRUE(::SetFileInformationByHandle(handle, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO)));
|
||||
|
||||
FILE_BASIC_INFO fbi2{};
|
||||
EXPECT_TRUE(
|
||||
::GetFileInformationByHandleEx(handle, FileBasicInfo, &fbi2, sizeof(FILE_BASIC_INFO)));
|
||||
|
||||
EXPECT_EQ(0, memcmp(&fbi, &fbi2, sizeof(FILE_BASIC_INFO)));
|
||||
|
||||
std::cout << fbi.FileAttributes << " " << fbi.ChangeTime.QuadPart << " "
|
||||
<< fbi.CreationTime.QuadPart << " " << fbi.LastAccessTime.QuadPart << " "
|
||||
<< fbi.LastWriteTime.QuadPart << std::endl;
|
||||
std::cout << fbi2.FileAttributes << " " << fbi2.ChangeTime.QuadPart << " "
|
||||
<< fbi2.CreationTime.QuadPart << " " << fbi2.LastAccessTime.QuadPart << " "
|
||||
<< fbi2.LastWriteTime.QuadPart << std::endl;
|
||||
|
||||
EXPECT_TRUE(::CloseHandle(handle));
|
||||
}
|
||||
|
||||
static void overwrite_file_test(const std::size_t &idx, winfsp_test *test,
|
||||
const std::string &mount_point) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/renter/dir/test_overwrite.txt", {},
|
||||
{{"message", "no file known"}}, api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/dir/test_overwrite2.txt", {},
|
||||
{{"message", "no file known"}}, api_error::comm_error, true);
|
||||
mock_comm.push_return("get", "/renter/file/test_overwrite.txt", {},
|
||||
{{"message", "no file known"}}, api_error::comm_error);
|
||||
|
||||
mock_comm.push_return("post_params", "/renter/upload/test_overwrite.txt", {}, {},
|
||||
api_error::success, true);
|
||||
mock_comm.push_return("post_params", "/renter/upload/test_overwrite2.txt", {}, {},
|
||||
api_error::success, true);
|
||||
|
||||
mock_comm.push_return("post_params", "/renter/delete/test_overwrite2.txt", {}, {},
|
||||
api_error::success, true);
|
||||
}
|
||||
|
||||
const auto file = utils::path::combine("./", {"test_overwrite.txt"});
|
||||
auto handle = ::CreateFileA(&file[0], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
EXPECT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
const std::string data = "0123456789";
|
||||
DWORD bytes_written = 0;
|
||||
EXPECT_TRUE(
|
||||
::WriteFile(handle, &data[0], static_cast<DWORD>(data.size()), &bytes_written, nullptr));
|
||||
EXPECT_EQ(10, bytes_written);
|
||||
EXPECT_TRUE(::CloseHandle(handle));
|
||||
|
||||
if (bytes_written == 10) {
|
||||
const auto file2 = utils::path::combine(mount_point, {"test_overwrite2.txt"});
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.push_return("get", "/renter/file/test_overwrite2.txt", {},
|
||||
{{"message", "no file known"}}, api_error::comm_error);
|
||||
mock_comm.push_return("get", "/renter/file/test_overwrite.txt",
|
||||
RENTER_FILE_DATA("test_overwrite.txt", 0), {}, api_error::success,
|
||||
true);
|
||||
mock_comm.push_return("get", "/renter/file/test_overwrite2.txt",
|
||||
RENTER_FILE_DATA("test_overwrite2.txt", 0), {}, api_error::success,
|
||||
true);
|
||||
}
|
||||
EXPECT_TRUE(::CopyFile(&file[0], &file2[0], TRUE));
|
||||
|
||||
EXPECT_FALSE(::CopyFile(&file[0], &file2[0], TRUE));
|
||||
}
|
||||
}
|
||||
|
||||
if (idx == 0) {
|
||||
auto &mock_comm = test->mock_sia_comm_;
|
||||
mock_comm.remove_return("post_params", "/renter/upload/test_overwrite.txt");
|
||||
mock_comm.remove_return("post_params", "/renter/upload/test_overwrite2.txt");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(winfsp_test, all_tests) {
|
||||
if (PROVIDER_INDEX == 0) {
|
||||
for (std::size_t idx = 0; idx < provider_tests_.size(); idx++) {
|
||||
launch_app(("cmd.exe /c unittests.exe --gtest_filter=winfsp_test.all_tests "
|
||||
"--provider_index " +
|
||||
std::to_string(idx) + " > unittests" + std::to_string(idx) + ".log 2>&1"));
|
||||
}
|
||||
} else {
|
||||
const auto idx = PROVIDER_INDEX - 1;
|
||||
|
||||
std::string mount_point;
|
||||
const auto drive_args = mount_setup(idx, this, mount_point);
|
||||
|
||||
event_capture ec({"drive_mounted"});
|
||||
std::thread th([&] {
|
||||
const auto mounted = ec.wait_for_event("drive_mounted");
|
||||
EXPECT_TRUE(mounted);
|
||||
if (mounted) {
|
||||
root_creation_test(mount_point);
|
||||
{
|
||||
const auto file = create_test(idx, this, mount_point);
|
||||
delete_file_test(idx, this, file);
|
||||
}
|
||||
{
|
||||
const auto testDir = utils::path::combine(mount_point, {"TestDir"});
|
||||
create_directory_test(idx, this, testDir);
|
||||
remove_directory_test(idx, this, testDir);
|
||||
}
|
||||
write_file_test(idx, this, mount_point);
|
||||
read_file_test(idx, this, mount_point);
|
||||
rename_file_test(idx, this, mount_point);
|
||||
rename_directory_test(idx, this, mount_point);
|
||||
overwrite_file_test(idx, this, mount_point);
|
||||
get_set_basic_info_test(idx, this, mount_point);
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
unmount(idx, this, mount_point);
|
||||
}
|
||||
});
|
||||
|
||||
execute_mount(idx, this, drive_args, th);
|
||||
}
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user