diff --git a/src/fspp/fuse/Fuse.cpp b/src/fspp/fuse/Fuse.cpp index 117beeed..c1085bb2 100644 --- a/src/fspp/fuse/Fuse.cpp +++ b/src/fspp/fuse/Fuse.cpp @@ -102,7 +102,6 @@ int fusepp_flush(const char *path, fuse_file_info *fileinfo) { } int fusepp_fsync(const char *path, int datasync, fuse_file_info *fileinfo) { - printf("Fsync\n");fflush(stdout); return FUSE_OBJ->fsync(bf::path(path), datasync, fileinfo); } diff --git a/src/fspp/impl/Filesystem.h b/src/fspp/impl/Filesystem.h index f364083e..b86db240 100644 --- a/src/fspp/impl/Filesystem.h +++ b/src/fspp/impl/Filesystem.h @@ -12,6 +12,7 @@ class Filesystem { public: virtual ~Filesystem() {} + virtual int createAndOpenFile(const boost::filesystem::path &path, mode_t mode) = 0; virtual int openFile(const boost::filesystem::path &path, int flags) = 0; virtual void flush(int descriptor) = 0; virtual void closeFile(int descriptor) = 0; @@ -25,7 +26,6 @@ public: virtual void fsync(int descriptor) = 0; virtual void fdatasync(int descriptor) = 0; virtual void access(const boost::filesystem::path &path, int mask) = 0; - virtual int createAndOpenFile(const boost::filesystem::path &path, mode_t mode) = 0; virtual void mkdir(const boost::filesystem::path &path, mode_t mode) = 0; virtual void rmdir(const boost::filesystem::path &path) = 0; virtual void unlink(const boost::filesystem::path &path) = 0; diff --git a/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenErrorTest.cpp b/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenErrorTest.cpp new file mode 100644 index 00000000..6024dede --- /dev/null +++ b/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenErrorTest.cpp @@ -0,0 +1,37 @@ +#include "testutils/FuseCreateAndOpenTest.h" + +#include "fspp/impl/FuseErrnoException.h" + +using ::testing::WithParamInterface; +using ::testing::Values; +using ::testing::Return; +using ::testing::Throw; +using ::testing::StrEq; +using ::testing::_; + +using namespace fspp; + +class FuseCreateAndOpenErrorTest: public FuseCreateAndOpenTest, public WithParamInterface { +}; +INSTANTIATE_TEST_CASE_P(FuseCreateAndOpenErrorTest, FuseCreateAndOpenErrorTest, Values(EACCES, EDQUOT, EEXIST, EFAULT, EFBIG, EINTR, EOVERFLOW, EINVAL, EISDIR, ELOOP, EMFILE, ENAMETOOLONG, ENFILE, ENODEV, ENOENT, ENOMEM, ENOSPC, ENOTDIR, ENXIO, EOPNOTSUPP, EPERM, EROFS, ETXTBSY, EWOULDBLOCK, EBADF, ENOTDIR)); + +TEST_F(FuseCreateAndOpenErrorTest, ReturnNoError) { + ReturnDoesntExistOnLstat(FILENAME); + EXPECT_CALL(fsimpl, createAndOpenFile(StrEq(FILENAME), _)).Times(1).WillOnce(Return(1)); + //For the syscall to succeed, we also need to give an fstat implementation. + ReturnIsFileOnFstat(1); + + errno = 0; + int retval = CreateAndOpenFileAllowError(FILENAME, O_RDONLY); + EXPECT_EQ(errno, 0); + EXPECT_GE(retval, 0); +} + +TEST_P(FuseCreateAndOpenErrorTest, ReturnError) { + ReturnDoesntExistOnLstat(FILENAME); + EXPECT_CALL(fsimpl, createAndOpenFile(StrEq(FILENAME), _)).Times(1).WillOnce(Throw(FuseErrnoException(GetParam()))); + + int retval = CreateAndOpenFileAllowError(FILENAME, O_RDONLY); + EXPECT_EQ(retval, -1); + EXPECT_EQ(GetParam(), errno); +} diff --git a/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenFileDescriptorTest.cpp b/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenFileDescriptorTest.cpp new file mode 100644 index 00000000..95e5fa95 --- /dev/null +++ b/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenFileDescriptorTest.cpp @@ -0,0 +1,44 @@ +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "testutils/FuseCreateAndOpenTest.h" + +using ::testing::_; +using ::testing::StrEq; +using ::testing::WithParamInterface; +using ::testing::Values; +using ::testing::Return; + +class FuseCreateAndOpenFileDescriptorTest: public FuseCreateAndOpenTest, public WithParamInterface { +public: + void CreateAndOpenAndReadFile(const char *filename) { + auto fs = TestFS(); + + int fd = CreateAndOpenFile(fs.get(), filename); + ReadFile(fd); + } + +private: + int CreateAndOpenFile(const TempTestFS *fs, const char *filename) { + auto realpath = fs->mountDir() / filename; + int fd = ::open(realpath.c_str(), O_RDONLY | O_CREAT); + EXPECT_GE(fd, 0) << "Creating file failed"; + return fd; + } + void ReadFile(int fd) { + int retval = ::read(fd, nullptr, 0); + EXPECT_EQ(0, retval) << "Reading file failed"; + } +}; +INSTANTIATE_TEST_CASE_P(FuseCreateAndOpenFileDescriptorTest, FuseCreateAndOpenFileDescriptorTest, Values(0, 2, 5, 1000, 1024*1024*1024)); + +TEST_P(FuseCreateAndOpenFileDescriptorTest, TestReturnedFileDescriptor) { + ReturnDoesntExistOnLstat(FILENAME); + EXPECT_CALL(fsimpl, createAndOpenFile(StrEq(FILENAME), _)) + .Times(1).WillOnce(Return(GetParam())); + EXPECT_CALL(fsimpl, read(GetParam(), _, _, _)).Times(1).WillOnce(Return(0)); + //For the syscall to succeed, we also need to give an fstat implementation. + ReturnIsFileOnFstat(GetParam()); + + CreateAndOpenAndReadFile(FILENAME); +} diff --git a/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenFilenameTest.cpp b/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenFilenameTest.cpp new file mode 100644 index 00000000..40677260 --- /dev/null +++ b/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenFilenameTest.cpp @@ -0,0 +1,45 @@ +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "testutils/FuseCreateAndOpenTest.h" + +using ::testing::_; +using ::testing::StrEq; +using ::testing::Return; + +class FuseCreateAndOpenFilenameTest: public FuseCreateAndOpenTest { +public: +}; + +TEST_F(FuseCreateAndOpenFilenameTest, CreateAndOpenFile) { + ReturnDoesntExistOnLstat("/myfile"); + EXPECT_CALL(fsimpl, createAndOpenFile(StrEq("/myfile"), _)) + .Times(1).WillOnce(Return(0)); + //For the syscall to succeed, we also need to give an fstat implementation. + ReturnIsFileOnFstat(0); + + CreateAndOpenFile("/myfile", O_RDONLY); +} + +TEST_F(FuseCreateAndOpenFilenameTest, CreateAndOpenFileNested) { + ReturnIsDirOnLstat("/mydir"); + ReturnDoesntExistOnLstat("/mydir/myfile"); + EXPECT_CALL(fsimpl, createAndOpenFile(StrEq("/mydir/myfile"), _)) + .Times(1).WillOnce(Return(0)); + //For the syscall to succeed, we also need to give an fstat implementation. + ReturnIsFileOnFstat(0); + + CreateAndOpenFile("/mydir/myfile", O_RDONLY); +} + +TEST_F(FuseCreateAndOpenFilenameTest, CreateAndOpenFileNested2) { + ReturnIsDirOnLstat("/mydir"); + ReturnIsDirOnLstat("/mydir/mydir2"); + ReturnDoesntExistOnLstat("/mydir/mydir2/myfile"); + EXPECT_CALL(fsimpl, createAndOpenFile(StrEq("/mydir/mydir2/myfile"), _)) + .Times(1).WillOnce(Return(0)); + //For the syscall to succeed, we also need to give an fstat implementation. + ReturnIsFileOnFstat(0); + + CreateAndOpenFile("/mydir/mydir2/myfile", O_RDONLY); +} diff --git a/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenFlagsTest.cpp b/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenFlagsTest.cpp new file mode 100644 index 00000000..1b2ded24 --- /dev/null +++ b/src/test/fspp/fuse/createAndOpenFile/FuseCreateAndOpenFlagsTest.cpp @@ -0,0 +1,22 @@ +#include "testutils/FuseCreateAndOpenTest.h" + +using ::testing::_; +using ::testing::StrEq; +using ::testing::WithParamInterface; +using ::testing::Values; +using ::testing::Return; + +class FuseCreateAndOpenFlagsTest: public FuseCreateAndOpenTest, public WithParamInterface { +}; +INSTANTIATE_TEST_CASE_P(FuseCreateAndOpenFlagsTest, FuseCreateAndOpenFlagsTest, Values(O_RDWR, O_RDONLY, O_WRONLY)); + +//TODO Disabled because it doesn't seem to work. Fuse doesn't seem to pass flags to create(). Why? +TEST_P(FuseCreateAndOpenFlagsTest, DISABLED_testFlags) { + ReturnDoesntExistOnLstat(FILENAME); + EXPECT_CALL(fsimpl, createAndOpenFile(StrEq(FILENAME), OpenFlagsEq(GetParam()))) + .Times(1).WillOnce(Return(0)); + //For the syscall to succeed, we also need to give an fstat implementation. + ReturnIsFileOnFstat(0); + + CreateAndOpenFile(FILENAME, GetParam()); +} diff --git a/src/test/fspp/fuse/createAndOpenFile/testutils/FuseCreateAndOpenTest.cpp b/src/test/fspp/fuse/createAndOpenFile/testutils/FuseCreateAndOpenTest.cpp new file mode 100644 index 00000000..d354a931 --- /dev/null +++ b/src/test/fspp/fuse/createAndOpenFile/testutils/FuseCreateAndOpenTest.cpp @@ -0,0 +1,20 @@ +#include "FuseCreateAndOpenTest.h" + +using ::testing::_; + +int FuseCreateAndOpenTest::CreateAndOpenFile(const char *filename, int flags) { + int fd = CreateAndOpenFileAllowError(filename, flags); + EXPECT_GE(fd, 0); + return fd; +} + +int FuseCreateAndOpenTest::CreateAndOpenFileAllowError(const char *filename, int flags) { + auto fs = TestFS(); + + auto realpath = fs->mountDir() / filename; + return ::open(realpath.c_str(), flags | O_CREAT); +} + +void FuseCreateAndOpenTest::ReturnIsFileOnFstat(int descriptor) { + EXPECT_CALL(fsimpl, fstat(descriptor, _)).WillRepeatedly(ReturnIsFileFstat); +} diff --git a/src/test/fspp/fuse/createAndOpenFile/testutils/FuseCreateAndOpenTest.h b/src/test/fspp/fuse/createAndOpenFile/testutils/FuseCreateAndOpenTest.h new file mode 100644 index 00000000..6997bab3 --- /dev/null +++ b/src/test/fspp/fuse/createAndOpenFile/testutils/FuseCreateAndOpenTest.h @@ -0,0 +1,21 @@ +#pragma once +#ifndef TEST_FSPP_FUSE_OPENFILE_TESTUTILS_FUSECREATEANDOPENTEST_H_ +#define TEST_FSPP_FUSE_OPENFILE_TESTUTILS_FUSECREATEANDOPENTEST_H_ + +#include "test/testutils/FuseTest.h" + +class FuseCreateAndOpenTest: public FuseTest { +public: + const char *FILENAME = "/myfile"; + + int CreateAndOpenFile(const char *FILENAME, int flags); + int CreateAndOpenFileAllowError(const char *FILENAME, int flags); + void ReturnIsFileOnFstat(int descriptor); +}; + +MATCHER_P(OpenFlagsEq, expectedFlags, "") { + printf("%d vs %d\n", expectedFlags, O_ACCMODE & arg); + return expectedFlags == (O_ACCMODE & arg); +} + +#endif