refactor winfsp test
This commit is contained in:
parent
cdfbaa47b6
commit
b4d61649cb
@ -55,7 +55,6 @@ public:
|
|||||||
static std::unique_ptr<app_config> config;
|
static std::unique_ptr<app_config> config;
|
||||||
static std::filesystem::path current_directory;
|
static std::filesystem::path current_directory;
|
||||||
static std::unique_ptr<fuse_drive> drive;
|
static std::unique_ptr<fuse_drive> drive;
|
||||||
static lock_data lock_data_;
|
|
||||||
static std::string mount_location;
|
static std::string mount_location;
|
||||||
static std::unique_ptr<i_provider> provider;
|
static std::unique_ptr<i_provider> provider;
|
||||||
static std::string test_directory;
|
static std::string test_directory;
|
||||||
@ -194,15 +193,20 @@ public:
|
|||||||
std::cout << "mount command: " << mount_cmd << std::endl;
|
std::cout << "mount command: " << mount_cmd << std::endl;
|
||||||
ASSERT_EQ(0, system(mount_cmd.c_str()));
|
ASSERT_EQ(0, system(mount_cmd.c_str()));
|
||||||
std::this_thread::sleep_for(5s);
|
std::this_thread::sleep_for(5s);
|
||||||
EXPECT_EQ(0, system(("mount|grep \"" + mount_location + "\"").c_str()));
|
ASSERT_TRUE(utils::file::directory{mount_location}.exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void execute_unmount() {
|
static void execute_unmount() {
|
||||||
auto unmounted{false};
|
auto unmounted{false};
|
||||||
|
|
||||||
|
auto unmount_cmd =
|
||||||
|
"./repertory -dd \"" + config->get_data_directory() + "\" -unmount";
|
||||||
for (int i = 0; not unmounted && (i < 50); i++) {
|
for (int i = 0; not unmounted && (i < 50); i++) {
|
||||||
unmounted = (fuse_base::unmount(mount_location) == 0);
|
std::cout << "unmount command: " << unmount_cmd << std::endl;
|
||||||
|
ASSERT_EQ(0, system(unmount_cmd.c_str()));
|
||||||
|
unmounted = not utils::file::directory{mount_location}.exists();
|
||||||
if (not unmounted) {
|
if (not unmounted) {
|
||||||
std::this_thread::sleep_for(100ms);
|
std::this_thread::sleep_for(5s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,8 +255,6 @@ std::filesystem::path fuse_test<provider_t>::current_directory{};
|
|||||||
template <typename provider_t>
|
template <typename provider_t>
|
||||||
std::unique_ptr<fuse_drive> fuse_test<provider_t>::drive{};
|
std::unique_ptr<fuse_drive> fuse_test<provider_t>::drive{};
|
||||||
|
|
||||||
template <typename provider_t> lock_data fuse_test<provider_t>::lock_data_{};
|
|
||||||
|
|
||||||
template <typename provider_t>
|
template <typename provider_t>
|
||||||
std::string fuse_test<provider_t>::mount_location{};
|
std::string fuse_test<provider_t>::mount_location{};
|
||||||
|
|
||||||
@ -262,7 +264,7 @@ std::unique_ptr<i_provider> fuse_test<provider_t>::provider{};
|
|||||||
template <typename provider_t>
|
template <typename provider_t>
|
||||||
std::string fuse_test<provider_t>::test_directory;
|
std::string fuse_test<provider_t>::test_directory;
|
||||||
|
|
||||||
typedef ::testing::Types<s3_provider, sia_provider> fuse_provider_types;
|
using fuse_provider_types = ::testing::Types<s3_provider, sia_provider>;
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
#endif // !defined(_WIN32)
|
#endif // !defined(_WIN32)
|
||||||
|
@ -31,133 +31,186 @@
|
|||||||
#include "platform/platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
#include "providers/s3/s3_provider.hpp"
|
#include "providers/s3/s3_provider.hpp"
|
||||||
#include "providers/sia/sia_provider.hpp"
|
#include "providers/sia/sia_provider.hpp"
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
#include "utils/event_capture.hpp"
|
||||||
#include "utils/file_utils.hpp"
|
#include "utils/file_utils.hpp"
|
||||||
#include "utils/path.hpp"
|
#include "utils/path.hpp"
|
||||||
|
|
||||||
extern std::size_t PROVIDER_INDEX;
|
namespace {
|
||||||
|
std::atomic<std::size_t> idx{0U};
|
||||||
|
constexpr const auto SLEEP_SECONDS{1.5s};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
class winfsp_test : public ::testing::Test {
|
template <typename provider_t> class winfsp_test : public ::testing::Test {
|
||||||
public:
|
public:
|
||||||
lock_data lock_data_;
|
static std::string cfg_directory;
|
||||||
std::unique_ptr<app_config> config;
|
static std::unique_ptr<curl_comm> comm;
|
||||||
std::unique_ptr<curl_comm> comm;
|
static std::unique_ptr<app_config> config;
|
||||||
std::unique_ptr<i_provider> provider;
|
static std::filesystem::path current_directory;
|
||||||
std::unique_ptr<winfsp_drive> drive;
|
static std::unique_ptr<winfsp_drive> drive;
|
||||||
|
static std::string mount_location;
|
||||||
|
static std::unique_ptr<i_provider> provider;
|
||||||
|
static std::string test_directory;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override {
|
static void SetUpTestCase() {
|
||||||
if (PROVIDER_INDEX != 0) {
|
current_directory = std::filesystem::current_path();
|
||||||
if (PROVIDER_INDEX == 1) {
|
|
||||||
EXPECT_TRUE(utils::file::directory(
|
|
||||||
utils::path::combine(
|
|
||||||
test::get_test_output_dir(),
|
|
||||||
{"winfsp_test" + std::to_string(PROVIDER_INDEX)}))
|
|
||||||
.remove_recursively());
|
|
||||||
|
|
||||||
app_config src_cfg(
|
test_directory = utils::path::combine(
|
||||||
|
test::get_test_output_dir(),
|
||||||
|
{
|
||||||
|
"winfsp_test",
|
||||||
|
std::to_string(static_cast<std::uint8_t>(provider_t::type)),
|
||||||
|
});
|
||||||
|
mount_location = "U:";
|
||||||
|
|
||||||
|
cfg_directory = utils::path::combine(test_directory, {"cfg"});
|
||||||
|
ASSERT_TRUE(utils::file::directory(cfg_directory).create_directory());
|
||||||
|
|
||||||
|
config = std::make_unique<app_config>(provider_t::type, cfg_directory);
|
||||||
|
|
||||||
|
std::vector<std::string> drive_args{};
|
||||||
|
|
||||||
|
switch (provider_t::type) {
|
||||||
|
case provider_type::s3: {
|
||||||
|
{
|
||||||
|
app_config src_cfg{
|
||||||
provider_type::s3,
|
provider_type::s3,
|
||||||
utils::path::combine(test::get_test_input_dir(), {"storj"}));
|
utils::path::combine(test::get_test_input_dir(), {"storj"}),
|
||||||
config = std::make_unique<app_config>(
|
};
|
||||||
provider_type::s3,
|
config->set_enable_drive_events(true);
|
||||||
utils::path::combine(
|
|
||||||
test::get_test_output_dir(),
|
|
||||||
{"winfsp_test" + std::to_string(PROVIDER_INDEX)}));
|
|
||||||
EXPECT_FALSE(config
|
|
||||||
->set_value_by_name("S3Config.AccessKey",
|
|
||||||
src_cfg.get_s3_config().access_key)
|
|
||||||
.empty());
|
|
||||||
EXPECT_FALSE(config
|
|
||||||
->set_value_by_name("S3Config.SecretKey",
|
|
||||||
src_cfg.get_s3_config().secret_key)
|
|
||||||
.empty());
|
|
||||||
EXPECT_FALSE(config
|
|
||||||
->set_value_by_name("S3Config.Region",
|
|
||||||
src_cfg.get_s3_config().region)
|
|
||||||
.empty());
|
|
||||||
EXPECT_FALSE(
|
|
||||||
config
|
|
||||||
->set_value_by_name("S3Config.EncryptionToken",
|
|
||||||
src_cfg.get_s3_config().encryption_token)
|
|
||||||
.empty());
|
|
||||||
EXPECT_FALSE(
|
|
||||||
config
|
|
||||||
->set_value_by_name("S3Config.URL", src_cfg.get_s3_config().url)
|
|
||||||
.empty());
|
|
||||||
EXPECT_FALSE(
|
|
||||||
config->set_value_by_name("S3Config.Bucket", "repertory").empty());
|
|
||||||
config->set_event_level(event_level::trace);
|
config->set_event_level(event_level::trace);
|
||||||
config->set_enable_drive_events(true);
|
config->set_s3_config(src_cfg.get_s3_config());
|
||||||
event_system::instance().start();
|
|
||||||
|
|
||||||
comm = std::make_unique<curl_comm>(config->get_s3_config());
|
|
||||||
provider = std::make_unique<s3_provider>(*config, *comm);
|
|
||||||
drive = std::make_unique<winfsp_drive>(*config, lock_data_, *provider);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PROVIDER_INDEX == 2) {
|
comm = std::make_unique<curl_comm>(config->get_s3_config());
|
||||||
EXPECT_TRUE(utils::file::directory(
|
drive_args = std::vector<std::string>({
|
||||||
utils::path::combine(
|
"-s3",
|
||||||
test::get_test_output_dir(),
|
"-na",
|
||||||
{"winfsp_test" + std::to_string(PROVIDER_INDEX)}))
|
"storj",
|
||||||
.remove_recursively());
|
});
|
||||||
|
} break;
|
||||||
|
|
||||||
app_config src_cfg(
|
case provider_type::sia: {
|
||||||
|
{
|
||||||
|
app_config src_cfg{
|
||||||
provider_type::sia,
|
provider_type::sia,
|
||||||
utils::path::combine(test::get_test_input_dir(), {"sia"}));
|
utils::path::combine(test::get_test_input_dir(), {"sia"}),
|
||||||
config = std::make_unique<app_config>(
|
};
|
||||||
provider_type::sia,
|
config->set_enable_drive_events(true);
|
||||||
utils::path::combine(
|
|
||||||
test::get_test_output_dir(),
|
|
||||||
{"winfsp_test" + std::to_string(PROVIDER_INDEX)}));
|
|
||||||
[[maybe_unused]] auto val = config->set_value_by_name(
|
|
||||||
"HostConfig.AgentString", src_cfg.get_host_config().agent_string);
|
|
||||||
EXPECT_FALSE(
|
|
||||||
config
|
|
||||||
->set_value_by_name("HostConfig.ApiPassword",
|
|
||||||
src_cfg.get_host_config().api_password)
|
|
||||||
.empty());
|
|
||||||
EXPECT_FALSE(config
|
|
||||||
->set_value_by_name(
|
|
||||||
"HostConfig.ApiPort",
|
|
||||||
std::to_string(src_cfg.get_host_config().api_port))
|
|
||||||
.empty());
|
|
||||||
EXPECT_FALSE(
|
|
||||||
config
|
|
||||||
->set_value_by_name("HostConfig.HostNameOrIp",
|
|
||||||
src_cfg.get_host_config().host_name_or_ip)
|
|
||||||
.empty());
|
|
||||||
config->set_event_level(event_level::debug);
|
config->set_event_level(event_level::debug);
|
||||||
config->set_enable_drive_events(true);
|
config->set_host_config(src_cfg.get_host_config());
|
||||||
event_system::instance().start();
|
|
||||||
|
|
||||||
comm = std::make_unique<curl_comm>(config->get_host_config());
|
|
||||||
provider = std::make_unique<sia_provider>(*config, *comm);
|
|
||||||
drive = std::make_unique<winfsp_drive>(*config, lock_data_, *provider);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comm = std::make_unique<curl_comm>(config->get_host_config());
|
||||||
|
} break;
|
||||||
|
// case 0U: {
|
||||||
|
// config =
|
||||||
|
// std::make_unique<app_config>(provider_type::encrypt,
|
||||||
|
// cfg_directory);
|
||||||
|
// {
|
||||||
|
// app_config src_cfg(
|
||||||
|
// provider_type::s3,
|
||||||
|
// utils::path::combine(test::get_test_input_dir(), {"encrypt"}));
|
||||||
|
// config->set_enable_drive_events(true);
|
||||||
|
// config->set_event_level(event_level::trace);
|
||||||
|
// config->set_s3_config(src_cfg.get_s3_config());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// comm = std::make_unique<curl_comm>(config->get_s3_config());
|
||||||
|
// provider = std::make_unique<s3_provider>(*config, *comm);
|
||||||
|
// drive_args = std::vector<std::string>({"-en"});
|
||||||
|
// } break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("provider type is not implemented");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
provider = std::make_unique<provider_t>(*config, *comm);
|
||||||
|
drive_args.push_back(mount_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown() override {
|
static void TearDownTestCase() {
|
||||||
if (PROVIDER_INDEX != 0) {
|
execute_unmount();
|
||||||
drive.reset();
|
std::filesystem::current_path(current_directory);
|
||||||
provider.reset();
|
[[maybe_unused]] auto ret =
|
||||||
comm.reset();
|
utils::file::directory(test_directory).remove_recursively();
|
||||||
config.reset();
|
/* if (PROVIDER_INDEX != 0) {
|
||||||
|
drive.reset();
|
||||||
|
provider.reset();
|
||||||
|
comm.reset();
|
||||||
|
config.reset();
|
||||||
|
|
||||||
event_system::instance().stop();
|
event_system::instance().stop();
|
||||||
EXPECT_TRUE(utils::file::directory(
|
EXPECT_TRUE(utils::file::directory(
|
||||||
utils::path::combine(
|
utils::path::combine(
|
||||||
test::get_test_output_dir(),
|
test::get_test_output_dir(),
|
||||||
{"winfsp_test" + std::to_string(PROVIDER_INDEX)}))
|
{"winfsp_test" + std::to_string(PROVIDER_INDEX)}))
|
||||||
.remove_recursively());
|
.remove_recursively());
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void delete_file_and_test(const std::string &file) {
|
||||||
|
event_capture ec({"file_removed"});
|
||||||
|
EXPECT_TRUE(utils::file::file(file).remove());
|
||||||
|
ec.wait_for_empty();
|
||||||
|
|
||||||
|
EXPECT_FALSE(utils::file::file(file).exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void execute_mount(auto &&drive_args) {
|
||||||
|
auto mount_cmd = ".\\repertory.exe -dd \"" + config->get_data_directory() +
|
||||||
|
"\"" + " " + utils::string::join(drive_args, ' ');
|
||||||
|
std::cout << "mount command: " << mount_cmd << std::endl;
|
||||||
|
ASSERT_EQ(0, system(mount_cmd.c_str()));
|
||||||
|
std::this_thread::sleep_for(5s);
|
||||||
|
ASSERT_TRUE(utils::file::directory{mount_location}.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void execute_unmount() {
|
||||||
|
auto unmounted{false};
|
||||||
|
|
||||||
|
auto unmount_cmd = ".\\repertory.exe -dd \"" +
|
||||||
|
config->get_data_directory() + "\" -unmount";
|
||||||
|
for (int i = 0; not unmounted && (i < 50); i++) {
|
||||||
|
std::cout << "unmount command: " << unmount_cmd << std::endl;
|
||||||
|
ASSERT_EQ(0, system(unmount_cmd.c_str()));
|
||||||
|
unmounted = not utils::file::directory{mount_location}.exists();
|
||||||
|
if (not unmounted) {
|
||||||
|
std::this_thread::sleep_for(5s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPECT_TRUE(unmounted);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename provider_t>
|
||||||
|
std::string winfsp_test<provider_t>::cfg_directory;
|
||||||
|
|
||||||
|
template <typename provider_t>
|
||||||
|
std::unique_ptr<app_config> winfsp_test<provider_t>::config;
|
||||||
|
|
||||||
|
template <typename provider_t>
|
||||||
|
std::filesystem::path winfsp_test<provider_t>::current_directory;
|
||||||
|
|
||||||
|
template <typename provider_t>
|
||||||
|
std::unique_ptr<curl_comm> winfsp_test<provider_t>::comm;
|
||||||
|
|
||||||
|
template <typename provider_t>
|
||||||
|
std::unique_ptr<i_provider> winfsp_test<provider_t>::provider;
|
||||||
|
|
||||||
|
template <typename provider_t>
|
||||||
|
std::string winfsp_test<provider_t>::test_directory;
|
||||||
|
|
||||||
|
template <typename provider_t>
|
||||||
|
std::unique_ptr<winfsp_drive> winfsp_test<provider_t>::drive;
|
||||||
|
|
||||||
|
using winfsp_provider_types = ::testing::Types<s3_provider, sia_provider>;
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
#endif
|
#endif // defined(_WIN32)
|
||||||
#endif // REPERTORY_TEST_INCLUDE_FIXTURES_WINFSP_FIXTURE_HPP
|
#endif // REPERTORY_TEST_INCLUDE_FIXTURES_WINFSP_FIXTURE_HPP
|
||||||
|
413
repertory/repertory_test/src/winfsp_drive_test.cpp
Normal file
413
repertory/repertory_test/src/winfsp_drive_test.cpp
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <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 0
|
||||||
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
#include "fixtures/winfsp_fixture.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, info, false, std::string, test_name, TN, E_FROM_STRING);
|
||||||
|
// #define TEST_HEADER(func) \
|
||||||
|
// event_system::instance().raise<test_begin>( \
|
||||||
|
// std::string(func) + \
|
||||||
|
// "\r\n***********************\r\n***********************")
|
||||||
|
//
|
||||||
|
// static auto mount_setup(std::string &mount_point) {
|
||||||
|
// mount_point = "U:";
|
||||||
|
// return std::vector<std::string>({"unittests", "-f", mount_point});
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void execute_mount(winfsp_test *test,
|
||||||
|
// const std::vector<std::string> &drive_args,
|
||||||
|
// std::thread &th) {
|
||||||
|
// ASSERT_EQ(0, test->drive->mount(drive_args));
|
||||||
|
// th.join();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void unmount(winfsp_test *test, const std::string &mount_point) {
|
||||||
|
// test->drive->shutdown();
|
||||||
|
// auto mounted = utils::file::directory(mount_point).exists();
|
||||||
|
// for (auto i = 0; mounted && (i < 50); i++) {
|
||||||
|
// std::this_thread::sleep_for(100ms);
|
||||||
|
// mounted = utils::file::directory(mount_point).exists();
|
||||||
|
// }
|
||||||
|
// EXPECT_FALSE(utils::file::directory(mount_point).exists());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void root_creation_test(const std::string &mount_point) {
|
||||||
|
// TEST_HEADER(__FUNCTION__);
|
||||||
|
// WIN32_FILE_ATTRIBUTE_DATA ad{};
|
||||||
|
// EXPECT_TRUE(
|
||||||
|
// ::GetFileAttributesEx(mount_point.c_str(), GetFileExInfoStandard, &ad));
|
||||||
|
// EXPECT_EQ(FILE_ATTRIBUTE_DIRECTORY, ad.dwFileAttributes);
|
||||||
|
// EXPECT_EQ(0, ad.nFileSizeHigh);
|
||||||
|
// EXPECT_EQ(0, ad.nFileSizeLow);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static auto create_test(winfsp_test *test, const std::string &mount_point) {
|
||||||
|
// TEST_HEADER(__FUNCTION__);
|
||||||
|
//
|
||||||
|
// 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::file(file).exists());
|
||||||
|
//
|
||||||
|
// auto opt_size = utils::file::file(file).size();
|
||||||
|
// EXPECT_TRUE(opt_size.has_value());
|
||||||
|
// EXPECT_EQ(0, opt_size.value());
|
||||||
|
//
|
||||||
|
// std::string attr;
|
||||||
|
// EXPECT_EQ(api_error::success, test->provider->get_item_meta(
|
||||||
|
// "/test_create.txt", META_ATTRIBUTES, attr));
|
||||||
|
// EXPECT_EQ(FILE_ATTRIBUTE_NORMAL, utils::string::to_uint32(attr));
|
||||||
|
//
|
||||||
|
// return file;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void delete_file_test(const std::string &file) {
|
||||||
|
// TEST_HEADER(__FUNCTION__);
|
||||||
|
// event_capture ec({"file_removed"});
|
||||||
|
// EXPECT_TRUE(utils::file::file(file).remove());
|
||||||
|
// EXPECT_FALSE(utils::file::file(file).exists());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void create_directory_test(const std::string &directory) {
|
||||||
|
// TEST_HEADER(__FUNCTION__);
|
||||||
|
//
|
||||||
|
// EXPECT_FALSE(::PathIsDirectory(&directory[0]));
|
||||||
|
// EXPECT_TRUE(::CreateDirectoryA(&directory[0], nullptr));
|
||||||
|
// EXPECT_TRUE(::PathIsDirectory(&directory[0]));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void remove_directory_test(const std::string &directory) {
|
||||||
|
// TEST_HEADER(__FUNCTION__);
|
||||||
|
//
|
||||||
|
// event_capture ec({"directory_removed"});
|
||||||
|
// EXPECT_TRUE(::PathIsDirectory(&directory[0]));
|
||||||
|
// EXPECT_TRUE(::RemoveDirectoryA(&directory[0]));
|
||||||
|
// EXPECT_FALSE(::PathIsDirectory(&directory[0]));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void write_file_test(const std::string &mount_point) {
|
||||||
|
// TEST_HEADER(__FUNCTION__);
|
||||||
|
//
|
||||||
|
// 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::file(file).exists());
|
||||||
|
//
|
||||||
|
// auto opt_size = utils::file::file(file).size();
|
||||||
|
// EXPECT_TRUE(opt_size.has_value());
|
||||||
|
// EXPECT_EQ(10U, opt_size.value());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void read_file_test(const std::string &mount_point) {
|
||||||
|
// TEST_HEADER(__FUNCTION__);
|
||||||
|
//
|
||||||
|
// 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);
|
||||||
|
//
|
||||||
|
// data_buffer 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));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void rename_file_test(winfsp_test *test,
|
||||||
|
// const std::string &mount_point) {
|
||||||
|
// TEST_HEADER(__FUNCTION__);
|
||||||
|
// 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));
|
||||||
|
//
|
||||||
|
// api_meta_map meta1{};
|
||||||
|
// EXPECT_EQ(api_error::success,
|
||||||
|
// test->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]));
|
||||||
|
//
|
||||||
|
// EXPECT_TRUE(utils::file::file(file2).exists());
|
||||||
|
// EXPECT_FALSE(utils::file::file(file).exists());
|
||||||
|
//
|
||||||
|
// api_meta_map meta2{};
|
||||||
|
// EXPECT_EQ(api_error::success,
|
||||||
|
// test->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, test->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,
|
||||||
|
// test->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,
|
||||||
|
// test->provider->get_item_meta("/rename_file.txt", meta2));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void rename_directory_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});
|
||||||
|
//
|
||||||
|
// 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]));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void get_set_basic_info_test(const std::string &mount_point) {
|
||||||
|
// TEST_HEADER(__FUNCTION__);
|
||||||
|
//
|
||||||
|
// 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::string &mount_point) {
|
||||||
|
// TEST_HEADER(__FUNCTION__);
|
||||||
|
//
|
||||||
|
// 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"});
|
||||||
|
// EXPECT_TRUE(::CopyFile(&file[0], &file2[0], TRUE));
|
||||||
|
//
|
||||||
|
// EXPECT_FALSE(::CopyFile(&file[0], &file2[0], TRUE));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// TEST_F(winfsp_test, all_tests) {
|
||||||
|
// if (PROVIDER_INDEX == 0) {
|
||||||
|
// for (std::size_t idx = 0U; idx < 2U; 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"));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (PROVIDER_INDEX == 1U) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// std::string mount_point;
|
||||||
|
// const auto drive_args = mount_setup(mount_point);
|
||||||
|
//
|
||||||
|
// event_capture ec({
|
||||||
|
// "drive_mounted",
|
||||||
|
// "drive_unmounted",
|
||||||
|
// "drive_unmount_pending",
|
||||||
|
// "drive_mount_result",
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// 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(this, mount_point);
|
||||||
|
// delete_file_test(file);
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// const auto dir = utils::path::combine(mount_point, {"TestDir"});
|
||||||
|
// create_directory_test(dir);
|
||||||
|
// remove_directory_test(dir);
|
||||||
|
// }
|
||||||
|
// write_file_test(mount_point);
|
||||||
|
// read_file_test(mount_point);
|
||||||
|
// // TODO enable after rename support is available
|
||||||
|
// // rename_file_test(this, mount_point);
|
||||||
|
// // rename_directory_test(mount_point);
|
||||||
|
// overwrite_file_test(mount_point);
|
||||||
|
// get_set_basic_info_test(mount_point);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (mounted) {
|
||||||
|
// unmount(this, mount_point);
|
||||||
|
// ec.wait_for_empty();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// execute_mount(this, drive_args, th);
|
||||||
|
// }
|
||||||
|
|
||||||
|
TYPED_TEST_CASE(winfsp_test, winfsp_provider_types);
|
||||||
|
|
||||||
|
TYPED_TEST(winfsp_test, root_is_created) {
|
||||||
|
WIN32_FILE_ATTRIBUTE_DATA ad{};
|
||||||
|
ASSERT_TRUE(
|
||||||
|
::GetFileAttributesEx(mount_location.c_str(), GetFileExInfoStandard, &ad));
|
||||||
|
EXPECT_EQ(FILE_ATTRIBUTE_DIRECTORY, ad.dwFileAttributes);
|
||||||
|
EXPECT_EQ(0, ad.nFileSizeHigh);
|
||||||
|
EXPECT_EQ(0, ad.nFileSizeLow);
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(winfsp_test, can_create_and_delete_file) {
|
||||||
|
auto file = utils::path::combine(mount_location, {"test_create.txt"});
|
||||||
|
auto handle = ::CreateFileA(file.c_str(), 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::file(file).exists());
|
||||||
|
|
||||||
|
auto opt_size = utils::file::file(file).size();
|
||||||
|
EXPECT_TRUE(opt_size.has_value());
|
||||||
|
EXPECT_EQ(0, opt_size.value());
|
||||||
|
|
||||||
|
std::string attr;
|
||||||
|
EXPECT_EQ(api_error::success, provider->get_item_meta(
|
||||||
|
"/test_create.txt", META_ATTRIBUTES, attr));
|
||||||
|
EXPECT_EQ(FILE_ATTRIBUTE_NORMAL, utils::string::to_uint32(attr));
|
||||||
|
|
||||||
|
delete_file_and_test(file);
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
#endif // 0
|
@ -1,385 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright <2018-2024> <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 0
|
|
||||||
#if defined(_WIN32)
|
|
||||||
|
|
||||||
#include "test_common.hpp"
|
|
||||||
|
|
||||||
#include "fixtures/winfsp_fixture.hpp"
|
|
||||||
#include "types/repertory.hpp"
|
|
||||||
#include "utils/event_capture.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, info, false, std::string, test_name, TN, E_FROM_STRING);
|
|
||||||
#define TEST_HEADER(func) \
|
|
||||||
event_system::instance().raise<test_begin>( \
|
|
||||||
std::string(func) + \
|
|
||||||
"\r\n***********************\r\n***********************")
|
|
||||||
|
|
||||||
static auto mount_setup(std::string &mount_point) {
|
|
||||||
mount_point = "U:";
|
|
||||||
return std::vector<std::string>({"unittests", "-f", mount_point});
|
|
||||||
}
|
|
||||||
|
|
||||||
static void execute_mount(winfsp_test *test,
|
|
||||||
const std::vector<std::string> &drive_args,
|
|
||||||
std::thread &th) {
|
|
||||||
ASSERT_EQ(0, test->drive->mount(drive_args));
|
|
||||||
th.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void unmount(winfsp_test *test, const std::string &mount_point) {
|
|
||||||
test->drive->shutdown();
|
|
||||||
auto mounted = utils::file::directory(mount_point).exists();
|
|
||||||
for (auto i = 0; mounted && (i < 50); i++) {
|
|
||||||
std::this_thread::sleep_for(100ms);
|
|
||||||
mounted = utils::file::directory(mount_point).exists();
|
|
||||||
}
|
|
||||||
EXPECT_FALSE(utils::file::directory(mount_point).exists());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void root_creation_test(const std::string &mount_point) {
|
|
||||||
TEST_HEADER(__FUNCTION__);
|
|
||||||
WIN32_FILE_ATTRIBUTE_DATA ad{};
|
|
||||||
EXPECT_TRUE(
|
|
||||||
::GetFileAttributesEx(mount_point.c_str(), GetFileExInfoStandard, &ad));
|
|
||||||
EXPECT_EQ(FILE_ATTRIBUTE_DIRECTORY, ad.dwFileAttributes);
|
|
||||||
EXPECT_EQ(0, ad.nFileSizeHigh);
|
|
||||||
EXPECT_EQ(0, ad.nFileSizeLow);
|
|
||||||
}
|
|
||||||
|
|
||||||
static auto create_test(winfsp_test *test, const std::string &mount_point) {
|
|
||||||
TEST_HEADER(__FUNCTION__);
|
|
||||||
|
|
||||||
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::file(file).exists());
|
|
||||||
|
|
||||||
auto opt_size = utils::file::file(file).size();
|
|
||||||
EXPECT_TRUE(opt_size.has_value());
|
|
||||||
EXPECT_EQ(0, opt_size.value());
|
|
||||||
|
|
||||||
std::string attr;
|
|
||||||
EXPECT_EQ(api_error::success, test->provider->get_item_meta(
|
|
||||||
"/test_create.txt", META_ATTRIBUTES, attr));
|
|
||||||
EXPECT_EQ(FILE_ATTRIBUTE_NORMAL, utils::string::to_uint32(attr));
|
|
||||||
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void delete_file_test(const std::string &file) {
|
|
||||||
TEST_HEADER(__FUNCTION__);
|
|
||||||
event_capture ec({"file_removed"});
|
|
||||||
EXPECT_TRUE(utils::file::file(file).remove());
|
|
||||||
EXPECT_FALSE(utils::file::file(file).exists());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void create_directory_test(const std::string &directory) {
|
|
||||||
TEST_HEADER(__FUNCTION__);
|
|
||||||
|
|
||||||
EXPECT_FALSE(::PathIsDirectory(&directory[0]));
|
|
||||||
EXPECT_TRUE(::CreateDirectoryA(&directory[0], nullptr));
|
|
||||||
EXPECT_TRUE(::PathIsDirectory(&directory[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void remove_directory_test(const std::string &directory) {
|
|
||||||
TEST_HEADER(__FUNCTION__);
|
|
||||||
|
|
||||||
event_capture ec({"directory_removed"});
|
|
||||||
EXPECT_TRUE(::PathIsDirectory(&directory[0]));
|
|
||||||
EXPECT_TRUE(::RemoveDirectoryA(&directory[0]));
|
|
||||||
EXPECT_FALSE(::PathIsDirectory(&directory[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void write_file_test(const std::string &mount_point) {
|
|
||||||
TEST_HEADER(__FUNCTION__);
|
|
||||||
|
|
||||||
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::file(file).exists());
|
|
||||||
|
|
||||||
auto opt_size = utils::file::file(file).size();
|
|
||||||
EXPECT_TRUE(opt_size.has_value());
|
|
||||||
EXPECT_EQ(10U, opt_size.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void read_file_test(const std::string &mount_point) {
|
|
||||||
TEST_HEADER(__FUNCTION__);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
data_buffer 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rename_file_test(winfsp_test *test,
|
|
||||||
const std::string &mount_point) {
|
|
||||||
TEST_HEADER(__FUNCTION__);
|
|
||||||
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));
|
|
||||||
|
|
||||||
api_meta_map meta1{};
|
|
||||||
EXPECT_EQ(api_error::success,
|
|
||||||
test->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]));
|
|
||||||
|
|
||||||
EXPECT_TRUE(utils::file::file(file2).exists());
|
|
||||||
EXPECT_FALSE(utils::file::file(file).exists());
|
|
||||||
|
|
||||||
api_meta_map meta2{};
|
|
||||||
EXPECT_EQ(api_error::success,
|
|
||||||
test->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, test->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,
|
|
||||||
test->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,
|
|
||||||
test->provider->get_item_meta("/rename_file.txt", meta2));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rename_directory_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});
|
|
||||||
|
|
||||||
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]));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void get_set_basic_info_test(const std::string &mount_point) {
|
|
||||||
TEST_HEADER(__FUNCTION__);
|
|
||||||
|
|
||||||
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::string &mount_point) {
|
|
||||||
TEST_HEADER(__FUNCTION__);
|
|
||||||
|
|
||||||
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"});
|
|
||||||
EXPECT_TRUE(::CopyFile(&file[0], &file2[0], TRUE));
|
|
||||||
|
|
||||||
EXPECT_FALSE(::CopyFile(&file[0], &file2[0], TRUE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(winfsp_test, all_tests) {
|
|
||||||
if (PROVIDER_INDEX == 0) {
|
|
||||||
for (std::size_t idx = 0U; idx < 2U; 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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PROVIDER_INDEX == 1U) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string mount_point;
|
|
||||||
const auto drive_args = mount_setup(mount_point);
|
|
||||||
|
|
||||||
event_capture ec({
|
|
||||||
"drive_mounted",
|
|
||||||
"drive_unmounted",
|
|
||||||
"drive_unmount_pending",
|
|
||||||
"drive_mount_result",
|
|
||||||
});
|
|
||||||
|
|
||||||
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(this, mount_point);
|
|
||||||
delete_file_test(file);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const auto dir = utils::path::combine(mount_point, {"TestDir"});
|
|
||||||
create_directory_test(dir);
|
|
||||||
remove_directory_test(dir);
|
|
||||||
}
|
|
||||||
write_file_test(mount_point);
|
|
||||||
read_file_test(mount_point);
|
|
||||||
// TODO enable after rename support is available
|
|
||||||
// rename_file_test(this, mount_point);
|
|
||||||
// rename_directory_test(mount_point);
|
|
||||||
overwrite_file_test(mount_point);
|
|
||||||
get_set_basic_info_test(mount_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mounted) {
|
|
||||||
unmount(this, mount_point);
|
|
||||||
ec.wait_for_empty();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
execute_mount(this, drive_args, th);
|
|
||||||
}
|
|
||||||
} // namespace repertory
|
|
||||||
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
#endif // 0
|
|
Loading…
x
Reference in New Issue
Block a user