[unit test] Complete FUSE unit tests #22
Some checks failed
Blockstorage/repertory/pipeline/head This commit looks good
BlockStorage/repertory/pipeline/head There was a failure building this commit

This commit is contained in:
2025-09-19 11:02:07 -05:00
parent 7116ea84fd
commit d219b961a5
3 changed files with 286 additions and 2 deletions

View File

@@ -18,6 +18,7 @@ cflags
chrono
clsid
cmake_current_source_dir
cmdc
coinit_apartmentthreaded
comdlg32
conin$

View File

@@ -9,6 +9,7 @@
### Issues
* \#12 [unit test] Complete all providers unit tests
* \#22 [unit test] Complete FUSE unit tests
* \#33 Complete initial v2.0 documentation
* \#34 Add macOS support
* \#38 Pinning a file should automatically initiate a download to cache

View File

@@ -23,12 +23,294 @@
#include "fixtures/drive_fixture.hpp"
namespace {
void overwrite_text(const std::string &path, const char *s) {
int fd = ::open(path.c_str(), O_WRONLY | O_TRUNC);
ASSERT_NE(fd, -1);
write_all(fd, s, std::strlen(s));
::close(fd);
}
void write_all(int fd, const char *s, size_t n) {
size_t off = 0;
while (off < n) {
ssize_t w = ::write(fd, s + off, n - off);
ASSERT_NE(w, -1);
off += static_cast<size_t>(w);
}
}
[[nodiscard]] auto slurp(const std::string &path) -> std::string {
int fd = ::open(path.c_str(), O_RDONLY);
if (fd == -1)
return {};
std::string out;
char buf[4096];
for (;;) {
ssize_t r = ::read(fd, buf, sizeof(buf));
if (r == 0)
break;
if (r == -1) {
if (errno == EINTR)
continue;
break;
}
out.append(buf, buf + r);
}
::close(fd);
return out;
}
} // namespace
namespace repertory {
TYPED_TEST_SUITE(fuse_test, platform_provider_types);
TYPED_TEST(fuse_test, can_rename_a_file) {}
TYPED_TEST(fuse_test, can_rename_a_file) {
std::string src_file_name{"rename_test"};
auto src = this->create_file_and_test(src_file_name);
TYPED_TEST(fuse_test, can_rename_a_directory) {}
std::string dest_file_name{"rename_test_2"};
auto dst = this->create_file_and_test(dest_file_name);
errno = 0;
ASSERT_EQ(0, ::rename(src.c_str(), dst.c_str()));
errno = 0;
EXPECT_EQ(-1, ::access(src.c_str(), F_OK));
EXPECT_EQ(ENOENT, errno);
struct stat st_unix{};
ASSERT_EQ(0, ::stat(dst.c_str(), &st_unix));
EXPECT_TRUE(S_ISREG(st_unix.st_mode));
this->unlink_file_and_test(dst);
}
TYPED_TEST(fuse_test, can_rename_a_directory) {
std::string src_dir_name{"rename_test"};
auto src_dir = this->create_directory_and_test(src_dir_name);
std::string dest_dir_name{"rename_test_2"};
auto dst_dir = this->create_directory_and_test(dest_dir_name);
errno = 0;
ASSERT_EQ(0, ::rename(src_dir.c_str(), dst_dir.c_str()));
errno = 0;
EXPECT_EQ(-1, ::access(src_dir.c_str(), F_OK));
EXPECT_EQ(ENOENT, errno);
struct stat st{};
ASSERT_EQ(0, ::stat(dst_dir.c_str(), &st));
EXPECT_TRUE(S_ISDIR(st.st_mode));
this->rmdir_and_test(dst_dir);
}
/* TYPED_TEST(fuse_test, rename_file_overwrite_existing) {
std::string src_name{"rename_overwrite_src.txt"};
std::string dst_name{"rename_overwrite_dst.txt"};
auto src = this->create_file_and_test(src_name);
auto dst = this->create_file_and_test(dst_name);
overwrite_text(src, "SRC");
overwrite_text(dst, "DST");
errno = 0;
ASSERT_EQ(0, ::rename(src.c_str(), dst.c_str()));
errno = 0;
EXPECT_EQ(-1, ::access(src.c_str(), F_OK));
EXPECT_EQ(ENOENT, errno);
EXPECT_EQ("SRC", slurp(dst));
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");
auto src = this->create_file_and_test("dir_1/file.txt");
std::string dst = utils::path::combine(dir2, {"moved.txt"});
overwrite_text(src, "CMDC");
errno = 0;
ASSERT_EQ(0, ::rename(src.c_str(), dst.c_str()));
errno = 0;
EXPECT_EQ(-1, ::access(src.c_str(), F_OK));
EXPECT_EQ(ENOENT, errno);
EXPECT_EQ("CMDC", slurp(dst));
this->unlink_file_and_test(dst);
this->rmdir_and_test(dir1);
this->rmdir_and_test(dir2);
}
TYPED_TEST(fuse_test, rename_file_same_path) {
auto src = this->create_file_and_test("rn_same.txt");
overwrite_text(src, "CMDC");
errno = 0;
EXPECT_EQ(0, ::rename(src.c_str(), src.c_str()));
EXPECT_EQ("CMDC", slurp(src));
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";
errno = 0;
EXPECT_EQ(-1, ::rename(missing.c_str(), dst.c_str()));
EXPECT_EQ(ENOENT, errno);
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";
errno = 0;
EXPECT_EQ(-1, ::rename(src.c_str(), dst.c_str()));
EXPECT_EQ(ENOENT, errno);
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");
errno = 0;
EXPECT_EQ(-1, ::rename(src.c_str(), dstdir.c_str()));
EXPECT_EQ(EISDIR, errno);
this->unlink_file_and_test(src);
this->rmdir_and_test(dstdir);
}
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";
ASSERT_EQ(0, ::chmod(srcdir.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));
this->unlink_file_and_test(src);
this->rmdir_and_test(srcdir);
this->rmdir_and_test(dstdir);
}
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";
ASSERT_EQ(0, ::chmod(dstdir.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));
this->unlink_file_and_test(src);
this->rmdir_and_test(srcdir);
this->rmdir_and_test(dstdir);
}
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");
overwrite_text(src, "NEW");
overwrite_text(dst, "OLD");
ASSERT_EQ(0, ::chmod(dst.c_str(), 0444));
errno = 0;
int rn = ::rename(src.c_str(), dst.c_str());
if (rn == -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);
EXPECT_EQ("NEW", slurp(dst));
ASSERT_EQ(0, ::chmod(dst.c_str(), 0644));
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();
}
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_open_fd_remains_valid) {
auto src = this->create_file_and_test("rn_fd_src.txt");
auto dst = this->mount_location() + "/rn_fd_dst.txt";
overwrite_text(src, "HELLO");
int fd = ::open(src.c_str(), O_RDWR);
ASSERT_NE(fd, -1);
errno = 0;
ASSERT_EQ(0, ::rename(src.c_str(), dst.c_str()));
errno = 0;
EXPECT_EQ(-1, ::access(src.c_str(), F_OK));
EXPECT_EQ(ENOENT, errno);
ASSERT_NE(-1, ::lseek(fd, 0, SEEK_END));
write_all(fd, " WORLD", 6);
::close(fd);
EXPECT_EQ("HELLO WORLD", slurp(dst));
this->unlink_file_and_test(dst);
}
TYPED_TEST(fuse_test, rename_file_destination_component_name_too_long) {
auto src = this->create_file_and_test("rn_ntl_src.txt");
std::string longname(300, 'a');
std::string dst = this->mount_location() + "/" + longname;
errno = 0;
EXPECT_EQ(-1, ::rename(src.c_str(), dst.c_str()));
EXPECT_TRUE(errno == ENAMETOOLONG || errno == EINVAL);
this->unlink_file_and_test(src);
} */
} // namespace repertory
#endif // !defined(_WIN32)