winfsp unit tests and fixes
This commit is contained in:
parent
2df84f53ed
commit
69d190e485
@ -40,25 +40,25 @@ public:
|
||||
|
||||
[[nodiscard]] virtual auto get_filesystem_item() const -> filesystem_item = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_open_data() -> std::map<std::uint64_t, open_file_data> & = 0;
|
||||
[[nodiscard]] virtual auto get_open_data()
|
||||
-> std::map<std::uint64_t, open_file_data> & = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_open_data() const -> const std::map<std::uint64_t, open_file_data> & = 0;
|
||||
[[nodiscard]] virtual auto get_open_data() const
|
||||
-> const std::map<std::uint64_t, open_file_data> & = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_open_data(std::uint64_t handle) -> open_file_data & = 0;
|
||||
[[nodiscard]] virtual auto get_open_data(std::uint64_t handle)
|
||||
-> open_file_data & = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_open_data(std::uint64_t handle) const -> const open_file_data & = 0;
|
||||
[[nodiscard]] virtual auto get_open_data(std::uint64_t handle) const
|
||||
-> const open_file_data & = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_open_file_count() const -> std::size_t = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_read_state() const -> boost::dynamic_bitset<> = 0;
|
||||
[[nodiscard]] virtual auto get_read_state() const
|
||||
-> boost::dynamic_bitset<> = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_read_state(std::size_t chunk) const -> bool = 0;
|
||||
[[nodiscard]] virtual auto get_read_state(std::size_t chunk) const
|
||||
-> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_source_path() const -> std::string = 0;
|
||||
|
||||
@ -74,11 +74,11 @@ public:
|
||||
native_operation_callback callback) -> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto read(std::size_t read_size,
|
||||
std::uint64_t read_offset,
|
||||
data_buffer &data) -> api_error = 0;
|
||||
std::uint64_t read_offset, data_buffer &data)
|
||||
-> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
resize(std::uint64_t new_file_size) -> api_error = 0;
|
||||
[[nodiscard]] virtual auto resize(std::uint64_t new_file_size)
|
||||
-> api_error = 0;
|
||||
|
||||
virtual void set_api_path(const std::string &api_path) = 0;
|
||||
|
||||
@ -97,8 +97,8 @@ public:
|
||||
|
||||
virtual auto close() -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_handles() const -> std::vector<std::uint64_t> = 0;
|
||||
[[nodiscard]] virtual auto get_handles() const
|
||||
-> std::vector<std::uint64_t> = 0;
|
||||
|
||||
[[nodiscard]] virtual auto is_complete() const -> bool = 0;
|
||||
|
||||
@ -106,7 +106,7 @@ public:
|
||||
|
||||
[[nodiscard]] virtual auto is_write_supported() const -> bool = 0;
|
||||
|
||||
virtual void remove(std::uint64_t handle) = 0;
|
||||
virtual void remove(std::uint64_t handle, bool noQueue = false) = 0;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
|
@ -107,7 +107,7 @@ public:
|
||||
native_operation_callback callback)
|
||||
-> api_error override;
|
||||
|
||||
void remove(std::uint64_t handle) override;
|
||||
void remove(std::uint64_t handle, bool noQueue = false) override;
|
||||
|
||||
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
|
||||
data_buffer &data) -> api_error override;
|
||||
|
@ -185,7 +185,7 @@ public:
|
||||
|
||||
[[nodiscard]] auto is_modified() const -> bool override;
|
||||
|
||||
void remove(std::uint64_t handle) override;
|
||||
void remove(std::uint64_t handle, bool noQueue = false) override;
|
||||
|
||||
void set_api_path(const std::string &api_path) override;
|
||||
};
|
||||
|
@ -129,25 +129,39 @@ void file_manager::close(std::uint64_t handle) {
|
||||
recur_mutex_lock file_lock(open_file_mtx_);
|
||||
auto closeable_file = get_open_file_by_handle(handle);
|
||||
if (closeable_file) {
|
||||
closeable_file->remove(handle);
|
||||
closeable_file->remove(handle, false);
|
||||
}
|
||||
}
|
||||
|
||||
void file_manager::close_all(const std::string &api_path) {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
recur_mutex_lock file_lock(open_file_mtx_);
|
||||
std::vector<std::uint64_t> handles;
|
||||
|
||||
auto file_iter = open_file_lookup_.find(api_path);
|
||||
if (file_iter == open_file_lookup_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto closeable_file = file_iter->second;
|
||||
remove_upload(api_path, true);
|
||||
|
||||
handles = closeable_file->get_handles();
|
||||
for (auto &&handle : handles) {
|
||||
closeable_file->remove(handle);
|
||||
}
|
||||
auto closeable_file = file_iter->second;
|
||||
open_file_lookup_.erase(api_path);
|
||||
|
||||
auto handles = closeable_file->get_handles();
|
||||
for (auto &&handle : handles) {
|
||||
closeable_file->remove(handle, false);
|
||||
}
|
||||
|
||||
auto result = utils::db::sqlite::db_delete{*db_, resume_table}
|
||||
.where("api_path")
|
||||
.equals(api_path)
|
||||
.go();
|
||||
if (not result.ok()) {
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::error,
|
||||
"failed to remove from resume table");
|
||||
}
|
||||
}
|
||||
|
||||
void file_manager::close_timed_out_files() {
|
||||
@ -505,6 +519,7 @@ void file_manager::queue_upload(const std::string &api_path,
|
||||
if (not no_lock) {
|
||||
lock = std::make_unique<mutex_lock>(upload_mtx_);
|
||||
}
|
||||
|
||||
remove_upload(api_path, true);
|
||||
|
||||
auto result =
|
||||
@ -542,18 +557,6 @@ auto file_manager::remove_file(const std::string &api_path) -> api_error {
|
||||
|
||||
close_all(api_path);
|
||||
|
||||
remove_upload(api_path, true);
|
||||
|
||||
auto result = utils::db::sqlite::db_delete{*db_, resume_table}
|
||||
.where("api_path")
|
||||
.equals(api_path)
|
||||
.go();
|
||||
if (not result.ok()) {
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::error,
|
||||
"failed to remove from resume table");
|
||||
}
|
||||
|
||||
res = provider_.remove_file(api_path);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
|
@ -388,10 +388,10 @@ auto open_file::read(std::size_t read_size, std::uint64_t read_offset,
|
||||
: get_api_error();
|
||||
}
|
||||
|
||||
void open_file::remove(std::uint64_t handle) {
|
||||
void open_file::remove(std::uint64_t handle, bool noQueue) {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
open_file_base::remove(handle);
|
||||
if (modified_ && read_state_.all() &&
|
||||
open_file_base::remove(handle, noQueue);
|
||||
if (not noQueue && modified_ && read_state_.all() &&
|
||||
(get_api_error() == api_error::success)) {
|
||||
mgr_.queue_upload(*this);
|
||||
modified_ = false;
|
||||
|
@ -235,7 +235,7 @@ auto open_file_base::is_modified() const -> bool {
|
||||
return modified_;
|
||||
}
|
||||
|
||||
void open_file_base::remove(std::uint64_t handle) {
|
||||
void open_file_base::remove(std::uint64_t handle, bool /* noQueue */) {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
open_data_.erase(handle);
|
||||
event_system::instance().raise<filesystem_item_handle_closed>(
|
||||
|
@ -138,14 +138,15 @@ TYPED_TEST(winfsp_test, delete_can_delete_after_mapping) {
|
||||
auto seed = static_cast<unsigned>(std::time(nullptr));
|
||||
srand(seed);
|
||||
|
||||
SYSTEM_INFO sys_info{};
|
||||
::GetSystemInfo(&sys_info);
|
||||
|
||||
{
|
||||
auto handle = ::CreateFileA(file_path.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
ASSERT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
|
||||
SYSTEM_INFO sys_info{};
|
||||
::GetSystemInfo(&sys_info);
|
||||
|
||||
auto *mapping =
|
||||
::CreateFileMappingA(handle, nullptr, PAGE_READWRITE, 0,
|
||||
16U * sys_info.dwAllocationGranularity, nullptr);
|
||||
@ -155,35 +156,41 @@ TYPED_TEST(winfsp_test, delete_can_delete_after_mapping) {
|
||||
auto *view = ::MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
ASSERT_TRUE(view != nullptr);
|
||||
|
||||
for (PUINT8 ptr = view, end = ptr + 16U * sys_info.dwAllocationGranularity;
|
||||
for (PUINT8 ptr = reinterpret_cast<PUINT8>(view),
|
||||
end = ptr + 16U * sys_info.dwAllocationGranularity;
|
||||
end > ptr; ++ptr) {
|
||||
*ptr = rand() & 0xFF;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(::UnmapViewOfFile(view));
|
||||
EXPECT_TRUE(::CloseHandle(mapping));
|
||||
}
|
||||
|
||||
auto handle = ::CreateFileA(file_path2.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
{
|
||||
auto handle =
|
||||
::CreateFileA(file_path2.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
ASSERT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
|
||||
mapping =
|
||||
auto mapping =
|
||||
::CreateFileMappingA(handle, nullptr, PAGE_READWRITE, 0,
|
||||
16U * sys_info.dwAllocationGranularity, nullptr);
|
||||
EXPECT_TRUE(::CloseHandle(handle));
|
||||
ASSERT_TRUE(mapping != nullptr);
|
||||
|
||||
view = ::MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
auto view = ::MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
EXPECT_TRUE(view != nullptr);
|
||||
|
||||
for (PUINT8 ptr = view, end = ptr + 16U * sys_info.dwAllocationGranularity;
|
||||
for (PUINT8 ptr = reinterpret_cast<PUINT8>(view),
|
||||
end = ptr + 16U * sys_info.dwAllocationGranularity;
|
||||
end > ptr; ++ptr) {
|
||||
*ptr = rand() & 0xff;
|
||||
*ptr = rand() & 0xFF;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(::UnmapViewOfFile(view));
|
||||
EXPECT_TRUE(::CloseHandle(mapping));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(::DeleteFileA(file_path.c_str()));
|
||||
EXPECT_TRUE(::DeleteFileA(file_path2.c_str()));
|
||||
@ -192,6 +199,81 @@ TYPED_TEST(winfsp_test, delete_can_delete_after_mapping) {
|
||||
EXPECT_FALSE(::RemoveDirectoryA(dir_path.c_str()));
|
||||
EXPECT_EQ(ERROR_FILE_NOT_FOUND, ::GetLastError());
|
||||
}
|
||||
|
||||
TYPED_TEST(winfsp_test, delete_can_delete_on_close_after_mapping) {
|
||||
auto dir_path{
|
||||
utils::path::combine(this->mount_location, {"test_dir_3"}),
|
||||
};
|
||||
auto file_path{
|
||||
utils::path::combine(dir_path, {"test_file_3"}),
|
||||
};
|
||||
auto file_path2{
|
||||
utils::path::combine(dir_path, {"test_file2_3"}),
|
||||
};
|
||||
|
||||
ASSERT_TRUE(::CreateDirectoryA(dir_path.c_str(), nullptr));
|
||||
|
||||
auto seed = static_cast<unsigned>(std::time(nullptr));
|
||||
srand(seed);
|
||||
|
||||
SYSTEM_INFO sys_info{};
|
||||
::GetSystemInfo(&sys_info);
|
||||
|
||||
{
|
||||
auto handle = ::CreateFileA(
|
||||
file_path.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, nullptr);
|
||||
ASSERT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
|
||||
auto *mapping =
|
||||
::CreateFileMappingA(handle, nullptr, PAGE_READWRITE, 0,
|
||||
16U * sys_info.dwAllocationGranularity, nullptr);
|
||||
EXPECT_TRUE(mapping != nullptr);
|
||||
|
||||
auto *view = ::MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
EXPECT_TRUE(view != nullptr);
|
||||
for (PUINT8 ptr = reinterpret_cast<PUINT8>(view),
|
||||
end = ptr + 16U * sys_info.dwAllocationGranularity;
|
||||
end > ptr; ++ptr) {
|
||||
*ptr = rand() & 0xFF;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(::UnmapViewOfFile(view));
|
||||
EXPECT_TRUE(::CloseHandle(mapping));
|
||||
EXPECT_TRUE(::CloseHandle(handle));
|
||||
}
|
||||
|
||||
{
|
||||
auto handle = ::CreateFileA(
|
||||
file_path2.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, nullptr);
|
||||
ASSERT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
|
||||
auto *mapping =
|
||||
::CreateFileMappingA(handle, nullptr, PAGE_READWRITE, 0,
|
||||
16U * sys_info.dwAllocationGranularity, nullptr);
|
||||
EXPECT_TRUE(mapping != nullptr);
|
||||
|
||||
auto *view = MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
EXPECT_TRUE(view != nullptr);
|
||||
|
||||
for (PUINT8 ptr = reinterpret_cast<PUINT8>(view),
|
||||
end = ptr + 16U * sys_info.dwAllocationGranularity;
|
||||
end > ptr; ++ptr) {
|
||||
*ptr = rand() & 0xFF;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(::UnmapViewOfFile(view));
|
||||
EXPECT_TRUE(::CloseHandle(mapping));
|
||||
EXPECT_TRUE(::CloseHandle(handle));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(::RemoveDirectoryA(dir_path.c_str()));
|
||||
EXPECT_FALSE(::RemoveDirectoryA(dir_path.c_str()));
|
||||
EXPECT_EQ(ERROR_FILE_NOT_FOUND, ::GetLastError());
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
Loading…
x
Reference in New Issue
Block a user