[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);
#else // !defined(__APPLE__)
auto res = ::posix_fallocate(desc, off, len);
if (res == EOPNOTSUPP) {
::close(desc);
this->unlink_file_and_test(src);
return;
}
EXPECT_EQ(0, res);
struct stat st_unix{};
@@ -90,6 +95,12 @@ TYPED_TEST(fuse_test, fallocate_then_ftruncate_makes_size_visible) {
store.fst_flags = F_ALLOCATEALL;
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, ::ftruncate(desc, len));
#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) {
ASSERT_EQ(0, ::chmod(src.c_str(), 0644));
this->unlink_file_and_test(src);
GTEST_SKIP();
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__)
}
auto ts_make(time_t sec, long nsec) -> struct timespec {
struct timespec spec{};
spec.tv_sec = sec;
spec.tv_nsec = nsec;
return spec;
[[nodiscard]] auto ts_make(time_t sec, long nsec) -> timespec {
return timespec{
.tv_sec = sec,
.tv_nsec = nsec,
};
}
[[nodiscard]] auto
to_ns(const struct timespec &spec) -> long long {
[[nodiscard]] auto to_ns(const timespec &spec) -> long long {
return static_cast<long long>(spec.tv_sec) *
static_cast<long long>(NANOS_PER_SECOND) +
static_cast<long long>(spec.tv_nsec);
}
[[nodiscard]] auto now_ns() -> long long {
struct timespec spec{};
timespec spec{};
#if defined(CLOCK_REALTIME)
clock_gettime(CLOCK_REALTIME, &spec);
#else
struct timeval val{};
#else // defined(CLOCK_REALTIME)
timeval val{};
gettimeofday(&val, nullptr);
spec.tv_sec = val.tv_sec;
spec.tv_nsec = val.tv_usec * 1000;
#endif
#endif // !defined(CLOCK_REALTIME)
return to_ns(spec);
}
[[nodiscard]] auto llabsll(long long value) -> long long {
return (value < 0) ? -value : value;
}
constexpr long long GRANULAR_TOL_NS =
1LL * 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 =
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 /
static_cast<long long>(NANOS_PER_SECOND)),
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 /
static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_mt %
static_cast<long long>(NANOS_PER_SECOND)))};
static_cast<long long>(NANOS_PER_SECOND))),
};
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 mt1{};
get_times_ns(src, at1, mt1);
EXPECT_LE(llabsll(at1 - target_at), GRANULAR_TOL_NS);
EXPECT_LE(llabsll(mt1 - target_mt), GRANULAR_TOL_NS);
EXPECT_LE(std::abs(at1 - target_at), GRANULAR_TOL_NS);
EXPECT_LE(std::abs(mt1 - target_mt), GRANULAR_TOL_NS);
this->unlink_file_and_test(src);
}
@@ -136,22 +132,23 @@ TYPED_TEST(fuse_test, utimens_set_atime_only_omit_mtime) {
long long target_at =
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 /
static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_at %
static_cast<long long>(NANOS_PER_SECOND))),
ts_make(0, UTIME_OMIT)};
ts_make(0, UTIME_OMIT),
};
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 mt_after{};
get_times_ns(src, at_after, mt_after);
EXPECT_LE(llabsll(at_after - target_at), GRANULAR_TOL_NS);
EXPECT_LE(llabsll(mt_after - mt_before), GRANULAR_TOL_NS);
EXPECT_LE(std::abs(at_after - target_at), GRANULAR_TOL_NS);
EXPECT_LE(std::abs(mt_after - mt_before), GRANULAR_TOL_NS);
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);
struct timespec spec[2]{
auto spec = std::array<timespec, 2U>{
ts_make(0, UTIME_OMIT),
ts_make(static_cast<time_t>(target_mt /
static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_mt %
static_cast<long long>(NANOS_PER_SECOND)))};
static_cast<long long>(NANOS_PER_SECOND))),
};
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 mt_after{};
get_times_ns(src, at_after, mt_after);
EXPECT_LE(llabsll(mt_after - target_mt), GRANULAR_TOL_NS);
EXPECT_LE(llabsll(at_after - at_before), GRANULAR_TOL_NS);
EXPECT_LE(std::abs(mt_after - target_mt), GRANULAR_TOL_NS);
EXPECT_LE(std::abs(at_after - at_before), GRANULAR_TOL_NS);
this->unlink_file_and_test(src);
}
@@ -190,29 +188,36 @@ TYPED_TEST(fuse_test, utimens_set_now_for_both) {
std::string name{"utimens"};
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;
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();
long long access_time{};
long long modified_time{};
get_times_ns(src, access_time, modified_time);
EXPECT_LE(llabsll(access_time - now_after), NOW_TOL_NS);
EXPECT_LE(llabsll(modified_time - now_after), NOW_TOL_NS);
EXPECT_LE(std::abs(access_time - now_after), NOW_TOL_NS);
EXPECT_LE(std::abs(modified_time - now_after), NOW_TOL_NS);
this->unlink_file_and_test(src);
}
TYPED_TEST(fuse_test, utimens_nonexistent_path_returns_enoent) {
std::string missing =
this->mount_location + "/utimens_missing_" + std::to_string(::getpid());
std::string file_name{"utimens"};
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;
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);
}
@@ -220,10 +225,13 @@ TYPED_TEST(fuse_test, utimens_invalid_nsec_returns_einval) {
std::string name{"utimens"};
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;
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);
this->unlink_file_and_test(src);
@@ -242,7 +250,7 @@ TYPED_TEST(fuse_test, futimens_set_both_times_specific_values) {
auto target_mt =
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 /
static_cast<long long>(NANOS_PER_SECOND)),
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 /
static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_mt %
static_cast<long long>(NANOS_PER_SECOND)))};
static_cast<long long>(NANOS_PER_SECOND))),
};
errno = 0;
ASSERT_EQ(0, ::futimens(desc, spec));
ASSERT_EQ(0, ::futimens(desc, spec.data()));
::close(desc);
long long access_time{};
long long modified_time{};
get_times_ns(src, access_time, modified_time);
EXPECT_LE(llabsll(access_time - target_at), GRANULAR_TOL_NS);
EXPECT_LE(llabsll(modified_time - target_mt), GRANULAR_TOL_NS);
EXPECT_LE(std::abs(access_time - target_at), GRANULAR_TOL_NS);
EXPECT_LE(std::abs(modified_time - target_mt), GRANULAR_TOL_NS);
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);
struct timespec spec[2]{
auto spec = std::array<timespec, 2U>{
ts_make(0, UTIME_OMIT),
ts_make(static_cast<time_t>(target_mt /
static_cast<long long>(NANOS_PER_SECOND)),
static_cast<long>(target_mt %
static_cast<long long>(NANOS_PER_SECOND)))};
static_cast<long long>(NANOS_PER_SECOND))),
};
errno = 0;
ASSERT_EQ(0, ::futimens(desc, spec));
ASSERT_EQ(0, ::futimens(desc, spec.data()));
::close(desc);
long long at_after{};
long long mt_after{};
get_times_ns(src, at_after, mt_after);
EXPECT_LE(llabsll(mt_after - target_mt), GRANULAR_TOL_NS);
EXPECT_LE(llabsll(at_after - at_before), GRANULAR_TOL_NS);
EXPECT_LE(std::abs(mt_after - target_mt), GRANULAR_TOL_NS);
EXPECT_LE(std::abs(at_after - at_before), GRANULAR_TOL_NS);
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);
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;
EXPECT_EQ(-1, ::futimens(desc, spec));
EXPECT_EQ(-1, ::futimens(desc, spec.data()));
EXPECT_EQ(EINVAL, errno);
::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,
begin_at_exact_chunk_boundary) {
if (chunk == 0U) {
GTEST_SKIP() << "chunk size is zero (unexpected)";
}
ASSERT_NE(chunk, 0U);
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;
if (end >= plain_sz)
end = static_cast<std::uint64_t>(plain_sz) - 1U;