[unit test] Complete FUSE unit tests #22
All checks were successful
Blockstorage/repertory/pipeline/head This commit looks good
BlockStorage/repertory/pipeline/head This commit looks good

This commit is contained in:
2025-09-20 08:12:42 -05:00
parent 415b28c7fe
commit 6b1891741b
3 changed files with 181 additions and 89 deletions

View File

@@ -34,33 +34,37 @@ private:
std::atomic<std::uint32_t> request_id_{0U};
public:
[[nodiscard]] auto get_drive_information() -> rpc_response;
[[nodiscard]] auto get_drive_information() const -> rpc_response;
[[nodiscard]] auto get_config() -> rpc_response;
[[nodiscard]] auto get_config() const -> rpc_response;
[[nodiscard]] auto get_config_value_by_name(const std::string &name)
[[nodiscard]] auto get_config_value_by_name(const std::string &name) const
-> rpc_response;
[[nodiscard]] auto get_directory_items(const std::string &api_path)
[[nodiscard]] auto get_directory_items(const std::string &api_path) const
-> rpc_response;
[[nodiscard]] auto get_item_info(const std::string &api_path) -> rpc_response;
[[nodiscard]] auto get_item_info(const std::string &api_path) const
-> rpc_response;
[[nodiscard]] auto get_open_files() -> rpc_response;
[[nodiscard]] auto get_open_files() const -> rpc_response;
[[nodiscard]] auto get_pinned_files() -> rpc_response;
[[nodiscard]] auto get_pinned_files() const -> rpc_response;
[[nodiscard]] auto pin_file(const std::string &api_path) -> rpc_response;
[[nodiscard]] auto pin_file(const std::string &api_path) const
-> rpc_response;
[[nodiscard]] auto pinned_status(const std::string &api_path) -> rpc_response;
[[nodiscard]] auto pinned_status(const std::string &api_path) const
-> rpc_response;
[[nodiscard]] auto set_config_value_by_name(const std::string &name,
const std::string &value)
const std::string &value) const
-> rpc_response;
[[nodiscard]] auto unmount() -> rpc_response;
[[nodiscard]] auto unmount() const -> rpc_response;
[[nodiscard]] auto unpin_file(const std::string &api_path) -> rpc_response;
[[nodiscard]] auto unpin_file(const std::string &api_path) const
-> rpc_response;
};
} // namespace repertory

View File

@@ -27,7 +27,7 @@
namespace repertory {
client::client(rpc_host_info host_info) : host_info_(std::move(host_info)) {}
auto client::get_drive_information() -> rpc_response {
auto client::get_drive_information() const -> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);
@@ -55,7 +55,7 @@ auto client::get_drive_information() -> rpc_response {
};
}
auto client::get_config() -> rpc_response {
auto client::get_config() const -> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);
@@ -83,7 +83,8 @@ auto client::get_config() -> rpc_response {
};
}
auto client::get_config_value_by_name(const std::string &name) -> rpc_response {
auto client::get_config_value_by_name(const std::string &name) const
-> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);
@@ -113,7 +114,8 @@ auto client::get_config_value_by_name(const std::string &name) -> rpc_response {
};
}
auto client::get_directory_items(const std::string &api_path) -> rpc_response {
auto client::get_directory_items(const std::string &api_path) const
-> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);
@@ -142,7 +144,7 @@ auto client::get_directory_items(const std::string &api_path) -> rpc_response {
};
}
auto client::get_item_info(const std::string &api_path) -> rpc_response {
auto client::get_item_info(const std::string &api_path) const -> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);
@@ -171,7 +173,7 @@ auto client::get_item_info(const std::string &api_path) -> rpc_response {
};
}
auto client::get_open_files() -> rpc_response {
auto client::get_open_files() const -> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);
@@ -199,7 +201,7 @@ auto client::get_open_files() -> rpc_response {
};
}
auto client::get_pinned_files() -> rpc_response {
auto client::get_pinned_files() const -> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);
@@ -227,7 +229,7 @@ auto client::get_pinned_files() -> rpc_response {
};
}
auto client::pin_file(const std::string &api_path) -> rpc_response {
auto client::pin_file(const std::string &api_path) const -> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);
@@ -256,7 +258,7 @@ auto client::pin_file(const std::string &api_path) -> rpc_response {
};
}
auto client::pinned_status(const std::string &api_path) -> rpc_response {
auto client::pinned_status(const std::string &api_path) const -> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);
@@ -286,7 +288,7 @@ auto client::pinned_status(const std::string &api_path) -> rpc_response {
}
auto client::set_config_value_by_name(const std::string &name,
const std::string &value)
const std::string &value) const
-> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);
@@ -321,7 +323,7 @@ auto client::set_config_value_by_name(const std::string &name,
};
}
auto client::unmount() -> rpc_response {
auto client::unmount() const -> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);
@@ -349,7 +351,7 @@ auto client::unmount() -> rpc_response {
};
}
auto client::unpin_file(const std::string &api_path) -> rpc_response {
auto client::unpin_file(const std::string &api_path) const -> rpc_response {
auto base_url =
"http://" + host_info_.host + ":" + std::to_string(host_info_.port);

View File

@@ -153,12 +153,20 @@ TYPED_TEST(fuse_test, rename_can_overwrite_existing_file) {
this->unlink_file_and_test(dst);
}
/*
TYPED_TEST(fuse_test, rename_file_cross_directory) {
auto dir1 = this->create_directory_and_test("dir_1");
auto dir2 = this->create_directory_and_test("dir_2");
TYPED_TEST(fuse_test, rename_can_rename_file_into_different_directory) {
if (this->current_provider != provider_type::sia) {
// TODO finish test
return;
}
auto src = this->create_file_and_test("dir_1/file.txt");
std::string dir_name_1{"dir_1"};
auto dir1 = this->create_directory_and_test(dir_name_1);
std::string dir_name_2{"dir_2"};
auto dir2 = this->create_directory_and_test(dir_name_2);
std::string file_name{dir_name_1 + "/rename"};
auto src = this->create_file_and_test(file_name);
std::string dst = utils::path::combine(dir2, {"moved.txt"});
overwrite_text(src, "CMDC");
@@ -176,8 +184,14 @@ TYPED_TEST(fuse_test, rename_file_cross_directory) {
this->rmdir_and_test(dir2);
}
TYPED_TEST(fuse_test, rename_file_same_path) {
auto src = this->create_file_and_test("rn_same.txt");
TYPED_TEST(fuse_test, rename_can_rename_file_to_same_path) {
if (this->current_provider != provider_type::sia) {
// TODO finish test
return;
}
std::string file_name{"rename"};
auto src = this->create_file_and_test(file_name);
overwrite_text(src, "CMDC");
errno = 0;
@@ -187,81 +201,143 @@ TYPED_TEST(fuse_test, rename_file_same_path) {
this->unlink_file_and_test(src);
}
TYPED_TEST(fuse_test, rename_file_source_missing_sets_errno) {
auto dst = this->create_file_and_test("rn_any_dest.txt");
auto missing = this->mount_location() + "/rn_missing_src.txt";
TYPED_TEST(fuse_test, rename_file_fails_if_source_file_does_not_exist) {
if (this->current_provider != provider_type::sia) {
// TODO finish test
return;
}
errno = 0;
EXPECT_EQ(-1, ::rename(missing.c_str(), dst.c_str()));
EXPECT_EQ(ENOENT, errno);
std::string src_file_name{"rename"};
auto src = this->create_file_path(src_file_name);
this->unlink_file_and_test(dst);
}
TYPED_TEST(fuse_test, rename_file_destination_parent_missing_sets_errno) {
auto src = this->create_file_and_test("rn_good_src.txt");
auto dst = this->mount_location() + "/rn_missing_parent/rn_dest.txt";
std::string dst_file_name{"rename_2"};
auto dst = this->create_file_path(dst_file_name);
errno = 0;
EXPECT_EQ(-1, ::rename(src.c_str(), dst.c_str()));
EXPECT_EQ(ENOENT, errno);
EXPECT_FALSE(utils::file::file{src}.exists());
EXPECT_FALSE(utils::file::file{dst}.exists());
}
TYPED_TEST(fuse_test,
rename_file_fails_if_destination_directory_does_not_exist) {
if (this->current_provider != provider_type::sia) {
// TODO finish test
return;
}
std::string file_name{"rename"};
auto src = this->create_file_and_test(file_name);
std::string dst_file_name{"cow_moose_doge_chicken/rename_2"};
auto dst = this->create_file_path(dst_file_name);
errno = 0;
EXPECT_EQ(-1, ::rename(src.c_str(), dst.c_str()));
EXPECT_EQ(ENOENT, errno);
EXPECT_FALSE(utils::file::file{dst}.exists());
this->unlink_file_and_test(src);
}
TYPED_TEST(fuse_test, rename_file_into_existing_directory_sets_eisdir) {
auto src = this->create_file_and_test("rn_file.txt");
auto dstdir = this->create_directory_and_test("rn_dest_dir");
TYPED_TEST(fuse_test, rename_file_fails_if_destination_is_directory) {
if (this->current_provider != provider_type::sia) {
// TODO finish test
return;
}
std::string file_name{"rename"};
auto src = this->create_file_and_test(file_name);
std::string dir_name{"dir"};
auto dest_dir = this->create_directory_and_test(dir_name);
errno = 0;
EXPECT_EQ(-1, ::rename(src.c_str(), dstdir.c_str()));
EXPECT_EQ(-1, ::rename(src.c_str(), dest_dir.c_str()));
EXPECT_EQ(EISDIR, errno);
EXPECT_TRUE(utils::file::directory{dest_dir}.exists());
this->unlink_file_and_test(src);
this->rmdir_and_test(dstdir);
this->rmdir_and_test(dest_dir);
}
TYPED_TEST(fuse_test, rename_file_no_write_on_source_parent_sets_eacces) {
auto srcdir = this->create_directory_and_test("rn_srcp");
auto dstdir = this->create_directory_and_test("rn_dstp");
auto src = this->create_file_and_test("rn_srcp/a.txt");
auto dst = dstdir + "/b.txt";
TYPED_TEST(fuse_test, rename_file_fails_if_source_directory_is_read_only) {
if (this->current_provider != provider_type::sia) {
// TODO finish test
return;
}
ASSERT_EQ(0, ::chmod(srcdir.c_str(), 0555));
std::string src_dir_name("dir_1");
auto src_dir = this->create_directory_and_test(src_dir_name);
std::string dest_dir_name("dir_2");
auto dest_dir = this->create_directory_and_test(dest_dir_name);
std::string file_name{src_dir_name + "/rename"};
auto src = this->create_file_and_test(file_name);
auto dst = dest_dir + "/dest";
ASSERT_EQ(0, ::chmod(src_dir.c_str(), 0555));
errno = 0;
EXPECT_EQ(-1, ::rename(src.c_str(), dst.c_str()));
EXPECT_EQ(EACCES, errno);
ASSERT_EQ(0, ::chmod(srcdir.c_str(), 0755));
EXPECT_FALSE(utils::file::file{dst}.exists());
ASSERT_EQ(0, ::chmod(src_dir.c_str(), 0755));
this->unlink_file_and_test(src);
this->rmdir_and_test(srcdir);
this->rmdir_and_test(dstdir);
this->rmdir_and_test(src_dir);
this->rmdir_and_test(dest_dir);
}
TYPED_TEST(fuse_test, rename_file_no_write_on_destination_parent_sets_eacces) {
auto srcdir = this->create_directory_and_test("rn_srcp2");
auto dstdir = this->create_directory_and_test("rn_dstp2");
auto src = this->create_file_and_test("rn_srcp2/a.txt");
auto dst = dstdir + "/b.txt";
TYPED_TEST(fuse_test, rename_file_fails_if_destination_directory_is_read_only) {
if (this->current_provider != provider_type::sia) {
// TODO finish test
return;
}
ASSERT_EQ(0, ::chmod(dstdir.c_str(), 0555));
std::string src_dir_name("dir_1");
auto src_dir = this->create_directory_and_test(src_dir_name);
std::string dest_dir_name("dir_2");
auto dest_dir = this->create_directory_and_test(dest_dir_name);
std::string file_name{src_dir_name + "/rename"};
auto src = this->create_file_and_test(file_name);
auto dst = dest_dir + "/dest";
ASSERT_EQ(0, ::chmod(dest_dir.c_str(), 0555));
errno = 0;
EXPECT_EQ(-1, ::rename(src.c_str(), dst.c_str()));
EXPECT_EQ(EACCES, errno);
ASSERT_EQ(0, ::chmod(dstdir.c_str(), 0755));
EXPECT_FALSE(utils::file::file{dst}.exists());
ASSERT_EQ(0, ::chmod(dest_dir.c_str(), 0755));
this->unlink_file_and_test(src);
this->rmdir_and_test(srcdir);
this->rmdir_and_test(dstdir);
this->rmdir_and_test(src_dir);
this->rmdir_and_test(dest_dir);
}
TYPED_TEST(fuse_test, rename_file_overwrite_readonly_destination_succeeds) {
auto src = this->create_file_and_test("rn_src_ro.txt");
auto dst = this->create_file_and_test("rn_dst_ro.txt");
TYPED_TEST(fuse_test, rename_file_succeeds_if_destination_file_is_read_only) {
if (this->current_provider != provider_type::sia) {
// TODO finish test
return;
}
std::string src_file_name{"rename_test"};
auto src = this->create_file_and_test(src_file_name);
std::string dest_file_name{"rename_test_2"};
auto dst = this->create_file_and_test(dest_file_name);
overwrite_text(src, "NEW");
overwrite_text(dst, "OLD");
@@ -269,14 +345,14 @@ TYPED_TEST(fuse_test, rename_file_overwrite_readonly_destination_succeeds) {
ASSERT_EQ(0, ::chmod(dst.c_str(), 0444));
errno = 0;
int rn = ::rename(src.c_str(), dst.c_str());
if (rn == -1 && errno == EROFS) {
auto res = ::rename(src.c_str(), dst.c_str());
if (res == -1 && errno == EROFS) {
this->unlink_file_and_test(src);
ASSERT_EQ(0, ::chmod(dst.c_str(), 0644));
this->unlink_file_and_test(dst);
GTEST_SKIP();
}
ASSERT_EQ(0, rn);
ASSERT_EQ(0, res);
EXPECT_EQ("NEW", slurp(dst));
@@ -284,25 +360,17 @@ TYPED_TEST(fuse_test, rename_file_overwrite_readonly_destination_succeeds) {
this->unlink_file_and_test(dst);
}
TYPED_TEST(fuse_test, rename_file_on_readonly_mount_sets_erofs_or_skip) {
auto src = this->create_file_and_test("rn_ro_src.txt");
auto dst = this->mount_location() + "/rn_ro_dst.txt";
if (::rename(src.c_str(), src.c_str()) == 0) {
this->unlink_file_and_test(src);
GTEST_SKIP();
TYPED_TEST(fuse_test, rename_file_retains_open_file_descriptor) {
if (this->current_provider != provider_type::sia) {
// TODO finish test
return;
}
errno = 0;
EXPECT_EQ(-1, ::rename(src.c_str(), dst.c_str()));
EXPECT_EQ(EROFS, errno);
std::string src_file_name{"rename_test"};
auto src = this->create_file_and_test(src_file_name);
this->unlink_file_and_test(src);
}
TYPED_TEST(fuse_test, rename_file_open_fd_remains_valid) {
auto src = this->create_file_and_test("rn_fd_src.txt");
auto dst = this->mount_location() + "/rn_fd_dst.txt";
std::string dest_file_name{"rename_test_2"};
auto dst = this->create_file_and_test(dest_file_name);
overwrite_text(src, "HELLO");
@@ -317,13 +385,31 @@ TYPED_TEST(fuse_test, rename_file_open_fd_remains_valid) {
EXPECT_EQ(ENOENT, errno);
ASSERT_NE(-1, ::lseek(desc, 0, SEEK_END));
write_all(desc, " WORLD", 6);
write_all(desc, " WORLD");
::close(desc);
EXPECT_EQ("HELLO WORLD", slurp(dst));
this->unlink_file_and_test(dst);
}
// TODO revisit tests
/*
TYPED_TEST(fuse_test, rename_file_on_readonly_mount_sets_erofs_or_skip) {
auto src = this->create_file_and_test("rn_ro_src.txt");
auto dst = this->mount_location() + "/rn_ro_dst.txt";
if (::rename(src.c_str(), src.c_str()) == 0) {
this->unlink_file_and_test(src);
GTEST_SKIP();
}
errno = 0;
EXPECT_EQ(-1, ::rename(src.c_str(), dst.c_str()));
EXPECT_EQ(EROFS, errno);
this->unlink_file_and_test(src);
}
TYPED_TEST(fuse_test, rename_file_destination_component_name_too_long) {
auto src = this->create_file_and_test("rn_ntl_src.txt");