[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-20 16:34:02 -05:00
parent 1bc57976c9
commit 0c7532e28b
4 changed files with 78 additions and 57 deletions

View File

@@ -57,6 +57,11 @@ TYPED_TEST(fuse_test, fallocate_basic_preallocation_platform_semantics) {
EXPECT_EQ(0, st_unix.st_size); EXPECT_EQ(0, st_unix.st_size);
#else // !defined(__APPLE__) #else // !defined(__APPLE__)
auto res = ::posix_fallocate(desc, off, len); auto res = ::posix_fallocate(desc, off, len);
if (res == EOPNOTSUPP) {
::close(desc);
this->unlink_file_and_test(src);
return;
}
EXPECT_EQ(0, res); EXPECT_EQ(0, res);
struct stat st_unix{}; struct stat st_unix{};
@@ -90,6 +95,12 @@ TYPED_TEST(fuse_test, fallocate_then_ftruncate_makes_size_visible) {
store.fst_flags = F_ALLOCATEALL; store.fst_flags = F_ALLOCATEALL;
res = ::fcntl(desc, F_PREALLOCATE, &store); res = ::fcntl(desc, F_PREALLOCATE, &store);
} }
if (res == EOPNOTSUPP) {
::close(desc);
this->unlink_file_and_test(src);
return;
}
EXPECT_EQ(0, res); EXPECT_EQ(0, res);
EXPECT_EQ(0, ::ftruncate(desc, len)); EXPECT_EQ(0, ::ftruncate(desc, len));
#else // !defined(__APPLE__) #else // !defined(__APPLE__)

View File

@@ -96,7 +96,6 @@ TYPED_TEST(fuse_test, truncate_fails_if_file_is_read_only) {
if (res == -1 && errno == EROFS) { if (res == -1 && errno == EROFS) {
ASSERT_EQ(0, ::chmod(src.c_str(), 0644)); ASSERT_EQ(0, ::chmod(src.c_str(), 0644));
this->unlink_file_and_test(src); this->unlink_file_and_test(src);
GTEST_SKIP();
return; return;
} }

View File

@@ -47,37 +47,32 @@ void get_times_ns(const std::string &path, long long &at_ns, long long &mt_ns) {
#endif // defined(__APPLE__) #endif // defined(__APPLE__)
} }
auto ts_make(time_t sec, long nsec) -> struct timespec { [[nodiscard]] auto ts_make(time_t sec, long nsec) -> timespec {
struct timespec spec{}; return timespec{
spec.tv_sec = sec; .tv_sec = sec,
spec.tv_nsec = nsec; .tv_nsec = nsec,
return spec; };
} }
[[nodiscard]] auto [[nodiscard]] auto to_ns(const timespec &spec) -> long long {
to_ns(const struct timespec &spec) -> long long {
return static_cast<long long>(spec.tv_sec) * return static_cast<long long>(spec.tv_sec) *
static_cast<long long>(NANOS_PER_SECOND) + static_cast<long long>(NANOS_PER_SECOND) +
static_cast<long long>(spec.tv_nsec); static_cast<long long>(spec.tv_nsec);
} }
[[nodiscard]] auto now_ns() -> long long { [[nodiscard]] auto now_ns() -> long long {
struct timespec spec{}; timespec spec{};
#if defined(CLOCK_REALTIME) #if defined(CLOCK_REALTIME)
clock_gettime(CLOCK_REALTIME, &spec); clock_gettime(CLOCK_REALTIME, &spec);
#else #else // defined(CLOCK_REALTIME)
struct timeval val{}; timeval val{};
gettimeofday(&val, nullptr); gettimeofday(&val, nullptr);
spec.tv_sec = val.tv_sec; spec.tv_sec = val.tv_sec;
spec.tv_nsec = val.tv_usec * 1000; spec.tv_nsec = val.tv_usec * 1000;
#endif #endif // !defined(CLOCK_REALTIME)
return to_ns(spec); return to_ns(spec);
} }
[[nodiscard]] auto llabsll(long long value) -> long long {
return (value < 0) ? -value : value;
}
constexpr long long GRANULAR_TOL_NS = constexpr long long GRANULAR_TOL_NS =
1LL * static_cast<long long>(NANOS_PER_SECOND); 1LL * static_cast<long long>(NANOS_PER_SECOND);
constexpr long long NOW_TOL_NS = 5LL * static_cast<long long>(NANOS_PER_SECOND); constexpr long long NOW_TOL_NS = 5LL * static_cast<long long>(NANOS_PER_SECOND);
@@ -102,7 +97,7 @@ TYPED_TEST(fuse_test, utimens_set_both_times_specific_values) {
auto target_mt = auto target_mt =
now - 1800LL * static_cast<long long>(NANOS_PER_SECOND) + 222222222LL; now - 1800LL * static_cast<long long>(NANOS_PER_SECOND) + 222222222LL;
struct timespec spec[2]{ auto spec = std::array<timespec, 2U>{
ts_make(static_cast<time_t>(target_at / ts_make(static_cast<time_t>(target_at /
static_cast<long long>(NANOS_PER_SECOND)), static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_at % static_cast<long>(target_at %
@@ -110,17 +105,18 @@ TYPED_TEST(fuse_test, utimens_set_both_times_specific_values) {
ts_make(static_cast<time_t>(target_mt / ts_make(static_cast<time_t>(target_mt /
static_cast<long long>(NANOS_PER_SECOND)), static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_mt % static_cast<long>(target_mt %
static_cast<long long>(NANOS_PER_SECOND)))}; static_cast<long long>(NANOS_PER_SECOND))),
};
errno = 0; errno = 0;
ASSERT_EQ(0, ::utimensat(AT_FDCWD, src.c_str(), spec, 0)); ASSERT_EQ(0, ::utimensat(AT_FDCWD, src.c_str(), spec.data(), 0));
long long at1{}; long long at1{};
long long mt1{}; long long mt1{};
get_times_ns(src, at1, mt1); get_times_ns(src, at1, mt1);
EXPECT_LE(llabsll(at1 - target_at), GRANULAR_TOL_NS); EXPECT_LE(std::abs(at1 - target_at), GRANULAR_TOL_NS);
EXPECT_LE(llabsll(mt1 - target_mt), GRANULAR_TOL_NS); EXPECT_LE(std::abs(mt1 - target_mt), GRANULAR_TOL_NS);
this->unlink_file_and_test(src); this->unlink_file_and_test(src);
} }
@@ -136,22 +132,23 @@ TYPED_TEST(fuse_test, utimens_set_atime_only_omit_mtime) {
long long target_at = long long target_at =
now_ns() - 10LL * static_cast<long long>(NANOS_PER_SECOND); now_ns() - 10LL * static_cast<long long>(NANOS_PER_SECOND);
struct timespec spec[2]{ auto spec = std::array<timespec, 2U>{
ts_make(static_cast<time_t>(target_at / ts_make(static_cast<time_t>(target_at /
static_cast<long long>(NANOS_PER_SECOND)), static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_at % static_cast<long>(target_at %
static_cast<long long>(NANOS_PER_SECOND))), static_cast<long long>(NANOS_PER_SECOND))),
ts_make(0, UTIME_OMIT)}; ts_make(0, UTIME_OMIT),
};
errno = 0; errno = 0;
ASSERT_EQ(0, ::utimensat(AT_FDCWD, src.c_str(), spec, 0)); ASSERT_EQ(0, ::utimensat(AT_FDCWD, src.c_str(), spec.data(), 0));
long long at_after{}; long long at_after{};
long long mt_after{}; long long mt_after{};
get_times_ns(src, at_after, mt_after); get_times_ns(src, at_after, mt_after);
EXPECT_LE(llabsll(at_after - target_at), GRANULAR_TOL_NS); EXPECT_LE(std::abs(at_after - target_at), GRANULAR_TOL_NS);
EXPECT_LE(llabsll(mt_after - mt_before), GRANULAR_TOL_NS); EXPECT_LE(std::abs(mt_after - mt_before), GRANULAR_TOL_NS);
this->unlink_file_and_test(src); this->unlink_file_and_test(src);
} }
@@ -166,22 +163,23 @@ TYPED_TEST(fuse_test, utimens_set_mtime_only_omit_atime) {
auto target_mt = now_ns() - 30LL * static_cast<long long>(NANOS_PER_SECOND); auto target_mt = now_ns() - 30LL * static_cast<long long>(NANOS_PER_SECOND);
struct timespec spec[2]{ auto spec = std::array<timespec, 2U>{
ts_make(0, UTIME_OMIT), ts_make(0, UTIME_OMIT),
ts_make(static_cast<time_t>(target_mt / ts_make(static_cast<time_t>(target_mt /
static_cast<long long>(NANOS_PER_SECOND)), static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_mt % static_cast<long>(target_mt %
static_cast<long long>(NANOS_PER_SECOND)))}; static_cast<long long>(NANOS_PER_SECOND))),
};
errno = 0; errno = 0;
ASSERT_EQ(0, ::utimensat(AT_FDCWD, src.c_str(), spec, 0)); ASSERT_EQ(0, ::utimensat(AT_FDCWD, src.c_str(), spec.data(), 0));
long long at_after{}; long long at_after{};
long long mt_after{}; long long mt_after{};
get_times_ns(src, at_after, mt_after); get_times_ns(src, at_after, mt_after);
EXPECT_LE(llabsll(mt_after - target_mt), GRANULAR_TOL_NS); EXPECT_LE(std::abs(mt_after - target_mt), GRANULAR_TOL_NS);
EXPECT_LE(llabsll(at_after - at_before), GRANULAR_TOL_NS); EXPECT_LE(std::abs(at_after - at_before), GRANULAR_TOL_NS);
this->unlink_file_and_test(src); this->unlink_file_and_test(src);
} }
@@ -190,29 +188,36 @@ TYPED_TEST(fuse_test, utimens_set_now_for_both) {
std::string name{"utimens"}; std::string name{"utimens"};
auto src = this->create_file_and_test(name); auto src = this->create_file_and_test(name);
struct timespec spec[2]{ts_make(0, UTIME_NOW), ts_make(0, UTIME_NOW)}; auto spec = std::array<timespec, 2U>{
ts_make(0, UTIME_NOW),
ts_make(0, UTIME_NOW),
};
errno = 0; errno = 0;
ASSERT_EQ(0, ::utimensat(AT_FDCWD, src.c_str(), spec, 0)); ASSERT_EQ(0, ::utimensat(AT_FDCWD, src.c_str(), spec.data(), 0));
auto now_after = now_ns(); auto now_after = now_ns();
long long access_time{}; long long access_time{};
long long modified_time{}; long long modified_time{};
get_times_ns(src, access_time, modified_time); get_times_ns(src, access_time, modified_time);
EXPECT_LE(llabsll(access_time - now_after), NOW_TOL_NS); EXPECT_LE(std::abs(access_time - now_after), NOW_TOL_NS);
EXPECT_LE(llabsll(modified_time - now_after), NOW_TOL_NS); EXPECT_LE(std::abs(modified_time - now_after), NOW_TOL_NS);
this->unlink_file_and_test(src); this->unlink_file_and_test(src);
} }
TYPED_TEST(fuse_test, utimens_nonexistent_path_returns_enoent) { TYPED_TEST(fuse_test, utimens_nonexistent_path_returns_enoent) {
std::string missing = std::string file_name{"utimens"};
this->mount_location + "/utimens_missing_" + std::to_string(::getpid()); auto missing = this->create_file_path(file_name);
auto spec = std::array<timespec, 2U>{
ts_make(123, 0),
ts_make(456, 0),
};
struct timespec spec[2]{ts_make(123, 0), ts_make(456, 0)};
errno = 0; errno = 0;
EXPECT_EQ(-1, ::utimensat(AT_FDCWD, missing.c_str(), spec, 0)); EXPECT_EQ(-1, ::utimensat(AT_FDCWD, missing.c_str(), spec.data(), 0));
EXPECT_EQ(ENOENT, errno); EXPECT_EQ(ENOENT, errno);
} }
@@ -220,10 +225,13 @@ TYPED_TEST(fuse_test, utimens_invalid_nsec_returns_einval) {
std::string name{"utimens"}; std::string name{"utimens"};
auto src = this->create_file_and_test(name); auto src = this->create_file_and_test(name);
struct timespec spec[2]{ts_make(0, 1000000000L), ts_make(0, 0)}; auto spec = std::array<timespec, 2U>{
ts_make(0, 1000000000L),
ts_make(0, 0),
};
errno = 0; errno = 0;
EXPECT_EQ(-1, ::utimensat(AT_FDCWD, src.c_str(), spec, 0)); EXPECT_EQ(-1, ::utimensat(AT_FDCWD, src.c_str(), spec.data(), 0));
EXPECT_EQ(EINVAL, errno); EXPECT_EQ(EINVAL, errno);
this->unlink_file_and_test(src); this->unlink_file_and_test(src);
@@ -242,7 +250,7 @@ TYPED_TEST(fuse_test, futimens_set_both_times_specific_values) {
auto target_mt = auto target_mt =
now - 600LL * static_cast<long long>(NANOS_PER_SECOND) + 444444444LL; now - 600LL * static_cast<long long>(NANOS_PER_SECOND) + 444444444LL;
struct timespec spec[2]{ auto spec = std::array<timespec, 2U>{
ts_make(static_cast<time_t>(target_at / ts_make(static_cast<time_t>(target_at /
static_cast<long long>(NANOS_PER_SECOND)), static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_at % static_cast<long>(target_at %
@@ -250,17 +258,18 @@ TYPED_TEST(fuse_test, futimens_set_both_times_specific_values) {
ts_make(static_cast<time_t>(target_mt / ts_make(static_cast<time_t>(target_mt /
static_cast<long long>(NANOS_PER_SECOND)), static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_mt % static_cast<long>(target_mt %
static_cast<long long>(NANOS_PER_SECOND)))}; static_cast<long long>(NANOS_PER_SECOND))),
};
errno = 0; errno = 0;
ASSERT_EQ(0, ::futimens(desc, spec)); ASSERT_EQ(0, ::futimens(desc, spec.data()));
::close(desc); ::close(desc);
long long access_time{}; long long access_time{};
long long modified_time{}; long long modified_time{};
get_times_ns(src, access_time, modified_time); get_times_ns(src, access_time, modified_time);
EXPECT_LE(llabsll(access_time - target_at), GRANULAR_TOL_NS); EXPECT_LE(std::abs(access_time - target_at), GRANULAR_TOL_NS);
EXPECT_LE(llabsll(modified_time - target_mt), GRANULAR_TOL_NS); EXPECT_LE(std::abs(modified_time - target_mt), GRANULAR_TOL_NS);
this->unlink_file_and_test(src); this->unlink_file_and_test(src);
} }
@@ -278,23 +287,24 @@ TYPED_TEST(fuse_test, futimens_set_mtime_only_omit_atime) {
auto target_mt = now_ns() - 20LL * static_cast<long long>(NANOS_PER_SECOND); auto target_mt = now_ns() - 20LL * static_cast<long long>(NANOS_PER_SECOND);
struct timespec spec[2]{ auto spec = std::array<timespec, 2U>{
ts_make(0, UTIME_OMIT), ts_make(0, UTIME_OMIT),
ts_make(static_cast<time_t>(target_mt / ts_make(static_cast<time_t>(target_mt /
static_cast<long long>(NANOS_PER_SECOND)), static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_mt % static_cast<long>(target_mt %
static_cast<long long>(NANOS_PER_SECOND)))}; static_cast<long long>(NANOS_PER_SECOND))),
};
errno = 0; errno = 0;
ASSERT_EQ(0, ::futimens(desc, spec)); ASSERT_EQ(0, ::futimens(desc, spec.data()));
::close(desc); ::close(desc);
long long at_after{}; long long at_after{};
long long mt_after{}; long long mt_after{};
get_times_ns(src, at_after, mt_after); get_times_ns(src, at_after, mt_after);
EXPECT_LE(llabsll(mt_after - target_mt), GRANULAR_TOL_NS); EXPECT_LE(std::abs(mt_after - target_mt), GRANULAR_TOL_NS);
EXPECT_LE(llabsll(at_after - at_before), GRANULAR_TOL_NS); EXPECT_LE(std::abs(at_after - at_before), GRANULAR_TOL_NS);
this->unlink_file_and_test(src); this->unlink_file_and_test(src);
} }
@@ -306,10 +316,13 @@ TYPED_TEST(fuse_test, futimens_invalid_nsec_returns_einval) {
auto desc = ::open(src.c_str(), O_RDWR); auto desc = ::open(src.c_str(), O_RDWR);
ASSERT_NE(desc, -1); ASSERT_NE(desc, -1);
struct timespec spec[2]{ts_make(0, 0), ts_make(0, 1000000000L)}; auto spec = std::array<timespec, 2U>{
ts_make(0, 0),
ts_make(0, 1000000000L),
};
errno = 0; errno = 0;
EXPECT_EQ(-1, ::futimens(desc, spec)); EXPECT_EQ(-1, ::futimens(desc, spec.data()));
EXPECT_EQ(EINVAL, errno); EXPECT_EQ(EINVAL, errno);
::close(desc); ::close(desc);

View File

@@ -336,11 +336,9 @@ TEST_P(utils_encryption_read_encrypted_range_fixture, single_byte_read) {
TEST_P(utils_encryption_read_encrypted_range_fixture, TEST_P(utils_encryption_read_encrypted_range_fixture,
begin_at_exact_chunk_boundary) { begin_at_exact_chunk_boundary) {
if (chunk == 0U) { ASSERT_NE(chunk, 0U);
GTEST_SKIP() << "chunk size is zero (unexpected)";
}
std::uint64_t begin = static_cast<std::uint64_t>(chunk); auto begin = static_cast<std::uint64_t>(chunk);
std::uint64_t end = begin + 1024U - 1U; std::uint64_t end = begin + 1024U - 1U;
if (end >= plain_sz) if (end >= plain_sz)
end = static_cast<std::uint64_t>(plain_sz) - 1U; end = static_cast<std::uint64_t>(plain_sz) - 1U;