Files
TheRock/rocm-systems/projects/hipfile/test/amd_detail/handle.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

814 lines
25 KiB
C++

/* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: MIT
*/
#include "context.h"
#include "file.h"
#include "hipfile.h"
#include "hipfile-test.h"
#include "hipfile-warnings.h"
#include "invalid-enum.h"
#include "msys.h"
#include "mmountinfo.h"
#include "mountinfo.h"
#include "state.h"
#include <cerrno>
#include <cstring>
#include <fcntl.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <linux/stat.h>
#include <memory>
#include <optional>
#include <stdexcept>
#include <sys/eventfd.h>
#include <system_error>
using namespace hipFile;
using namespace testing;
using namespace std;
// Put tests inside the macros to suppress the global constructor
// warnings
HIPFILE_WARN_NO_GLOBAL_CTOR_OFF
struct ExpectUnregisteredFile;
struct ExpectUnregisteredFileBuilder {
MSys &m_msys;
MLibMountHelper &m_mlibmounthelper;
optional<struct statx> m_statx;
optional<int> m_fd_flags;
optional<MountInfo> m_mountinfo;
optional<int> m_open_fd;
optional<int> m_open_flags;
optional<int> m_open_throws;
ExpectUnregisteredFileBuilder(MSys &msys, MLibMountHelper &mlibmounthelper)
: m_msys(msys), m_mlibmounthelper(mlibmounthelper)
{
}
ExpectUnregisteredFileBuilder &statx(const struct statx &statxbuf)
{
m_statx = statxbuf;
return *this;
}
ExpectUnregisteredFileBuilder &fd_flags(int flags)
{
m_fd_flags = flags;
return *this;
}
ExpectUnregisteredFileBuilder &mountinfo(const MountInfo &mountinfo)
{
m_mountinfo = mountinfo;
return *this;
}
ExpectUnregisteredFileBuilder &open_fd(int fd)
{
if (m_open_throws) {
throw "Cannot specify both open_throws(...) and open_fd(...)";
}
m_open_fd = fd;
return *this;
}
ExpectUnregisteredFileBuilder &open_flags(int flags)
{
m_open_flags = flags;
return *this;
}
ExpectUnregisteredFileBuilder &open_throws(int errno_)
{
if (m_open_fd) {
throw "Cannot specify both open_throws(...) and open_fd(...)";
}
m_open_throws = errno_;
return *this;
}
ExpectUnregisteredFile build();
};
struct ExpectUnregisteredFile {
ExpectUnregisteredFile(const ExpectUnregisteredFileBuilder &builder)
{
if (builder.m_statx) {
EXPECT_CALL(builder.m_msys, statx).WillOnce(Return(builder.m_statx.value()));
}
else {
EXPECT_CALL(builder.m_msys, statx);
}
if (builder.m_fd_flags) {
EXPECT_CALL(builder.m_msys, fcntl(_, F_GETFL, 0)).WillOnce(Return(builder.m_fd_flags.value()));
}
else {
EXPECT_CALL(builder.m_msys, fcntl(_, F_GETFL, 0));
}
if (builder.m_mountinfo) {
EXPECT_CALL(builder.m_mlibmounthelper, getMountInfo)
.WillOnce(Return(builder.m_mountinfo.value()));
}
else {
EXPECT_CALL(builder.m_mlibmounthelper, getMountInfo);
}
if (builder.m_open_throws && builder.m_open_flags) {
EXPECT_CALL(builder.m_msys, open(_, builder.m_open_flags.value(), _))
.WillOnce(Throw(std::system_error(builder.m_open_throws.value(), std::generic_category())));
}
else if (builder.m_open_throws) {
EXPECT_CALL(builder.m_msys, open)
.WillOnce(Throw(std::system_error(builder.m_open_throws.value(), std::generic_category())));
}
else if (builder.m_open_flags) {
EXPECT_CALL(builder.m_msys, open(_, builder.m_open_flags.value(), _))
.WillOnce(Return(builder.m_open_fd ? builder.m_open_fd.value() : -1));
}
else {
EXPECT_CALL(builder.m_msys, open)
.WillOnce(Return(builder.m_open_fd ? builder.m_open_fd.value() : -1));
}
}
};
ExpectUnregisteredFile
ExpectUnregisteredFileBuilder::build()
{
return ExpectUnregisteredFile(*this);
}
void
expect_file_registration(MSys &msys, MLibMountHelper &mlibmounthelper)
{
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).build();
}
struct HipFileHandle : public HipFileOpened {
StrictMock<MSys> msys;
StrictMock<MLibMountHelper> mlibmounthelper;
};
TEST_F(HipFileHandle, register_handle_internal_linux_fd)
{
int fd{0xBADF00D};
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).build();
ASSERT_NE(Context<DriverState>::get()->registerFile(fd), nullptr);
}
TEST_F(HipFileHandle, file_initialization)
{
int fd{0x12345678};
int fd_flags{~O_DIRECT}; // All flags, except O_DIRECT, set
struct statx stxbuf {};
#if defined(STATX_DIOALIGN)
stxbuf.stx_mask = STATX_TYPE | STATX_MODE | STATX_DIOALIGN;
stxbuf.stx_dio_mem_align = 4;
stxbuf.stx_dio_offset_align = 512;
#else
stxbuf.stx_mask = STATX_TYPE | STATX_MODE;
#endif
stxbuf.stx_mode = S_IFREG;
// In this test, the registered file is destroyed _after_ the mocks are
// destroyed. Use an eventfd so that when FileDescriptor calls close, it
// has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
MountInfo mountinfo{};
mountinfo.type = FilesystemType::ext4;
mountinfo.options.ext4.journaling_mode = ExtJournalingMode::ordered;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.statx(stxbuf)
.fd_flags(fd_flags)
.mountinfo(mountinfo)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_EQ(fh, file->handle());
EXPECT_EQ(fd, file->clientFd());
EXPECT_EQ(fd, file->bufferedFd());
EXPECT_EQ(open_fd, file->unbufferedFd());
#if defined(STATX_DIOALIGN)
EXPECT_EQ(file->dioMemAlign(), stxbuf.stx_dio_mem_align);
EXPECT_EQ(file->dioOffsetAlign(), stxbuf.stx_dio_offset_align);
#else
EXPECT_EQ(file->dioMemAlign(), 4096);
EXPECT_EQ(file->dioOffsetAlign(), 4096);
#endif
EXPECT_FALSE(file->isBlockDevice());
EXPECT_TRUE(file->isRegularFile());
EXPECT_TRUE(file->onExt4Ordered());
EXPECT_FALSE(file->onXfs());
}
TEST_F(HipFileHandle, register_handle_internal_linux_fd_already_registered)
{
int fd{0xBADF00D};
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).build();
ASSERT_NE(Context<DriverState>::get()->registerFile(fd), nullptr);
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).build();
ASSERT_THROW(Context<DriverState>::get()->registerFile(fd), FileAlreadyRegistered);
}
TEST_F(HipFileHandle, register_handle_linux_fd)
{
hipFileHandle_t fh{};
hipFileDescr_t rfd{};
rfd.type = hipFileHandleTypeOpaqueFD;
rfd.handle.fd = 0xBADF00D;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).build();
ASSERT_EQ(hipFileHandleRegister(&fh, &rfd), HIPFILE_SUCCESS);
ASSERT_NE(fh, nullptr);
}
// If statx() fails during file registration return hipfileInternalError
TEST_F(HipFileHandle, RocfileHandleRegisterStatxError)
{
hipFileHandle_t fh{};
hipFileDescr_t rfd{};
rfd.type = hipFileHandleTypeOpaqueFD;
rfd.handle.fd = 0xBADF00D;
EXPECT_CALL(msys, statx).WillOnce(Throw(std::system_error(EBADF, std::generic_category())));
ASSERT_EQ(hipFileHandleRegister(&fh, &rfd), HipFileOpError(hipFileInternalError));
}
// If the fcntl() fails during file registration return hipfileInternalError
TEST_F(HipFileHandle, RocfileHandleRegisterFcntlError)
{
hipFileHandle_t fh{};
hipFileDescr_t rfd{};
rfd.type = hipFileHandleTypeOpaqueFD;
rfd.handle.fd = 0xBADF00D;
EXPECT_CALL(msys, statx);
EXPECT_CALL(msys, fcntl).WillOnce(Throw(std::system_error(EBADF, std::generic_category())));
ASSERT_EQ(hipFileHandleRegister(&fh, &rfd), HipFileOpError(hipFileInternalError));
}
// If getting mount information fails during file registration return hipfileInternalError
TEST_F(HipFileHandle, RocfileHandleRegisterLibMountError)
{
hipFileHandle_t fh{};
hipFileDescr_t rfd{};
rfd.type = hipFileHandleTypeOpaqueFD;
rfd.handle.fd = 0xBADF00D;
EXPECT_CALL(msys, statx);
EXPECT_CALL(msys, fcntl);
EXPECT_CALL(mlibmounthelper, getMountInfo).WillOnce(Throw(std::runtime_error("error from test")));
ASSERT_EQ(hipFileHandleRegister(&fh, &rfd), HipFileOpError(hipFileInternalError));
}
TEST_F(HipFileHandle, register_handle_linux_fd_already_registered)
{
hipFileHandle_t fh{};
hipFileDescr_t rfd{};
rfd.type = hipFileHandleTypeOpaqueFD;
rfd.handle.fd = 0xBADF00D;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).build();
ASSERT_EQ(hipFileHandleRegister(&fh, &rfd), HIPFILE_SUCCESS);
ASSERT_NE(fh, nullptr);
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).build();
ASSERT_EQ(hipFileHandleRegister(&fh, &rfd), HipFileOpError(hipFileHandleAlreadyRegistered));
}
TEST_F(HipFileHandle, register_handle_windows_handle_not_supported)
{
hipFileHandle_t fh{};
hipFileDescr_t rfd{};
rfd.type = hipFileHandleTypeOpaqueWin32;
rfd.handle.fd = 0xBADF00D;
ASSERT_EQ(hipFileHandleRegister(&fh, &rfd), HipFileOpError(hipFileIONotSupported));
}
TEST_F(HipFileHandle, register_handle_userspace_fs_not_supported)
{
hipFileHandle_t fh{};
hipFileDescr_t rfd{};
rfd.type = hipFileHandleTypeUserspaceFS;
rfd.handle.fd = 0xBADF00D;
ASSERT_EQ(hipFileHandleRegister(&fh, &rfd), HipFileOpError(hipFileIONotSupported));
}
// A type outside the enum's valid range must be rejected, not crash or invoke
// undefined behavior when loaded.
TEST_F(HipFileHandle, register_handle_invalid_type_not_supported)
{
hipFileHandle_t fh{};
hipFileDescr_t rfd{};
rfd.type = invalidEnum<hipFileFileHandleType_t>(maxEnum<hipFileFileHandleType_t>());
rfd.handle.fd = 0xBADF00D;
ASSERT_EQ(hipFileHandleRegister(&fh, &rfd), HipFileOpError(hipFileIONotSupported));
}
TEST_F(HipFileHandle, deregister_handle_internal_throws_if_not_registered)
{
ASSERT_THROW(Context<DriverState>::get()->deregisterFile(reinterpret_cast<hipFileHandle_t>(0xdeadbeef)),
FileNotRegistered);
}
TEST_F(HipFileHandle, deregister_handle_doesnt_throw_if_not_registered)
{
hipFileHandleDeregister(reinterpret_cast<hipFileHandle_t>(0xdeadbeef));
}
TEST_F(HipFileHandle, deregister_handle_internal)
{
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).build();
auto fh = Context<DriverState>::get()->registerFile(0xBADF00D);
Context<DriverState>::get()->deregisterFile(fh);
ASSERT_THROW(Context<DriverState>::get()->deregisterFile(fh), FileNotRegistered);
}
TEST_F(HipFileHandle, deregister_handle)
{
hipFileHandle_t fh{};
hipFileDescr_t rfd{};
rfd.type = hipFileHandleTypeOpaqueFD;
rfd.handle.fd = 0xBADF00D;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).build();
ASSERT_EQ(hipFileHandleRegister(&fh, &rfd), HIPFILE_SUCCESS);
hipFileHandleDeregister(fh);
hipFileHandleDeregister(fh);
}
TEST_F(HipFileHandle, deregister_handle_internal_fails_when_operations_are_oustanding)
{
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).build();
auto fh = Context<DriverState>::get()->registerFile(0xBADF00D);
{
auto file = Context<DriverState>::get()->getFile(fh);
ASSERT_THROW(Context<DriverState>::get()->deregisterFile(fh), FileOperationsOutstanding);
}
Context<DriverState>::get()->deregisterFile(fh);
}
TEST_F(HipFileHandle, deregister_handle_fails_when_operations_are_oustanding)
{
hipFileHandle_t fh{};
hipFileDescr_t rfd{};
rfd.type = hipFileHandleTypeOpaqueFD;
rfd.handle.fd = 0xBADF00D;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).build();
ASSERT_EQ(hipFileHandleRegister(&fh, &rfd), HIPFILE_SUCCESS);
{
auto file = Context<DriverState>::get()->getFile(fh);
hipFileHandleDeregister(fh);
}
hipFileHandleDeregister(fh);
}
TEST_F(HipFileHandle, UnregisteredFileCreatesOpensBufferedIfClientFdIsUnbuffered)
{
int open_fd{888888};
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(~0) // All flags, including O_DIRECT, set
.open_fd(open_fd)
.open_flags(~O_DIRECT) // All flags, excluding O_DIRECT, set
.build();
UnregisteredFile uf{777777};
EXPECT_CALL(msys, close(open_fd));
}
TEST_F(HipFileHandle, UnregisteredFileSetsCloseOnExecOnOpenedFile)
{
int open_fd{888888};
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(0)
.open_fd(open_fd)
.open_flags(O_DIRECT | O_CLOEXEC)
.build();
UnregisteredFile uf{777777};
EXPECT_CALL(msys, close(open_fd));
}
TEST_F(HipFileHandle, UnregisteredFileMaintainsCloseOnExecOnOpenedFile)
{
int open_fd{888888};
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT | O_CLOEXEC)
.open_fd(open_fd)
.open_flags(O_CLOEXEC)
.build();
UnregisteredFile uf{777777};
EXPECT_CALL(msys, close(open_fd));
}
TEST_F(HipFileHandle, UnregisteredFileOpensUnbufferedIfClientFdIsBuffered)
{
int open_fd{888888};
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(~O_DIRECT) // All flags, excluding O_DIRECT, set
.open_fd(open_fd)
.open_flags(~0) // All flags, including O_DIRECT, set
.build();
UnregisteredFile uf{777777};
EXPECT_CALL(msys, close(open_fd));
}
TEST_F(HipFileHandle, UnregisteredFileClosesOpenedFileWhenDestroyed)
{
int open_fd{888888};
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).open_fd(open_fd).build();
UnregisteredFile uf{777777};
EXPECT_CALL(msys, close(open_fd));
}
TEST_F(HipFileHandle, UnregisteredFilesUnbufferedFdIsNulloptIfOpenThrowsEinval)
{
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).fd_flags(~O_DIRECT).open_throws(EINVAL).build();
UnregisteredFile uf{777777};
ASSERT_EQ(uf.unbuffered_fd, nullopt);
}
TEST_F(HipFileHandle, UnregisteredFileConstructorThrowsOnErrOtherThanEinval)
{
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).fd_flags(~O_DIRECT).open_throws(EPERM).build();
ASSERT_THROW(UnregisteredFile{777777}, std::system_error);
}
#if defined(STATX_DIOALIGN)
TEST_F(HipFileHandle, UnregisteredFileDioMemAlignMatchesStatxDioMemAlign)
{
int open_fd{888888};
struct statx stxbuf {};
stxbuf.stx_mask = STATX_TYPE | STATX_MODE | STATX_DIOALIGN;
stxbuf.stx_dio_mem_align = 1234;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.open_fd(open_fd)
.statx(stxbuf)
.build();
UnregisteredFile uf{777777};
ASSERT_EQ(uf.m_dio_mem_align, 1234);
EXPECT_CALL(msys, close(open_fd));
}
#endif
#if defined(STATX_DIOALIGN)
TEST_F(HipFileHandle, UnregisteredFileDioOffsetAlignMatchesStatxDioOffsetAlign)
{
int open_fd{888888};
struct statx stxbuf {};
stxbuf.stx_mask = STATX_TYPE | STATX_MODE | STATX_DIOALIGN;
stxbuf.stx_dio_offset_align = 1234;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.open_fd(open_fd)
.statx(stxbuf)
.build();
UnregisteredFile uf{777777};
ASSERT_EQ(uf.m_dio_offset_align, 1234);
EXPECT_CALL(msys, close(open_fd));
}
#endif
TEST_F(HipFileHandle, UnregisteredFileDioMemAlignIsPageSizeIfStatxDoesntHaveDioAlign)
{
int open_fd{888888};
struct statx stxbuf {};
stxbuf.stx_mask = STATX_TYPE | STATX_MODE;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.open_fd(open_fd)
.statx(stxbuf)
.build();
UnregisteredFile uf{777777};
ASSERT_EQ(uf.m_dio_mem_align, 4096);
EXPECT_CALL(msys, close(open_fd));
}
TEST_F(HipFileHandle, UnregisteredFileDioOffsetAlignIsPageSizeIfStatxDoesntHaveDioAlign)
{
int open_fd{888888};
struct statx stxbuf {};
stxbuf.stx_mask = STATX_TYPE | STATX_MODE;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.open_fd(open_fd)
.statx(stxbuf)
.build();
UnregisteredFile uf{777777};
ASSERT_EQ(uf.m_dio_offset_align, 4096);
EXPECT_CALL(msys, close(open_fd));
}
TEST_F(HipFileHandle, UnregisteredFileDioMemAlignIsZeroIfUnableToOpenUnbufferedFd)
{
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).fd_flags(~O_DIRECT).open_throws(EINVAL).build();
UnregisteredFile uf{777777};
ASSERT_EQ(uf.m_dio_mem_align, 0);
}
TEST_F(HipFileHandle, UnregisteredFileDioOffsetAlignIsZeroIfUnableToOpenUnbufferedFd)
{
ExpectUnregisteredFileBuilder(msys, mlibmounthelper).fd_flags(~O_DIRECT).open_throws(EINVAL).build();
UnregisteredFile uf{777777};
ASSERT_EQ(uf.m_dio_offset_align, 0);
}
TEST_F(HipFileHandle, IsBlockDeviceReturnsTrueForBlockDevice)
{
int fd{0xBADF00D};
struct statx stxbuf {};
stxbuf.stx_mask = STATX_TYPE;
stxbuf.stx_mode = S_IFBLK;
// Return an eventfd as the file descriptor for the bufferd fd open so that when
// FileDescriptor calls close, it has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.statx(stxbuf)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_TRUE(file->isBlockDevice());
}
TEST_F(HipFileHandle, IsBlockDeviceReturnsFalseForRegularFile)
{
int fd{0xBADF00D};
struct statx stxbuf {};
stxbuf.stx_mask = STATX_TYPE;
stxbuf.stx_mode = S_IFREG;
// Return an eventfd as the file descriptor for the bufferd fd open so that when
// FileDescriptor calls close, it has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.statx(stxbuf)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_FALSE(file->isBlockDevice());
}
TEST_F(HipFileHandle, IsBlockDeviceReturnsFalseWhenStatxTypeNotAvailable)
{
int fd{0xBADF00D};
struct statx stxbuf {};
stxbuf.stx_mask = 0;
stxbuf.stx_mode = S_IFBLK;
// Return an eventfd as the file descriptor for the bufferd fd open so that when
// FileDescriptor calls close, it has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.statx(stxbuf)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_FALSE(file->isBlockDevice());
}
TEST_F(HipFileHandle, IsRegularFileReturnsTrueForRegularFile)
{
int fd{0xBADF00D};
struct statx stxbuf {};
stxbuf.stx_mask = STATX_TYPE;
stxbuf.stx_mode = S_IFREG;
// Return an eventfd as the file descriptor for the bufferd fd open so that when
// FileDescriptor calls close, it has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.statx(stxbuf)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_TRUE(file->isRegularFile());
}
TEST_F(HipFileHandle, IsRegularFileReturnsFalseForBlockDevice)
{
int fd{0xBADF00D};
struct statx stxbuf {};
stxbuf.stx_mask = STATX_TYPE;
stxbuf.stx_mode = S_IFBLK;
// Return an eventfd as the file descriptor for the bufferd fd open so that when
// FileDescriptor calls close, it has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.statx(stxbuf)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_FALSE(file->isRegularFile());
}
TEST_F(HipFileHandle, IsRegularFileReturnsFalseWhenStatxTypeNotAvailable)
{
int fd{0xBADF00D};
struct statx stxbuf {};
stxbuf.stx_mask = 0;
stxbuf.stx_mode = S_IFBLK;
// Return an eventfd as the file descriptor for the bufferd fd open so that when
// FileDescriptor calls close, it has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.statx(stxbuf)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_FALSE(file->isRegularFile());
}
TEST_F(HipFileHandle, OnExt4OrderedReturnsTrueForExt4Ordered)
{
int fd{0xBADF00D};
// Return an eventfd as the file descriptor for the bufferd fd open so that when
// FileDescriptor calls close, it has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
MountInfo mountinfo{};
mountinfo.type = FilesystemType::ext4;
mountinfo.options.ext4.journaling_mode = ExtJournalingMode::ordered;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.mountinfo(mountinfo)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_TRUE(file->onExt4Ordered());
}
TEST_F(HipFileHandle, OnExt4OrderedReturnsFalseForExt4Journal)
{
int fd{0xBADF00D};
// Return an eventfd as the file descriptor for the bufferd fd open so that when
// FileDescriptor calls close, it has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
MountInfo mountinfo{};
mountinfo.type = FilesystemType::ext4;
mountinfo.options.ext4.journaling_mode = ExtJournalingMode::journal;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.mountinfo(mountinfo)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_FALSE(file->onExt4Ordered());
}
TEST_F(HipFileHandle, OnExt4OrderedReturnsFalseForOtherFileSystem)
{
int fd{0xBADF00D};
// Return an eventfd as the file descriptor for the bufferd fd open so that when
// FileDescriptor calls close, it has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
MountInfo mountinfo{};
mountinfo.type = FilesystemType::other;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.mountinfo(mountinfo)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_FALSE(file->onExt4Ordered());
}
TEST_F(HipFileHandle, OnXfsReturnsTrueForXfs)
{
int fd{0xBADF00D};
// Return an eventfd as the file descriptor for the bufferd fd open so that when
// FileDescriptor calls close, it has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
MountInfo mountinfo{};
mountinfo.type = FilesystemType::xfs;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.mountinfo(mountinfo)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_TRUE(file->onXfs());
}
TEST_F(HipFileHandle, OnXfsReturnsFalseForOtherFileSystem)
{
int fd{0xBADF00D};
// Return an eventfd as the file descriptor for the bufferd fd open so that when
// FileDescriptor calls close, it has a valid file descriptor to close.
int open_fd{eventfd(0, 0)};
ASSERT_NE(open_fd, -1);
MountInfo mountinfo{};
mountinfo.type = FilesystemType::other;
ExpectUnregisteredFileBuilder(msys, mlibmounthelper)
.fd_flags(O_DIRECT)
.mountinfo(mountinfo)
.open_fd(open_fd)
.build();
auto fh{Context<DriverState>::get()->registerFile(fd)};
auto file{Context<DriverState>::get()->getFile(fh)};
EXPECT_FALSE(file->onXfs());
}
HIPFILE_WARN_NO_GLOBAL_CTOR_ON